import sys
from datetime import datetime
from ..errors import *
from ..parse_rules import parse_rules
import cardsharp as cs

from ..util import check_file
from ..segment import segment_dict

__all__ = ['get_rules', 'run_rules']

def _create_task(segment, var, converter):
    """Helper function to create and return a task. Takes a segment name (str),
    a variable name (str) within that segment and a field converter 
    (object *created in parse_rules*). The task does the following, 
    for each row apply the translate function in the field converter object
    to the given variable."""
    region_var = segment_dict[segment]['region_var'].lower()
    def task(row):
        row[var] = converter.translate(region_var, row[var], row)

    return task

def get_rules(rule_list, segment, **opt):
    try:
        print "Loading Rules...."
        rules = {}
        for key in rule_list:
            r = '%s_%s' % (opt['rules'], key)
            check_file(r, as_dir = True)
            rules[key] = parse_rules(r, segment, **opt)
        
        print "Rules loaded."
        return rules
    
    except RuleParsingError as ex:
        print ex
        print "Aborting rule parsing and terminating program."
        sys.exit(1)
    
#TODO set lengths on variables that were assigned max length based 
#on their size
def run_rules(rules_list, rules, seg, segment_name):
    #TODO: make converter map to make only 1 iteration over dataset
    #apply process rules
    for key in rules_list:
        print "Running %s rule phase %s at %s..." % (key, seg.phase, datetime.now().isoformat(' '))
        
        for var in seg.ds.variables:
            #get the conversion rules associated with segment 
            #and variable name
            
            converter = rules[key].get((segment_name, var.name))
            
            #if a rule exists for segment_name, var.name
            if converter:
                print "Running %s at %s..." % (var, datetime.now().isoformat(' '))
                #set the output format
                converter.set_format(var.format)
                
                #create a task on the dataset for a given segment and 
                #variable the task will use the converter to do 
                #data conversions
                seg.ds.add_task(_create_task(segment_name, var, converter))
                
                #TODO move this out to phase level. First need to check that this will not impact
                #rules processing on a row
                cs.wait()
                print "complete at %s." % datetime.now().isoformat(' ')
    
