"""
 *
 * This file is part of rasdaman community.
 *
 * Rasdaman community is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Rasdaman community is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU  General Public License for more details.
 *
 * You should have received a copy of the GNU  General Public License
 * along with rasdaman community.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright 2003 - 2016 Peter Baumann / rasdaman GmbH.
 *
 * For more information please see <http://www.rasdaman.org>
 * or contact Peter Baumann via <baumann@rasdaman.com>.
 *
"""
import os
from abc import abstractmethod, ABCMeta

from util.log import log
from util.commands import sudo_remove, remove
from services import executor, rasdaman_system_service


class Uninstaller:
    """
    The classes implementing the Uninstaller interface uninstall different
    rasdaman components from the system.
    """
    __metaclass__ = ABCMeta

    @abstractmethod
    def clean(self):
        """
        Cleans up previous installed or configured components
        """
        pass


class UninstallerBasis(Uninstaller):
    def __init__(self):
        pass

    def clean(self):
        pass


class UninstallerDecorator(Uninstaller):
    def __init__(self, uninstaller):
        """
        The Uninstaller decorator allows you to compose several uninstallers into one.
        :param Uninstaller uninstaller: the uninstaller that this decorator wraps
        """
        self.uninstaller = uninstaller

    def clean(self):
        """
        This method should be overridden to add new cleaning behavior
        However a call to super will always be required
        """
        self.uninstaller.clean()


class RasdamanServiceUninstaller(UninstallerDecorator):
    def __init__(self, uninstaller):
        super(RasdamanServiceUninstaller, self).__init__(uninstaller)

    def __remove_init_scripts(self):
        rasdaman_system_service.disable()
        for f in ["/etc/init.d/rasdaman", "/etc/systemd/system/rasdaman.service"]:
            if os.path.exists(f):
                sudo_remove(f)

    def clean(self):
        UninstallerDecorator.clean(self)
        log.info("Removing rasdaman service scripts...")
        self.__remove_init_scripts()
        log.info("Rasdaman service scripts removed.")


class RasdamanPathUninstaller(UninstallerDecorator):
    def __init__(self, uninstaller, install_path, remove_data, remove_config):
        super(RasdamanPathUninstaller, self).__init__(uninstaller)
        self.install_path = install_path
        self.remove_data = remove_data
        self.remove_config = remove_config

    def clean(self):
        UninstallerDecorator.clean(self)
        log.info("Removing rasdaman installation...")
        if self.remove_data and self.remove_config:
            remove(self.install_path)
        elif self.remove_data or self.remove_config:
            exclude = "data" if self.remove_data else "etc"
            executor.execute(["find", self.install_path, "!", "-name",
                              exclude, "-exec", "rm", "-rf", "{}", "\;"])
        else:
            executor.execute(["find", self.install_path, "!", "\(", "-name",
                              "data", "-o", "-name", "etc", "\)",
                              "-exec", "rm", "-rf", "{}", "\;"])
        sudo_remove("/etc/profile.d/rasdaman.sh")
        log.info("Rasdaman installation was successfully uninstalled.")


class PostgresUninstaller(UninstallerDecorator):
    def __init__(self, uninstaller, user, database):
        """
        Removes the postgres rasdaman database
        :param Uninstaller uninstaller: the uninstaller to decorate
        :param str user: the user used for rasdaman
        :param str database: the database used for rasdaman
        """
        super(PostgresUninstaller, self).__init__(uninstaller)
        self.user = user
        self.database = database

    def clean(self):
        UninstallerDecorator.clean(self)
        log.info("Removing postgres database...")
        executor.execute(["dropdb", self.database], user="postgres",
            throw_on_error=False)
        executor.execute(["dropuser", self.user], user="postgres",
            throw_on_error=False)
        log.info("Postgres database was successfully removed")


class SqliteUninstaller(UninstallerDecorator):
    def __init__(self, uninstaller, data_dir):
        """
        Removes the sqlite database
        :param Uninstaller uninstaller: the uninstaller to decorate
        :param str data_dir: the data directory of rasdaman
        """
        super(SqliteUninstaller, self).__init__(uninstaller)
        self.data_dir = data_dir

    def clean(self):
        UninstallerDecorator.clean(self)
        log.info("Removing sqlite database...")
        sudo_remove(self.data_dir)
        log.info("Sqlite database removed.")


class WebappUninstaller(UninstallerDecorator):
    def __init__(self, uninstaller, webapps_path):
        """
        Removes petascope / SECORE database and webapps.
        :param Uninstaller uninstaller: the uninstaller to decorate
        :param str user: the user used for petascope
        :param str database: the database used for petascope
        """
        super(WebappUninstaller, self).__init__(uninstaller)
        self.webapps_path = webapps_path

    def __remove_wars(self):
        removed = False
        for f in ["def", "def.war", "rasdaman", "rasdaman.war", "secoredb"]:
            target = self.webapps_path + f
            if os.path.exists(target):
                sudo_remove(target)
                removed = True
        if removed:
            log.info("  Removed externally deployed webapps.")

    def clean(self):
        UninstallerDecorator.clean(self)
        log.info("Removing petascope and SECORE...")
        self.__remove_wars()
        log.info("Petascope and SECORE were successfully removed.")
