import toml
import json
import requests

from urllib.request import urlopen
from urllib.error import HTTPError


class CompileVersion(object):
    """
    :param PATH_URL:    url to get version list
    :param PATH_OUT:    path where the toml file will be written
    :param CONSTANTS:   constants path
    :param SUPPORT_5:   distro with 5 years support
    """

    def __init__(
            self,
            path_url: str = "https://releases.ubuntu.com/?C=M;O=A",
            path_out: str = "../../data/downloads.toml",
            constants: str = "./assets/costants.json",
            ignore_interim: str = None,
            ignore_lts: str = None,
    ):
        self.path_url = path_url
        self.path_out = path_out
        self.constants = constants

        self.SUPPORT_5 = ["desktop", "live-server"]
        self.INVERT_RELEASES = ["live-server"]

        self.ignore_interim = ignore_interim if ignore_interim else []
        self.ignore_lts = ignore_lts if ignore_lts else []

    @property
    def data_sources(self) -> list:
        return [
            (
                "releases-ubuntu",
                "https://releases.ubuntu.com/{codename}/ubuntu-{version}-{distro}-{arch}.iso"
            ),
            (
                "cdimages-ubuntu",
                "https://cdimages.ubuntu.com/releases/{codename}/release/ubuntu-{version}-{distro}-{arch}.iso"
            ),
            (
                "cdimages-derivatives",
                "https://cdimages.ubuntu.com/{distro}/releases/{codename}/release/{distro}-{version}-desktop-{arch}.iso"
            ),
            (
                "cdimages-studio",
                "https://cdimages.ubuntu.com/{distro}/releases/{codename}/release/{distro}-{version}-dvd-{arch}.iso"
            ),
        ]

    @property
    def ver_lts(self) -> str:
        return max(self.get_list_version()["LTS"])

    @property
    def ver_interim(self) -> str:
        return max(self.get_list_version()["Interim"])

    def get_list_version(self) -> dict:
        res = requests.get(self.path_url)
        if res.status_code != 200:
            raise Exception("Error requests")

        ver_list = {"Interim": [], "LTS": []}
        table_rows = res.text.split('<img src="/icons/folder.gif" alt="[DIR]"> ')[1:]
        for val in table_rows:
            row = val.split('/">')
            version = row[0].replace('<a href="', "")
            if "Ubuntu " in row[1] and "." in version:
                _version, name = row[1].split("Ubuntu ")[1].split("(")
                name = name.replace(")\n", "")
                codename = name.split(" ")[0].lower()
                ver, release_type = _version.split(" ")[0:2]
                if release_type == "LTS":
                    if codename not in self.ignore_lts:
                        ver_list["LTS"].append((version, codename, name))
                else:
                    if codename not in self.ignore_interim:
                        ver_list["Interim"].append((version, codename, name))
        return ver_list

    def compile_download(self) -> None:
        version, codename, _ = self.ver_interim
        latest = {"version": version, "codename": codename, "lts": False}
        version, codename, _ = self.ver_lts
        lts = {"version": version, "codename": codename, "lts": True}
        with open(self.constants, "r") as fn:
            data = json.load(fn)
        # write releases
        data["releases"] = {"latest": latest, "lts": lts}
        # write all distros and relative archs
        for key in data["distros"]:
            data["distros"][key]["lts-only"] = False
            data["distros"][key]["releases"] = ["latest", "lts"]
            data["distros"][key]["lts-support-years"] = (
                5 if key in self.SUPPORT_5 else 3
            )
            data["distros"][key]["releases"] = (
                ["latest", "lts"]
                if key not in self.INVERT_RELEASES
                else ["lts", "latest"]
            )
            data["distros"][key]["archs"] = {
                "amd64": self.get_archs_releases(codename, version, key, "amd64")
            }
            if key == "live-server":
                data["distros"][key]["archs"] = {
                    "arm64": self.get_archs_releases(codename, version, key, "arm64")
                }
                data["distros"][key]["archs"] = {
                    "ppc64el": self.get_archs_releases(
                        codename, version, key, "ppc64el"
                    )
                }
        # write sources
        data["sources"] = {}
        for key, path in self.data_sources:
            data["sources"][key] = {"https": path, "torrent": path + ".torrent"}
        # write download.toml
        with open(self.path_out, "w") as out:
            toml.dump(data, out)

    def get_archs_releases(self, codename: str, version: str, distro: str, arch: str) -> str:
        http = None
        for http, path in self.data_sources:
            try:
                conn = urlopen(path.format(codename=codename, version=version, distro=distro, arch=arch))
            except HTTPError:
                pass
            except ValueError:
                pass
            else:
                conn.close()
                break

        if http is None:
            raise Exception("Nessun path http corretto")

        return http
