dialogue_state = {
    # current context should be set to an act that is currently taking place
    'current_context' : None,
    # topics will be an array of dicts structured similar to this
    # {'act': 'notifications', 'slots': [('time_when', None), ('liczba', ''), ('timeunit', None)]}
    'topics': [],
    # facts is a dict of contextual data such as selected repo and a timeframe
    'facts': {
        'repo' : None,
        'time': None
    },
    'counter': 0
}

def add_fact(key, value):
    global dialogue_state
    dialogue_state['facts'][key] = value


def monitor_stanu_dialogowego(frame):
    not_pivot_acts = ['time',
    'repo',
    'howmany']
    global dialogue_state
    # Some frames can reset the dialogue state, like saying hello.

    incr_counter(dialogue_state)

    # Discarding acts that were not identified properly, but lets keep increasing the counter
    if frame['act'] == 'null':
        return dialogue_state

    reset_state_if_needed(frame, dialogue_state)
    if frame['act'] not in not_pivot_acts:
        dialogue_state['current_context'] = frame['act']
    append_or_merge_frame(frame, dialogue_state)

    return dialogue_state


def append_or_merge_frame(frame, dialogue_state):
    act = frame['act']
    act_from_state = list(filter(lambda x: x['act'] == act, dialogue_state['topics']))
    if len(act_from_state) > 0:
        append_or_merge_slots(frame['slots'], act_from_state[0]['slots'])
    else:
        dialogue_state['topics'].append(frame)


def update_facts_if_needed(slot):
    global dialogue_state

    if slot != None and len(slot) > 1:
        if slot[1] is None or slot[1] == '':
            return

        if slot[0] == 'repo':
            dialogue_state['facts']['repo'] = slot[1]
        elif slot[0] == 'time':
            dialogue_state['facts']['time'] = slot[1]


def append_or_merge_slots(frame_slots, state_slots):
    """
    This function expects both parameters to be an array
    of tuples (slot_name, slot_value), and will merge
    frame slots into state_slots (on unique slot names).
    """
    for frame_slot in frame_slots:
        merged = False
        for i in range(len(state_slots)):
            if len(frame_slot) > i:
                update_facts_if_needed(frame_slot[i])
                if state_slots[i][0] == frame_slot[0]:
                    merged = True
                    # Do not merge empty incomming slots
                    if frame_slot[1] is not None and not len(frame_slot[1]) == 0:
                        state_slots[i] = frame_slot
                    break

        if not merged:
            state_slots.append(frame_slot)


def incr_counter(dialogue_state):
    current_val = dialogue_state['counter']
    dialogue_state['counter'] = current_val + 1

def reset_state_if_needed(frame, dialogue_state):
    if frame['act'] == "hello" or frame['act'] == "bye":
        dialogue_state['topics'] = []
        dialogue_state['counter'] = 0
        # should we reset 'facts' aswell?