import os

import yaml

__all__ = ['IDAssign']


class IDAssign(object):

    def __init__(self, path: str):
        self._path = path
        self._mapping = {'': 0}  # by default let 0 == '' (a NULL item)

        if os.path.isfile(path):
            with open(path, 'r', encoding='utf-8') as f:
                self._mapping = yaml.safe_load(f.read())

        if self._mapping:
            self._next_index = max(self._mapping.values()) + 1
            self._rev_mapping = {v: k for k, v in self._mapping.items()}
        else:
            self._next_index = 0
            self._rev_mapping = {}

    def __len__(self):
        return self._next_index

    def __getitem__(self, key):
        return self._mapping[key]

    @property
    def path(self) -> str:
        return self._path

    def dump_to(self, path: str):
        cnt = yaml.safe_dump(self._mapping)
        with open(path, 'w', encoding='utf-8') as f:
            f.write(cnt)

    def get_or_assign(self, key: str):
        ret = self._mapping.get(key, None)
        if ret is None:
            self._mapping[key] = ret = self._next_index
            self._rev_mapping[ret] = key
            self._next_index += 1
        return ret

    def rev(self, index: int):
        return self._rev_mapping[index]

    def get(self, key: str):
        return self._mapping.get(key, None)

    def flush(self):
        self.dump_to(self._path)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.flush()
