from visitor import Visitor

def jsonstr(s):
    return '"%s"' % s

def empty(s):
    return None

class ModelVisitor(Visitor):
    def __init__(self, args):
        Visitor.__init__(self, args)
        self.constructors = []
        self.free_id = 0
        self.name_maps = {}
        self.current_model = None
        self.current_element = None

    def dump(self):
        print(self.constructors)
        return self.constructors

    def __getattr__(self, attr):
        if attr.startswith("visit_"):
            return empty
        else:
            raise AttributeError()

    def visit_start(self, tree):
        self.constructors.append('"model"')
        for t in tree.get_tail():
            self.visit(t)
        self.constructors.append('"exit"')

    def visit_import(self, tree):
        url = tree.get_children("MV_URL")[0]
        target = tree.get_children("MODEL_ID")[0]
        self.constructors.extend(['"import_node"', jsonstr(url.get_text()), jsonstr(target.get_text())])

    def visit_export(self, tree):
        url = tree.get_children("MV_URL")[0]
        target = tree.get_children("MODEL_ID")[0]
        self.constructors.extend(['"export_node"', jsonstr(target.get_text()), jsonstr(url.get_text())])

    def visit_model(self, tree):
        children = tree.get_children("MODEL_ID")
        model_type = children[0].get_text()
        model_name = children[1].get_text()
        self.constructors.extend(['"instantiate_model"', jsonstr(model_type), jsonstr(model_name)])
        self.constructors.extend(['"define_inheritance"', jsonstr(model_name), jsonstr("Inheritance")])
        self.current_model = model_name
        for element in tree.get_children("model_element"):
            self.visit(element)

    def visit_model_element(self, tree):
        children = tree.get_children("MODEL_ID")
        element_type = children[0].get_text()
        if len(children) == 2 or len(children) == 4:
            element_name = children[1].get_text()
        else:
            element_name = ""

        if len(children) > 2:
            # So we have a source and target; but aren't sure which is which, because the name is optional!
            source_name = children[-2].get_text()
            target_name = children[-1].get_text()
            self.constructors.extend(['"instantiate_link"', jsonstr(self.current_model), jsonstr(element_type), jsonstr(element_name), jsonstr(source_name), jsonstr(target_name)])
        else:
            self.constructors.extend(['"instantiate_node"', jsonstr(self.current_model), jsonstr(element_type), jsonstr(element_name)])
        self.current_element = element_name
            
        for attr in tree.get_children("model_attribute"):
            self.visit(attr)

    def visit_model_attribute(self, tree):
        children = tree.get_children("MODEL_ID")
        is_definition = bool(tree.get_children("COLON"))

        if is_definition:
            # is definition
            attr_name = children[0].get_text()
            attr_type = children[1].get_text()
            self.constructors.extend(['"instantiate_link"', jsonstr(self.current_model), jsonstr("Association"), jsonstr(self.current_element + "_" + attr_name), jsonstr(self.current_element), jsonstr(attr_type)])
            self.constructors.extend(['"instantiate_attribute"', jsonstr(self.current_model), jsonstr(self.current_element + "_" + attr_name), jsonstr("name"), jsonstr(attr_name)])
        else:
            # is assign
            attr_name = children[0].get_text()
            attr_value = tree.get_children("value")[0]
            self.constructors.extend(['"instantiate_attribute"', jsonstr(self.current_element), jsonstr(attr_name), jsonstr(attr_value.get_text()) if attr_value.head == "STRVALUE" else attr_value.get_text()])
