import util.distro as distro
import os


class DistroTypes:
    UNKNOWN = 0
    DEBIAN = 1
    CENTOS = 2
    UBUNTU = 3

    @staticmethod
    def get_distro_type(distro_name):
        name_type_map = {'debian': DistroTypes.DEBIAN,
                         'Debian GNU/Linux': DistroTypes.DEBIAN,
                         'Ubuntu': DistroTypes.UBUNTU,
                         'ubuntu': DistroTypes.UBUNTU,
                         'TUXEDO OS': DistroTypes.UBUNTU,
                         'TUXEDO OS 2': DistroTypes.UBUNTU,
                         'tuxedo': DistroTypes.UBUNTU,
                         'CentOS Linux': DistroTypes.CENTOS,
                         'centos': DistroTypes.CENTOS,
                         'rhel': DistroTypes.CENTOS}
        if distro_name in name_type_map:
            return name_type_map[distro_name]
        else:
            return DistroTypes.UNKNOWN


class InitDTypes:
    UNKNOWN = 0
    SYSV = 1
    # Ubuntu 15.10+, Debian 8+, CentOS 7+
    SYSTEMD = 2
    # Docker doesn't quite support systemd, so it's a special case
    DOCKER = 3

    @staticmethod
    def get_initd_type(distro_type, distro_version):
        if os.path.exists("/.dockerenv"):
            return InitDTypes.DOCKER
        elif (distro_type == DistroTypes.DEBIAN and distro_version >= 8) or \
             (distro_type == DistroTypes.CENTOS and distro_version >= 7) or \
             (distro_type == DistroTypes.UBUNTU and distro_version >= 15.10):
            return InitDTypes.SYSTEMD
        elif (distro_type == DistroTypes.DEBIAN and distro_version < 8) or \
             (distro_type == DistroTypes.CENTOS and distro_version < 7) or \
             (distro_type == DistroTypes.UBUNTU and distro_version < 15.10):
            return InitDTypes.SYSV
        else:
            return InitDTypes.UNKNOWN


class DistroWrapper:
    def __init__(self):
        """
        Wraps aspects specific to the different Linux distributions supported
        by the installer, such as getting the tomcat package name, service
        management commands, etc.
        """
        self.distro_name, version, _ = distro.linux_distribution()
        self.distro_id, _, _ = distro.linux_distribution(full_distribution_name=False)
        self.distro_type = DistroTypes.get_distro_type(self.distro_id)
        try:
            if version.count('.') == 2:
                self.distro_version = float('.'.join(version.split('.')[0:2]))
            else:
                self.distro_version = float(version)
        except ValueError as v:
            if version == "buster/sid":
                self.distro_version = 10.0
            else:
                raise v
        self.initd_type = InitDTypes.get_initd_type(self.distro_type, self.distro_version)

    def get_jdk_name(self):
        if (self.distro_type == DistroTypes.UBUNTU and self.distro_version >= 17.04) or \
           (self.distro_type == DistroTypes.DEBIAN and self.distro_version > 10):
            return "default-jdk-headless"
        elif (self.distro_type == DistroTypes.UBUNTU and self.distro_version >= 15.10) or \
           (self.distro_type == DistroTypes.DEBIAN and self.distro_version >= 9) or \
           (self.distro_type == DistroTypes.CENTOS and self.distro_version >= 8):
            return "openjdk-8-jdk"
        else:
            return "openjdk-7-jdk"

    def get_tomcat_path(self):
        return "/var/lib/" + self.get_tomcat_name()

    def get_tomcat_logs(self):
        return "/var/log/" + self.get_tomcat_name()

    def get_tomcat_conf_path(self):
        if self.distro_type == DistroTypes.CENTOS:
            return "/etc/tomcat/tomcat.conf"
        else:
            return "/etc/default/" + self.get_tomcat_name()

    def get_tomcat_name(self):
        if self.distro_type == DistroTypes.CENTOS and self.distro_version >= 7:
            return "tomcat"
        elif (self.distro_type == DistroTypes.UBUNTU and self.distro_version >= 18.04) or \
             (self.distro_type == DistroTypes.DEBIAN and self.distro_version >= 10):
            if not os.path.exists("/var/lib/tomcat9/webapps") and os.path.exists("/var/lib/tomcat8/webapps"):
                return "tomcat8"
            else:
                return "tomcat9"
        elif (self.distro_type == DistroTypes.UBUNTU and self.distro_version >= 15.10) or \
             (self.distro_type == DistroTypes.DEBIAN and self.distro_version >= 9):
            return "tomcat8"
        else:
            return "tomcat7"

    def get_tomcat_user(self):
        return "tomcat"

    def get_initd_type(self):
        return self.initd_type

    def get_distro_name(self):
        return self.distro_name

    def get_distro_id(self):
        return self.distro_id

    def has_libpaho_packages(self):
        return (self.distro_type == DistroTypes.UBUNTU and self.distro_version >= 22.04) or \
               (self.distro_type == DistroTypes.DEBIAN and self.distro_version >= 12)

    def get_distro_codename(self):
        if self.distro_type == DistroTypes.UBUNTU:
            if self.distro_version == 16.04:
                return "xenial"
            elif self.distro_version == 14.04:
                return "trusty"
            elif self.distro_version == 18.04:
                return "bionic"
            elif self.distro_version == 20.04:
                return "focal"
            elif self.distro_version == 22.04:
                return "jammy"
            elif self.distro_version == 24.04:
                return "noble"
            elif self.distro_version == 26.04:
                return "resolute"
        elif self.distro_type == DistroTypes.DEBIAN:
            if int(self.distro_version) == 8:
                return "jessie"
            elif int(self.distro_version) == 9:
                return "stretch"
            elif int(self.distro_version) == 10:
                return "buster"
            elif int(self.distro_version) == 11:
                return "bullseye"
            elif int(self.distro_version) == 12:
                return "bookworm"
            elif int(self.distro_version) == 13:
                return "trixie"
        elif self.distro_type == DistroTypes.CENTOS:
            if int(self.distro_version) == 7:
                return "centos7"
            if int(self.distro_version) == 8:
                return "centos8"

    def is_deb(self):
        return self.distro_type == DistroTypes.DEBIAN or self.distro_type == DistroTypes.UBUNTU

    def is_rpm(self):
        return self.distro_type == DistroTypes.CENTOS

    def get_distro_type(self):
        return self.distro_type

    def get_distro_version(self):
        return self.distro_version

    def get_service_start_cmd(self, service_name):
        return self.__get_service_cmd(service_name, "start")

    def get_service_stop_cmd(self, service_name):
        return self.__get_service_cmd(service_name, "stop")

    def get_service_restart_cmd(self, service_name):
        return self.__get_service_cmd(service_name, "restart")

    def get_service_enable_cmd(self, service_name):
        if self.initd_type == InitDTypes.SYSTEMD or self.initd_type == InitDTypes.DOCKER:
            return self.__get_service_cmd(service_name, "enable")
        elif self.distro_type == DistroTypes.DEBIAN or self.distro_type == DistroTypes.UBUNTU:
            return ['update-rc.d', service_name, 'start', '99', '2', '3',
                    '4', '5', '.', 'stop', '20', '0', '1', '6', '.']
        elif self.distro_type == DistroTypes.CENTOS:
            return ['chkconfig', service_name, 'on']
        else:
            return []

    def get_service_disable_cmd(self, service_name):
        if self.initd_type == InitDTypes.SYSTEMD or self.initd_type == InitDTypes.DOCKER:
            return self.__get_service_cmd(service_name, "disable")
        elif self.distro_type == DistroTypes.DEBIAN or self.distro_type == DistroTypes.UBUNTU:
            return ['update-rc.d', '-f', service_name, 'remove']
        elif self.distro_type == DistroTypes.CENTOS:
            return ['chkconfig', service_name, 'on']
        else:
            return []

    def get_service_reload_cmd(self, service_name):
        if self.initd_type == InitDTypes.SYSTEMD:
            return ['systemctl', 'daemon-reload']
        else:
            return []

    def get_runuser(self, user):
        if (self.distro_type == DistroTypes.DEBIAN and self.distro_version < 8) or \
           (self.distro_type == DistroTypes.CENTOS and self.distro_version < 7) or \
           (self.distro_type == DistroTypes.UBUNTU and self.distro_version < 15.10):
            return "sudo su " + user + " -c"
        else:
            return "runuser -l " + user + " -c"

    def get_runuser_cmd(self):
        return 'runuser' if 'runuser' in DistroWrapper().get_runuser('dummy') else 'sudo'

    def __get_service_cmd(self, service_name, cmd):
        if self.initd_type == InitDTypes.DOCKER:
            return []
        elif self.initd_type == InitDTypes.SYSV:
            return ["service", service_name, cmd]
        elif self.initd_type == InitDTypes.SYSTEMD:
            return ["systemctl", cmd, service_name + ".service"]
        else:
            return []

    def __str__(self):
        ret = """distro name: {}
distro id: {}
distro type: {}
distro version: {}
inid type: {}
tomcat name: {}
tomcat path: {}
jdk name: {}
runuser: {}
service start: {}
service stop: {}
service enable: {}
service disable: {}
service reload: {}
        """.format(self.get_distro_name(),
                   self.get_distro_id(),
                   self.get_distro_type(),
                   self.get_distro_version(),
                   self.get_initd_type(),
                   self.get_tomcat_name(),
                   self.get_tomcat_path(),
                   self.get_jdk_name(),
                   self.get_runuser('local_user'),
                   self.get_service_start_cmd('rasdaman'),
                   self.get_service_stop_cmd('rasdaman'),
                   self.get_service_enable_cmd('rasdaman'),
                   self.get_service_disable_cmd('rasdaman'),
                   self.get_service_reload_cmd('rasdaman')
                   )
        return ret
