from abc import ABC, abstractmethod
import os

def fix_action_name(a):
    assert a.startswith("(") and a.endswith(")")
    return "(" + " ".join([x.strip() for x in a[1:-1].split(" ") if len(x) > 0]) + ")"

def str_remove_before_first_parentheses(s):
    if s.startswith("("):
        return s
    try:
        return s[s.index("("):]
    except:
        return ""

def str_remove_after_last_parentheses(s):
    if s.endswith(")"):
        return s

    i = s.rfind(")")

    if i == -1:
        return ""
    return s[:i+1]

def cleanup_answer(ans):
    if isinstance(ans, str):
        ans = str_remove_before_first_parentheses(ans)
        ans = str_remove_after_last_parentheses(ans)
        ans = ans.lower()
        ans = ans.replace(")\n(", ")######(").replace("),(", ")######(").replace(") (", ")######(").split("######")
        return ans
    if isinstance(ans, list):
        res = []
        for x in ans:
            res.extend(cleanup_answer(x))
        return res

def set_equal(ans1, ans2):
    return set(ans1) == set(ans2)

def jaccard_similarity(ans1, ans2):
    s1, s2 = set(ans1), set(ans2)
    # assert (len(s2) == len(ans2))
    return float(len(s1 & s2)) / len(s1 | s2) 


def skewed_jaccard_similarity(ans1, ans2):
    # Non-symmetric - ans1 is assumed to be the correct one
    # If ans2 - ans1 not empty, return 0 (hallucination)
    # Otherwise, return Jaccard.
    s1, s2 = set(ans1), set(ans2)
    if len(s2-s1) > 0:
        return 0.0
    return float(len(s1 & s2)) / len(s1 | s2) 

class BaseEvaluator(ABC):
    def __init__(self) -> None:
        self.scores = []

    @abstractmethod
    def get_score(self, ans, doc):
        pass

    def add_scores(self, scores):
        self.scores.extend(scores)
    
    def get_avg_score(self):
        avg_score = sum(self.scores)/len(self.scores)
        return avg_score