# -*- coding: utf-8 -*-
from setuphelpers import *
from io import BytesIO
import gzip
import os
import re


class DebianPackagesParser:

    def __init__(self, file):
        file_text = self.__read_input(file)
        file_text = self.__remove_pgp_key(file_text)

        packages = file_text.split("\n\n")

        self.raw_pkg_info = []
        if len(packages[0]):
            self.raw_pkg_info = [self.__get_raw_info(pkg) for pkg in packages]

    def __read_input(self, input_obj):
        """Ensures valid input type"""
        if type(input_obj) is not str:
            raise TypeError("input must be string or string path to file")
        elif os.path.exists(os.path.abspath(input_obj)):
            with open(input_obj, "r", encoding="utf8") as f:
                file_text = f.read().strip()
            return file_text
        else:
            return input_obj.strip()

    def __remove_pgp_key(self, text):
        gpg_regex = re.compile(r"^-----BEGIN PGP PUBLIC KEY BLOCK-----[a-zA-Z\d\n\/.:+= ]+-----END PGP PUBLIC KEY BLOCK-----$", flags=re.MULTILINE)
        return re.sub(gpg_regex, '', text)

    def __get_raw_info(self, text):
        """Parses a Debian control file and returns raw dictionary"""
        split_regex = re.compile(r"^[A-Za-z0-9-]+:\s", flags=re.MULTILINE)

        keys = [key[:-2].lower() for key in split_regex.findall(text)]
        values = [value.strip() for value in re.split(split_regex, text)[1:]]

        if values:
            return dict(zip(keys, values))
        else:
            raise ValueError("file or text don't match Debian Control File schema")

def get_all_dep_version_package(list_package, package_name, all_dep):
    """Recursively get all dependencies of a given package."""
    # Get the latest version of the package
    last_package = sorted([u for u in list_package if u['package'] == package_name], 
                          key=lambda p: Version(p['version']), reverse=True)
    if not last_package:
        return  # Exit if the package is not found
    
    last_package = last_package[0]
    
    # Add the last package to the dependencies list
    if last_package not in all_dep:
        all_dep.append(last_package)
    
    # Parse the dependencies
    dependencies = last_package.get('depends', '').split(',')
    
    for dep_group in dependencies:
        dep_candidates = dep_group.split('|')
        
        # Pick the first available candidate
        for dep in dep_candidates:
            dep_name = dep.split('(')[0].strip()
            # Recursively fetch dependencies for this package
            get_all_dep_version_package(list_package, dep_name, all_dep)

def download_all_dependencies(list_package, package_name, urldepot, proxies=None):
    """Download all dependencies of a package."""
    all_dep = []

    # Fetch all dependencies of the package
    get_all_dep_version_package(list_package, package_name, all_dep)

    # Create the list of URLs for all dependencies
    list_deb = [urldepot + '/' + u['filename'] for u in all_dep]

    # Download each dependency
    for f in list_deb:
        filename = f.split('/')[-1]
        if not isfile(filename):
            print(f"Download URL is: {f}")
            wget(f, filename, proxies=proxies)
        else:
            print(f"{filename} already exists.")

def get_package_version(input_obj):
    parts = input_obj.split(':', 1)
    if len(parts) == 2:
        epoch, version = parts
    else:
        epoch, version = 0, parts[0]
        
    for i in "+~":
        version = version.split(i)[0]
    return epoch, str(Version(version, 4))

def update_package():
    # Declaring local variables
    package_updated = False
    proxies = get_proxies_from_wapt_console()
    if not proxies:
        proxies = get_proxies()
    app_name = control.name

    base_url = "https://packages.adoptium.net/artifactory/deb"
    dist = "trixie"
    arch = "amd64"
    package_name = "temurin-25-jre"

    # We remove all deb file first
    for deb in glob.glob('*.deb'):
        remove_file(deb)

    urldepot = f"{base_url}/dists/{dist}/main/binary-{arch}/Packages.gz"
    print(f"Repo url is {urldepot}")

    with gzip.open(BytesIO(wgets(urldepot, proxies=proxies))) as f:
        data = f.read().decode('utf-8')

    list_package = DebianPackagesParser(data).raw_pkg_info

    # Getting latest version of the package
    last_package = sorted([u for u in list_package if u['package'] == package_name], key=lambda p: (Version(p['version'])), reverse=True)[0]
    epoch, version = get_package_version(last_package['version'])

    print(f"Latest {app_name} version is: {version}")
    download_all_dependencies(list_package, package_name, base_url, proxies)

    # Changing version of the package
    if Version(version) > Version(control.get_software_version()):
        print(f"Software version updated (from: {control.get_software_version()} to: {Version(version)})")
        package_updated = True
    else:
        print(f"Software version up-to-date ({Version(version)})")

    control.set_software_version(version)
    control.save_control_to_wapt()

    return package_updated