"""
Read hippocampal subfield volumes computed by Freesurfer and/or ASHS

https://sites.google.com/site/hipposubfields/home
https://surfer.nmr.mgh.harvard.edu/fswiki/HippocampalSubfields

>>> from freesurfer_volume_reader import ashs, freesurfer
>>>
>>> for volume_file in itertools.chain(
>>>         ashs.HippocampalSubfieldsVolumeFile.find('/my/ashs/subjects'),
>>>         freesurfer.HippocampalSubfieldsVolumeFile.find('/my/freesurfer/subjects')):
>>>     print(volume_file.absolute_path)
>>>     print(volume_file.subject, volume_file.hemisphere)
>>>     print(volume_file.read_volumes_mm3())
>>>     print(volume_file.read_volumes_dataframe())
"""

import abc
import os
import pathlib
import re
import typing
import warnings

import pandas

try:
    from freesurfer_volume_reader.version import __version__
except ImportError:  # pragma: no cover
    __version__ = None


def parse_version_string(
    version_string: str,
) -> typing.Tuple[typing.Union[int, str], ...]:
    warnings.warn(  # previously used in `__main__.concat_dataframes`
        "function `parse_version_string` is deprecated"
    )
    return tuple(int(p) if p.isdigit() else p for p in version_string.split("."))


def remove_group_names_from_regex(regex_pattern: str) -> str:
    return re.sub(r"\?P<.+?>", "", regex_pattern)


class VolumeFile(metaclass=abc.ABCMeta):

    FILENAME_REGEX: typing.Pattern[str] = NotImplemented

    @abc.abstractmethod
    def __init__(self, path: str) -> None:
        self._absolute_path = pathlib.Path(path).absolute()

    @property
    def absolute_path(self) -> str:
        return str(self._absolute_path)

    @classmethod
    def find(
        cls, root_dir_path: str, filename_regex: typing.Optional[typing.Pattern] = None
    ) -> typing.Iterator["VolumeFile"]:
        if filename_regex is None:
            filename_regex = cls.FILENAME_REGEX
        for dirpath, _, filenames in os.walk(root_dir_path):
            for filename in filter(filename_regex.search, filenames):
                yield cls(path=os.path.join(dirpath, filename))


class SubfieldVolumeFile(VolumeFile):
    @abc.abstractmethod
    def read_volumes_mm3(self) -> typing.Dict[str, float]:
        raise NotImplementedError()

    @abc.abstractmethod
    def read_volumes_dataframe(self) -> pandas.DataFrame:
        raise NotImplementedError()

    def _read_volume_series(self) -> pandas.Series:
        subfield_volumes = self.read_volumes_mm3()
        return pandas.Series(
            data=list(subfield_volumes.values()),
            name="volume_mm^3",
            index=pandas.Index(data=subfield_volumes.keys(), name="subfield"),
        )
