"""
Хеш-таблица

Хранится как список buckets фиксированной длины,
каждый элемент — голова связного списка (или None).
"""

from task1.structures.LinkedList import *

def hash_fun(name: str, size: int) -> int:
    """Принимает имя и возвращает индекс бакета для него."""
    if size <= 0:
        raise ValueError("size должен быть больше 0")
    
    hashSum = 0
    n = size+1
    base = 1103 # ord('я')
    for letter in name:
        hashSum += ord(letter) * pow(base, n)
        n -= 1
    return int(hashSum) % size

def ht_insert(buckets: list|None, name: str, phone: str, blen:int = 50) -> list:
    """Возвращает новый массив бакетов
    Вычисляет индекс, вызывает ll_insert для соответствующего бакета.
    Функция не меняет размер массива бакетов автоматически!"""
    if buckets == [] or buckets == None:
        buckets = [None] * blen
        # raise ValueError("Длинна buckets должна быть больше 0")

    size = len(buckets)
    index = hash_fun(name, size)
    buckets[index] = ll_insert(buckets[index], name, phone)
    return buckets

def ht_delete(buckets: list, name: str) -> list:
    """Возвращает новый массив бакетов без элемента с именем name"""
    if buckets == []:
        raise ValueError("Длинна buckets должна быть больше 0")

    size = len(buckets)
    index = hash_fun(name, size)
    buckets[index] = ll_delete(buckets[index], name)
    return buckets

def ht_find(buckets: list|None, name: str) -> str|None:
    if buckets == [] or buckets == None:
        raise ValueError("Длинна buckets должна быть больше 0")

    size = len(buckets)
    index = hash_fun(name, size)
    return ll_find(buckets[index], name)

def ht_list_all(buckets):
    """Собирает все записи из всех бакетов и сортирует"""
    allRecords = []
    for bucket in buckets:
        allRecords.extend(ll_list_all(bucket))
    return sorted(allRecords, key=lambda x: x[0])