#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Helper script to generate resource classes from 
bacula c definitions.

Usage:
c2py_resource.py BACULA_SRC_PATH 
"""
#    RESOURCE_TYPE has to be either 'dird', 'console', 'filed' or 'stored'
#    CONF_C_FILE is the corresponding c source e.g. 'dird/dird_conf.c'
#"""

C_CONFS = (
           ("dird", "dird_conf.c"),
           ("console", "console_conf.c"),
           ("filed", "filed_conf.c"),
           ("stored", "stored_conf.c"),
           )


import sys
import os
import re
from directive import *
from resource import Resource
import pprint

RXP_RESOURCE = re.compile(r'''
    ^(?:static\s+)?RES_ITEM\s+
    (?P<name>[^[]+)\[\]\s+=\s+\{\s*\n # First line with starting brace
    (?P<items>.*?)                    # Non greedy search
    \n}\s*;
''', re.M|re.X|re.S)

RXP_ITEM = re.compile(r'''
    ^\s+{"(?P<name>[^"]+)"\s*,
    \s*(?P<handler>[^,]+)\s*,
    \s*(?P<value>[^,]+)\s*,
    \s*(?P<code>[^,]+)\s*,
    \s*(?P<flags>[^,]+)\s*,
    \s*(?P<default_value>[^}]+)},?\s* 
''', re.X)

# handler to python type wrapping
CONF2TYPE = {
    'store_bool'    : bool,
    'store_pint32'  : int,
    'store_str'     : str,
    'store_name'    : str,
    'store_dir'     : Path,
    'store_password': Password,
    'store_time'    : Time,
    'store_bit'     : bool,
    'store_size'    : int,
    'store_acl'     : Acl,
    'store_strname' : str,
    'store_res'     : Res
    }

def parse_conf_c(filename):
    """parce a bacula c file for resoure item definitions"""
    cfg = {}
    cf = open(filename).read()
    for block in RXP_RESOURCE.finditer(cf):
        bl = cfg[block.group("name")] = {}
        for line in block.group("items").split('\n'):
            m = RXP_ITEM.search(line)
            if not m: continue
            item = m.groupdict()
            bl[item.pop("name")] = item
    return cfg

def directives(daemon, conf):
    res = conf.keys()
    res.sort()
    for r in res:
        items = []        
        for i, v in conf[r].iteritems():
            name = i
            if v["flags"] == "ITEM_DEFAULT":
                default = v["default_value"]
            else:
                default = None
            type = CONF2TYPE.get(v["handler"], v["handler"])
            required = v["flags"] == "ITEM_REQUIRED"           
            items.append(Item(name, default, type, required))
        items.sort()
        print "%s_%s = %s\n" % (daemon, r, pprint.pformat(items, 2))
        print "\n".join([str(i) for i in items])    

if __name__ == "__main__":
    try:
        bacula_src = sys.argv[1]
    except:
        raise(__doc__)

    rsc = []

    for daemon, conf in C_CONFS:
        filename = os.path.join(bacula_src, daemon, conf)
        directives(daemon, parse_conf_c(filename))


