import os
# import hashlib
from calculate.utils.files import Process, join_paths
from calculate.templates.format.base_format import FormatError
from typing import NoReturn, Union, List, Tuple, Optional


class ImageMagickError(FormatError):
    pass


class ImageMagick:
    def __init__(self, chroot: str = '/'):
        self._chroot_path: str = chroot
        self.init_commands(chroot)
        self.default_opts: List[str] = []

    @property
    def available(self) -> bool:
        return bool(self.convert_cmd and self.identify_cmd)

    @property
    def chrooted(self) -> bool:
        return self._chroot_path != '/'

    def init_commands(self, chroot: str) -> NoReturn:
        self.convert_cmd: str = "/usr/bin/convert"
        self.identify_cmd: str = "/usr/bin/identify"
        self.chroot_cmd: str = "/bin/chroot"
        self.bash_cmd: str = "/bin/bash"

        if not os.path.exists(join_paths(chroot, self.convert_cmd)):
            self.convert_cmd = None
        if not os.path.exists(join_paths(chroot, self.identify_cmd)):
            self.identify_cmd = None

    def trim_prefix_path(self, filename: str) -> Union[str, None]:
        retpath = "/{}".format(os.path.relpath(filename, self._chroot_path))
        if retpath.startswith("/.."):
            return None
        return retpath

    def get_image_resolution(self, source: str
                             ) -> Union[None, Tuple[int, int]]:
        '''Метод для получения разрешения указанного изображения,
        с помощью команды 'identify -format %w %h <path_to_image>'.'''
        print(f"SOURCE: {source}")
        if self.chrooted:
            print(f"CHROOT_PATH: {self._chroot_path}")
            identify = Process(self.chroot_cmd, self._chroot_path,
                               self.bash_cmd, "-c",
                               " ".join([self.identify_cmd,
                                        "-format '%w %h'", source]))
        else:
            identify = Process(self.identify_cmd, "-format", "%w %h", source)

        if identify.success():
            result = identify.read()
            swidth, sheight = result.split(" ")

            if swidth.isdigit() and sheight.isdigit():
                return int(swidth), int(sheight)
            else:
                raise ImageMagickError(f"ERROR: can not parse: '{result}'")
        else:
            raise ImageMagickError(f"ERROR: {identify.read_error()}")

    def convert(self, source: str, target: str, *opts: List[str],
                image_format: Optional[str] = None) -> bool:
        command = [self.convert_cmd, "-quality", "95",
                   source]
        command.extend(self.default_opts)
        command.extend(opts)
        if image_format is not None:
            command.append(f"{image_format}:{target}")
        else:
            command.append(target)
        if self.chrooted:
            convert = Process(self.chroot_cmd, self._chroot_path,
                              self.bash_cmd, "-c",
                              " ".join(command))
        else:
            print("OPTIONS:")
            print(command)
            convert = Process(*command)
        if convert.success():
            print("CREATED: {}".format(target))
            return True
        else:
            print("ERROR:", convert.read_error())
        return False

    def convert_resize_crop_center(self, source: str, target: str,
                                   height: int, width: int,
                                   image_format: Optional[str] = None) -> bool:
        # if ((width == self.source_width and height == self.source_height) and
        #         (source.rpartition('.')[2] == target.rpartition('.')[2])):
        #     with write_file(target) as sf:
        #         sf.write(read_file(source))
        #     return True
        res = f"{width}x{height}"
        return self.convert(source, target, "-quality", "95",
                            "-resize", f"{res}^",
                            "-strip", "-gravity", "center",
                            "-crop", f"{res}+0+0",
                            image_format=image_format)

    def convert_resize_gfxboot(self, source: str, target: str,
                               height: int, width: int,
                               image_format: Optional[str] = None) -> bool:
        res = f"{width}x{height}"
        return self.convert(source, target, "-quality", "95",
                            "-resize", f"{res}^",
                            "-strip", "-gravity", "center",
                            "-crop", f"{res}+0+0",
                            "-sampling-factor", "2x2",
                            "-interlace", "none",
                            "-set", "units", "PixelsPerSecond",
                            image_format=image_format)

    def get_image_format(self, source: str) -> str:
        """Метод для получения формата указанного файла."""
        if self.chrooted:
            identify = Process(self.chroot_cmd, self._chroot_path,
                               self.bash_cmd, "-c",
                               " ".join([self.identify_cmd,
                                         "-format '%m'", source]))
        else:
            identify = Process(self.identify_cmd, "-format", "%m", source)

        if identify.success():
            image_format = identify.read()
            return image_format
        else:
            raise ImageMagickError(f"ERROR: {identify.read_error()}")
