# Author: Michelle Liu
# Class: CS 261
# Date: 6/10/2020
# word_count.py
# ===================================================
# Implement a word counter that counts the number of
# occurrences of all the words in a file. The word
# counter will return the top X words, as indicated
# by the user.
# ===================================================

import re
from hash_map import HashMap

"""
This is the regular expression used to capture words. It could probably be endlessly
tweaked to catch more words, but this provides a standard we can test against, so don't
modify it for your assignment submission.
"""
rgx = re.compile("(\w[\w']*\w|\w)")


def hash_function_2(key):
    """
    This is a hash function that can be used for the hashmap.
    """

    hash = 0
    index = 0
    for i in key:
        hash = hash + (index + 1) * ord(i)
        index = index + 1
    return hash


def top_words(source, number):
    """
    Takes a plain text file and counts the number of occurrences of case insensitive words.
    Returns the top `number` of words in a list of tuples of the form (word, count).

    Args:
        source: the file name containing the text
        number: the number of top results to return (e.g. 5 would return the 5 most common words)
    Returns:
        A list of tuples of the form (word, count), sorted by most common word. (e.g. [("a", 23), ("the", 20), ("it", 10)])
    """

    keys = set()

    ht = HashMap(2500, hash_function_2)

    # This block of code will read a file one word as a time and
    # put the word in `w`. It should be left as starter code.
    with open(source) as f:
        for line in f:
            words = rgx.findall(line)
            for w in words:
                # if a link with the key w exists in the table, update increment its value
                if ht.contains_key(w.lower()):
                    ht.put(w.lower(), ht.get(w.lower()) + 1)
                # otherwise add w to the hash table as a new link with count of 1
                else:
                    ht.put(w.lower(), 1)

    # call the list_of_links() method of the hash table to get a list of tuples of all links in the table
    word_list = ht.list_of_links()

    # sort the list of tuples from highest to lowest according to count
    word_list.sort(key=get_count, reverse=True)

    # return the first however many words requested by the user in a list of tuples
    return word_list[:number]


def get_count(element):
    """
    Returns the second element of a tuple
    """
    return element[1]

# print(top_words("alice.txt",10))  # COMMENT THIS OUT WHEN SUBMITTING TO GRADESCOPE
