import string
from primitives_visitor import PrimitivesVisitor
from cached_exception import CachedException

import urllib
import urllib2
import json

class PrimitivesObjectVisitor(PrimitivesVisitor):
    def __init__(self, args):
        PrimitivesVisitor.__init__(self, args)

        self.username = args[0]
        self.obj_file = args[1]
        self.real_file = args[2]
        self.address = args[3]

        self.object_symbols = {}

        with open(self.real_file, 'r') as f:
            import hashlib
            md5 = hashlib.md5()
            md5.update(f.read())
        self.hash_file = md5.hexdigest()

        # Create user
        urllib2.urlopen(urllib2.Request(self.address, urllib.urlencode({"op": "set_input", "value": '"%s"' % self.username, "username": "user_manager"}))).read()

        simple_filename = self.real_file.rsplit("/")[-1]
        print("[COMPILE] %s" % simple_filename)

    def dump(self):
        v = PrimitivesVisitor.dump(self)
        data = []

        # Set up interface
        data = [3, "upload", self.obj_file, self.hash_file, False]

        # Start uploading the code
        data.append(v)

        # Upload symbol table
        for e, v in self.object_symbols.iteritems():
            data.extend([True, e, v])

        # Finish the symbol table
        data.append(False)

        # Wait for kernel to signal that it finished
        data.append(2)

        urllib2.urlopen(urllib2.Request(self.address, urllib.urlencode({"op": "set_input", "data": json.dumps(data), "username": self.username}))).read()
        v = urllib2.urlopen(urllib2.Request(self.address, urllib.urlencode({"op": "get_output", "username": self.username}))).read()
        v = json.loads(v)
        if v == "DONE":
            return True
        else:
            return False

    def visit_definition(self, tree):
        for a in tree.get_children("ID"):
            name = a.get_tail()[0]
            self.object_symbols[name] = True
            return PrimitivesVisitor.visit_definition(self, tree)

    def visit_vardecl(self, tree):
        if len(tree.get_tail()) > 2:
            for a in tree.get_children("ID"):
                name = a.get_tail()[0]
                self.object_symbols.setdefault(name, False)
                return PrimitivesVisitor.visit_vardecl(self, tree)
        else:
            return PrimitivesVisitor.visit_vardecl(self, tree)

    def visit_funcdecl(self, tree):
        for a in tree.get_children("func_name"):
            for b in a.get_children("ID"):
                name = b.get_tail()[0]
                if tree.get_children("func_body") or tree.get_children("ASSIGN"):
                    self.object_symbols[name] = True
                else:
                    self.object_symbols.setdefault(name, False)
                return PrimitivesVisitor.visit_funcdecl(self, tree)
