from typing import Counter


def build_vocab_from_text_file(
    file_path, keep_tokens=("<pad>", "<unk>", "<sos>", "<eos>"), 
    freq_threshold=3, stop_words=(" ",), tokenizer=lambda x: list(x),
):
    """Build vocab from a text file.

    Args:
        file_path (str): text file path
        keep_tokens (tuple, optional): preset tokens. 
            Defaults to ("<pad>", "<unk>", "<sos>", "<eos>").
        freq_threshold (int, optional): word frequency limition. Defaults to 3.
        stop_words (iterable[str], optional): stop words that we don't want
            keep in vocab. Defaults to (" ",).
        tokenizer (callable): tokenizer.

    Returns:
        tuple: (str_to_idx: dict, idx_to_str: dict)
    """
    word_counter = Counter()
    
    with open(file_path, 'r') as frd:
        for line in frd.readlines():
            word_counter.update(Counter(tokenizer(line.strip())))

    # remove stop words
    if stop_words:
        for word in stop_words:
            if word in word_counter:
                word_counter.pop(word)
    
    str_to_idx = {}
    idx_to_str = {}
    cnt = 0
    
    for token in keep_tokens:
        str_to_idx[token] = cnt
        idx_to_str[cnt] = token
        cnt += 1
        
    for word, freq in word_counter.items():
        # filter words with frequency less than threshold
        if freq < freq_threshold:
            continue
        str_to_idx[word] = cnt
        idx_to_str[cnt] = word
        cnt += 1

    return str_to_idx, idx_to_str