"""
 *
 * 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>.
 *
"""
from abc import abstractmethod

from util.log import log
from services import executor, rasdaman_service
from config_manager import ConfigManager


class Finalizer:

    def __init__(self):
        """
        Base class for finalizer classes that execute after the system is
        installed and running. Example of such classes are ones that provide
        functionality to insert demo data
        """
        pass

    @abstractmethod
    def finalize(self):
        """
        Called to finalize the installation
        """
        pass


class FinalizerBasis(Finalizer):
    def __init__(self):
        """
        Class to be used as the basis of the decorator hierarchy
        """
        Finalizer.__init__(self)

    def finalize(self):
        pass


class FinalizerDecorator(Finalizer):
    def __init__(self, finalizer):
        """
        Decorator class to be used by finalizer classes
        :param Finalizer finalizer: the finalizer to decorate around
        """
        Finalizer.__init__(self)
        self.finalizer = finalizer

    def finalize(self):
        self.finalizer.finalize()


def coll_exists(bin_path, coll_names):
    out, err, rc = executor.execute([bin_path + "/rasql", "--out", "string", "-q",
                                    "SELECT C FROM RAS_COLLECTIONNAMES AS C"],
                                    throw_on_error=False, timeout_sec=3)
    coll_found = any(name in out for name in coll_names)
    return coll_found and rc == 0


class RasdamanDemoDataFinalizer(FinalizerDecorator):
    def __init__(self, finalizer, install_path, rasmgr_port):
        """
        Ingests the rasdaman demo data
        :param Finalizer finalizer: the finalizer to decorate
        :param str install_path: the install path of rasdaman
        :param int rasmgr_port: rasmgr port
        """
        FinalizerDecorator.__init__(self, finalizer)
        self.install_path = install_path
        self.rasmgr_port = rasmgr_port

    def finalize(self):
        FinalizerDecorator.finalize(self)
        bin_path = self.install_path + "bin"
        if coll_exists(bin_path, ["mr2", "rgb", "mr"]):
            return
        try:
            log.info("Ingesting rasdaman demo data...")
            if not rasdaman_service.available():
                log.info("Rasdaman service is down, cannot ingest demo data.")
                return
            images_path = self.install_path + "share/rasdaman/examples/images"
            executor.execute([bin_path + "/rasdaman_insertdemo.sh", "localhost",
                             str(self.rasmgr_port), images_path, "rasadmin",
                             "rasadmin"])
            log.info("Rasdaman demo data ingested successfully.")
        except:
            log.warn("Failed ingesting rasdaman demo data.")


class PetascopeDemoDataFinalizer(FinalizerDecorator):
    def __init__(self, finalizer, install_path):
        """
        Ingests the petascope demo data
        :param Finalizer finalizer: the finalizer to decorate
        :param str install_path: the install path of rasdaman
        """
        FinalizerDecorator.__init__(self, finalizer)
        self.install_path = install_path

    def finalize(self):
        FinalizerDecorator.finalize(self)
        if not ConfigManager.petascope_available:
            return
        bin_path = self.install_path + "bin"
        if coll_exists(bin_path, ["AverageTemperature", "AverageChloro"]):
            return
        try:
            log.info("Ingesting petascope demo data...")
            if not rasdaman_service.available():
                log.info("Rasdaman service is down, cannot ingest demo data.")
                return
            executor.execute([bin_path + "/petascope_insertdemo.sh"])
            log.info("Petascope demo data ingested successfully.")
        except:
            log.warn("Failed ingesting petascope demo data.")
