import inspect
import logging
import os
from pathlib import Path
from typing import List

import git


logger = logging.getLogger(__name__)


class HlsProjectRepository:
    """
        HLS Project Repository class

        Provides methods for managing HLS projects.
        """

    # Note: a 'syn' directory also exists with contents being identical
    HDL_PARENT_DIRECTORY = 'impl'

    SUPPORTED_HDL_LANGUAGES = ['verilog', 'vhdl']

    def __init__(self, path=None) -> None:
        """
        Constructs a new HlsProjectRepository class instance.

        :param path: optional path to an alternate HLS project.
        """

        if not path:
            self_path = Path(inspect.getfile(inspect.currentframe())).parent
            path = Path(*self_path.parts[:-4])
            logger.debug(f'Using self path {path}')
        else:
            logger.info(f'Using supplied path {path}')

        self.path = path
        logger.info(f'New HlsProjectRepository with path {self.path}')

    def list_hdl_files(self, language) -> List:
        """
        List the HDL files generated by the csynth command.

        :param language: HDL language, 'vhdl' or 'verilog'
        :return: list of all the HDL files
        """

        if language not in HlsProjectRepository.SUPPORTED_HDL_LANGUAGES:
            raise ValueError(f'Unsupported language: {language}')

        # Locate the implementation directory

        implementation_dir = None
        for (root, dirs, _) in os.walk(self.path):
            if HlsProjectRepository.HDL_PARENT_DIRECTORY in dirs:
                implementation_dir = (
                        Path(root) / HlsProjectRepository.HDL_PARENT_DIRECTORY)
        if not implementation_dir:
            logger.warning('No implementation directory found')
            return list()
        logger.debug(f'Located implementation directory: {implementation_dir}')

        # List HDL files in the relevant language directory

        hdl_dir = implementation_dir / language
        (_, _, files) = next(os.walk(hdl_dir))
        files = [hdl_dir / file for file in files]
        logger.debug(f'Listed {len(files)} in {hdl_dir}')

        return files

    def get_last_commit(self) -> str:
        """Get the hash of the last commit (beware of uncommitted files though)

        :return: hash of the latest commit
        :rtype: string
        """

        repo = git.Repo(path=self.path, search_parent_directories=True)
        commit_hash = repo.head.object.hexsha
        logger.debug(f'Last commit: {commit_hash}')

        return commit_hash
