import json


class _Field(dict):

    def __init__(self, request_json={}):
        super(_Field, self).__init__(request_json)
        for key, value in request_json.items():
            if isinstance(value, dict):
                value = _Field(value)
            self[key] = value

    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)


class Entity():
    """docstring for Entity"""

    def __init__(self, name):
        self.name = name
        self.entries = []

    def add_entry(self, value, synonyms=[]):
        # import ipdb; ipdb.set_trace()
        entry = {'value': value, 'synonyms': synonyms}
        self.entries.append(entry)
        # self.entries[value] = synonyms

    def add_synonyms(self, entry, synonyms):
        self.entries[entry].extend(synonyms)

    @property
    def serialize(self):
        return json.dumps(self.__dict__)

    def __repr__(self):
        return '@' + self.name




class Intent():
    """Represents an Intent object within the API.AI REST APi.

    Intents are created internally using an Assistant app's action decorated view functions
    These objects provide the JSON schema for registering, updating, and removing intents in
    the API.AI develoepr console via JSON requests.
    """

    def __init__(self, name, priority=500000, fallback_intent=False):

        self.name = name
        self.auto = True
        self.contexts = None
        self.templates = []
        self.userSays = []
        self.responses = []
        self.priority = priority
        self.fallbackIntent = fallback_intent
        self.webhookUsed = True
        self.webhookForSlotFilling = True
        self.events = []
        self.id = None

    def registered(self):
        if self.id:
            return True


    def add_example(self, phrase, templ_entity_map=None):  # TODO
        if templ_entity_map:
            example = UserDefinedExample(phrase, templ_entity_map)
        else:
            example = AutoAnnotedExamle(phrase)

        self.userSays.append(example.serialize)

    def add_action(self, action_name, parameters=[]):
        self.responses = [{
            'action': action_name,
            'resetContexts': False,
            'affectedContexts': [],  # TODO: register context outs
            'parameters': parameters,
            'messages': []  # TODO: possibly register action responses to call from intent object directly
        }]
        # self.responses.append(new_response)

    @property
    def serialize(self):
        return json.dumps(self.__dict__)

    def update(self, intent_json):
        self.__dict__.update(json.loads(intent_json))
        return self._update


class ExampleBase(object):
    """docstring for ExampleBase"""

    def __init__(self, phrase, user_defined=False, isTemplate=False):

        self.text = phrase
        self.userDefined = user_defined
        self.isTemplate = isTemplate
        self.data = []

    @property
    def serialize(self):
        return {
            'data': self.data,
            'isTemplate': self.isTemplate,
            'count': 0
        }


class AutoAnnotedExamle(ExampleBase):

    def __init__(self, phrase):
        super(AutoAnnotedExamle, self).__init__(phrase)
        self.text = phrase
        self.data.append({'text': self.text, 'userDefined': False})


class UserDefinedExample(ExampleBase):

    def __init__(self, phrase, entity_map):
        super(UserDefinedExample, self).__init__(phrase, user_defined=True)
        # import ipdb; ipdb.set_trace()
        self.entity_map = entity_map

        self.parse_phrase()

    def parse_phrase(self):
        # import ipdb; ipdb.set_trace()
        annotated = {}
        sub_phrase = ''

        for word in self.text.split():
            if word in self.entity_map:
                self.data.append({'text': sub_phrase})  # add non-annotated, then deal with annotation
                sub_phrase = ''
                self.annotate_params(word)

            else:
                sub_phrase += '{} '.format(word)

        if sub_phrase:
            self.data.append({'text': sub_phrase})

    def annotate_params(self, word):
        """Annotates a given word for the UserSays data field of an Intent object.
        
        Annotations are created using the entity map within the user_says.yaml template.
        """
        annotation = {}
        annotation['text'] = word
        annotation['meta'] = '@' + self.entity_map[word]
        annotation['alias'] = self.entity_map[word].strip('sys.')
        annotation['userDefined'] = True
        self.data.append(annotation)


@@ -10,421 +10,8 @@
 on%0A%0A
-%0Aclass _Field(dict):%0A%0A    def __init__(self, request_json=%7B%7D):%0A        super(_Field, self).__init__(request_json)%0A        for key, value in request_json.items():%0A            if isinstance(value, dict):%0A                value = _Field(value)%0A            self%5Bkey%5D = value%0A%0A    def __getattr__(self, attr):%0A        return self.get(attr)%0A%0A    def __setattr__(self, key, value):%0A        self.__setitem__(key, value)%0A%0A%0A
 clas
@@ -1055,20 +1055,18 @@
 texts = 
-None
+%5B%5D
 %0A       
@@ -4149,20 +4149,26 @@
 rd%5D.
-strip
+replace
 ('sys.'
+, ''
 )%0A  

replace instead of strip