from collections import namedtuple

# Melissa
import actions_db

order_match_factor = 1.5


def query(text):
    """
    Processes the text against the words.sqlite DB to identify
    which module and function can be best applied.

    Arguments:
    text -- user input, typically speech
    """

    text_list = text.split()  # Make a list of expression words

    # Make a list of lists where each sublist has an expression
    # word and its sequence in the expression.
    zlist = zip(text_list, list(range(len(text_list))))

    # Clear the expression table for each new user expression.
    actions_db.cur.execute('DELETE FROM expression')

    # Insert expression words in to SQLite. A word may appear more
    # than once in the expression. Only the first occurence will
    # be kept.
    actions_db.cur.executemany("INSERT OR IGNORE INTO expression "
                               "values (?,?)", zlist)
    actions_db.con.commit()

    # Match multiple-word groups against the expression words.
    sql = "SELECT e.word, e.word_order, "\
        + "  g.word_group, g.word_count, g.function "\
        + "FROM expression e "\
        + "JOIN words w "\
        + "ON w.word = e.word "\
        + "JOIN word_groups g "\
        + "ON g.word_group = w.word_group "\
        + "WHERE g.word_count > 1 "\
        + "ORDER BY e.word_order, g.word_group"

    actions_db.cur.execute(sql)
    rows = actions_db.cur.fetchall()

    # Make the following easier to read using namedtuple.
    sql_row_def = namedtuple('sql_row_def', 'word, word_order, word_group, word_count, function') # noqa
    scoring = {}
    for row in rows:
        sql_row = sql_row_def._make(row)
        if not sql_row.word_group in scoring: # noqa
            # If the word_group is not already in the scoring
            # dictionary ...

            # Split word_group on spaces into a words list.
            group_list = sql_row.word_group.split()

            # If the row word is the first word in the group_list
            # set order to 1. 'order' checks to see if the words
            # in the word_group are matched in expression order.
            order = 1 if sql_row.word == group_list[0] else 0
            scoring[sql_row.word_group] = {
                'group': group_list,
                'score': 0.0,
                'count': sql_row.word_count,
                'matched': 1,
                'order': order,
                'function': sql_row.function
            }
        else:
            # Update word_group already in the dictionary for
            # total words in the matched group.
            scoring_row = scoring[sql_row.word_group]
            scoring_row['matched'] += 1

            # And if the row word matches the next group word in
            # order, add 1 to order.
            if sql_row.word ==\
                    scoring_row['group'][scoring_row['order']]:
                scoring_row['order'] += 1