/*
 * Name: Owen Sullivan
 * Date Submitted: 10/10/22
 * Lab Section: 006
 * Assignment Name: Lab 5: Spell Checker Using a Hash Table
*/

#include "stringset.h"

Stringset::Stringset() : table(4), num_elems(0), size(4) {}

// Used in test cases and testStringset() in main.cpp, do not modify
vector<list<string>> Stringset::getTable() const {
    
    return table;

}

// Used in test cases and testStringset() in main.cpp, do not modify
int Stringset::getNumElems() const {
    
    return num_elems;

}

// Used in test cases and testStringset() in main.cpp, do not modify
int Stringset::getSize() const {
    
    return size;

}

void Stringset::insert(string word) {
    
    // If the word already exists in the hash table, return early
    if (find(word)) {

        return;

    }

    // Create a hash object
    hash<string> stringHash;

    // If the number of elements in the hash table is equal to the
    // hash table size
    if (num_elems == size) {

        // Double the size
        size = size * 2;
        
        // Create a new vector with the new size
        vector<list<string>> newTable(size);

        // Loop through the linked lists in the hash table
        for (list list : table) {

            // Loop through the strings in the current linked list
            for (string value : list) {

                // Hash the current string with the new size
                int newLocation = stringHash(value) % size;

                // Insert the current string at the new hash location
                newTable.at(newLocation).push_back(value);

            }

        }

        // Set the original hash table equal to the new table
        table = newTable;

    }

    // Hash the input string with the hash table size
    int insertLocation = stringHash(word) % size;

    // Insert the input string at the hash location
    table.at(insertLocation).push_back(word);

    // Increment num_elems
    num_elems++;

}

bool Stringset::find(string word) const {
    
    // Create a hash object
    hash<string> stringHash;

    // Hash the input string with the hash table size
    int findLocation = stringHash(word) % size;

    // Loop through the strings in the linked list at the hash location
    for (string value : table.at(findLocation)) {

        // If the string is equal to the input string, return true
        if (value == word) {

            return true;

        }

    }

    // If a match hasn't been found in the hash table, return false
    return false;

}

void Stringset::remove(string word) {
    
    // If the input string isn't in the hash table, return early
    if (!find(word)) {

        return;

    }

    // Create a hash object
    hash<string> stringHash;

    // Hash the input string with the hash table size
    int removeLocation = stringHash(word) % size;

    // Remove the input string from the hash table
    table.at(removeLocation).remove(word); // remove can be used because only
                                           // one instance of the input string
                                           // will exist in the hash table

    // Decrement num_elems
    num_elems--;

}