"""
    Action versions - compare versions
"""

# TODO html output
# out_html = self.params.option('html')

import os
import shutil
import urllib
import gzip
import pyalpm
import lib
from lib.actions import Action
from lib.action.actionpactree import ActionPactree
from lib.alpm import AlpmBranch
from lib.exceptions import BranchError


class ActionVersions(Action):

    @staticmethod
    def usage():
        return """
            versions [packager] --unstable --archlinux [-q] [--verbose | -v]: compare version over branches
                packager : stefano@manjaro
                -q : only package name
                --verbose | -v : show all differences
                --aur : only if archlinux selected
                --pkg [pkgname] : test package dependencies
            """

    def test(self):
        super().test()
        if not self.params.branch:
            raise BranchError(f"Enter a valid branch {AlpmBranch.BRANCHES}")
        if not self.params.branch_two:
            raise BranchError(f"Enter a second valid branch {AlpmBranch.BRANCHES}")
        return True

    def run(self):
        """
        command : Maintener test versions over branch
        versions [user] [--aur]
        """
        super().run()
        branches = self.params.get_branches()
        use_aur = self.params.option('aur')
        verbose = self.params.option('verbose', 'v')
        quiet = self.params.option('quiet', 'q')
        packager = ''
        use_pkg = self.params.option('pkg', 'p')
        if use_pkg and isinstance(use_pkg, bool):
            try:
                use_pkg = self.params.values.pop(0).strip()
            except IndexError:
                use_pkg = ''
        else:
            try:
                packager = self.params.values.pop(0).strip()
            except IndexError:
                packager = ''
                if use_aur:
                    print('No AUR if not packager !')
                use_aur = False     # for big aur request

        branch = AlpmBranch(branches[1])
        branch_two = AlpmBranch(branches[0])

        print(f":: Compare versions {branch.color(branch.branch)}{branch.branch}{branch.color('none')} / {branch_two.color(branch_two.branch)}{branch_two.branch}{branch.color('none')}")
        pkgs = frozenset(p for p in branch.pkg_search('') if packager in p.packager)

        if use_pkg:
            try:
                old_branch = self.params.branch
                self.params.branch = 'unstable'
                ret = ActionPactree(self.params).run(use_pkg)
            finally:
                self.params.branch = old_branch
            if ret:
                ret = set(ret) & set(p.name for p in pkgs)
                pkgs = frozenset(p for p in pkgs if p.name in ret)
                print(f":: Package {branch.color(branch.branch)}{use_pkg}{branch.color('none')}")
            else:
                raise UserWarning(f"Nothing found ! {use_pkg}")
        aurs = {}

        if use_aur and branch_two.branch == 'archlinux':
            # download list all packages in AUR
            if not os.path.exists(f"{lib.TMP_DIR}/aur.packages"):
                if not os.path.exists(lib.TMP_DIR):
                    os.mkdir(lib.TMP_DIR)
                with urllib.request.urlopen("https://aur.archlinux.org/packages.gz") as f_url:
                    with open(f"{lib.TMP_DIR}/packages.gz", 'wb') as p_archive:
                        p_archive.write(f_url.read())
                with gzip.open(f"{lib.TMP_DIR}/packages.gz", 'rb') as z_file, open(f"{lib.TMP_DIR}/aur.packages", 'wb') as t_file:
                    shutil.copyfileobj(z_file, t_file, 65536)
                os.remove(f"{lib.TMP_DIR}/packages.gz")
            if verbose:
                print(":: use AUR")

            aurs = self.load_aur_pkgs(f"{lib.TMP_DIR}/aur.packages", frozenset(p.name for p in pkgs))
            print(f"{len(aurs)} packages manjaro in aur")
            aurs = AlpmBranch.aur_infos(aurs, verbose)
            #print('aur_requests:', aurs)

        i = 0
        for i, pkg in enumerate(pkgs):
            pkg_arch = branch_two.pkg_get(pkg.name)
            in_aur = '    '
            if pkg_arch:
                version_two = pkg_arch.version
            else:
                version_two = aurs.get(pkg.name, pkg.version)
                if version_two != pkg.version:
                    in_aur = '(aur)'

            if version_two != pkg.version:
                cmp_versions = pyalpm.vercmp(pkg.version, version_two)
                if quiet:
                    if cmp_versions < 0:
                        print(pkg.name)
                        continue
                else:
                    if verbose or cmp_versions < 0:
                        if cmp_versions < 0:
                            version2 = f"{self.colorize(pkg.version, version_two)}  {in_aur}"
                        else:
                            version2 = f"{version_two}  {in_aur}"
                        print(f"{pkg.name:36} {pkg.version:28} {version2:38} {cmp_versions:>2}")

        if not quiet:
            print(f":: {i} packages")
        #if use_aur and verbose:
        #    print(f"\nAUR packages ({len(aurs)}):\n", *sorted(aurs), sep="  ")

    @staticmethod
    def colorize(ver1, ver2, sep='\33[31m', end='\33[0m') -> str:
        result = ''
        first = True
        for c in ver2:
            if ver1.startswith(f"{result}{c}"):
                result += c
            else:
                if first:
                    first = False
                    result += f"{sep}{c}"
                else:
                    result += c
        if first:
            result += f"{result}{sep}"  # for align columns
        return f"{result}{end}"

    @staticmethod
    def load_aur_pkgs(file_name, include_pkgs) -> list:
        """ find if packages are in file 'aur list packages' """
        result = []
        with open(file_name, 'rt') as t_file:
            for line in t_file:
                line = line.rstrip('\n')
                if line in include_pkgs:
                    result.append(line)
            return result
