import json
from pathlib import Path
from typing import Any, List, Optional, Set

from sziszapangma.integration.repository.experiment_repository import ExperimentRepository


class MultiFilesExperimentRepository(ExperimentRepository):
    _root_directory: str
    _experiment_name: str

    def __init__(self, root_directory: str, experiment_name: str):
        self._root_directory = root_directory
        self._experiment_name = experiment_name

    def initialise(self) -> None:
        if not Path(self._root_directory).exists():
            Path(self._root_directory).mkdir()
        return

    def property_exists(self, record_id: str, property_name: str) -> bool:
        return self._get_file_path(property_name, record_id).exists()

    def update_property_for_key(self, record_id: str, property_name: str, property_value: Any):
        path = self._get_file_path(property_name, record_id)
        path.parent.mkdir(parents=True, exist_ok=True)
        json.dump(property_value, open(path, "w"))

    def delete_property_for_key(self, record_id: str, property_name: str):
        self._get_file_path(property_name, record_id).unlink()

    def get_property_for_key(self, record_id: str, property_name: str) -> Optional[Any]:
        if self.property_exists(record_id, property_name):
            path = self._get_file_path(property_name, record_id)
            return json.load(open(path, "r"))
        else:
            return None

    def get_all_record_ids(self) -> Set[str]:
        ids: List[str] = []
        for property_name in self.get_all_properties():
            path = (
                Path(self._root_directory).joinpath(self._experiment_name).joinpath(property_name)
            )
            property_ids = set([children.name.replace(".json", "") for children in path.iterdir()])
            ids.extend(property_ids)
        return set(ids)

    def get_all_properties(self) -> Set[str]:
        experiment_path = Path(self._root_directory).joinpath(self._experiment_name)
        return set([it.name for it in experiment_path.iterdir()])

    def _get_file_path(self, property_name: str, record_id: str) -> Path:
        return (
            Path(self._root_directory)
            .joinpath(self._experiment_name)
            .joinpath(property_name)
            .joinpath(f"{record_id}.json")
        )