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

from util.log import log
from util.commands import sudo_move, sudo_mkdir
from util.string_util import get_file_timestamp
from services import rasdaman_service, rasdaman_system_service


class Validator:
    def __init__(self):
        """
        Validator classes are responsible for validating the system at a given state
        """
        pass

    @abstractmethod
    def validate(self):
        """
        Validates
        :return:
        """
        pass


class ValidatorBasis(Validator):
    def __init__(self):
        """
        The basis for all validators
        """
        Validator.__init__(self)

    def validate(self):
        pass


class ValidatorDecorator(Validator):
    def __init__(self, validator):
        """
        Allows validators to be decorated with extra functionality
        :param Validator validator: validator to decorate
        """
        Validator.__init__(self)
        self.validator = validator

    def validate(self):
        Validator.validate(self)
        self.validator.validate()


class RasdamanIsRunningValidator(ValidatorDecorator):
    def __init__(self, validator, rasmgr_port):
        """
        Checks if another process (rasdaman) is running on the chosen port
        :param Validator validator: the validator to decorate
        :param int rasmgr_port: the port rasdaman should run
        """
        ValidatorDecorator.__init__(self, validator)
        self.rasmgr_port = rasmgr_port

    def __rasmgr_running(self):
        from util.url_util import is_port_in_use
        return is_port_in_use(self.rasmgr_port)

    def validate(self):
        ValidatorDecorator.validate(self)

        if not self.__rasmgr_running():
            return

        log.error("Some process is already using port '" + str(self.rasmgr_port) +
                  "' which is by default used by rasdaman.\n"
                  "This is most likely due to a previous installation of rasdaman.")
        try:
            log.warn("Attempting to stop rasdaman...")
            rasdaman_system_service.stop()
            if self.__rasmgr_running():
                rasdaman_service.stop()
        except:
            pass

        if self.__rasmgr_running():
            log.error("Port '" + str(self.rasmgr_port) + "' is still in use; "
                      "please stop the process using this port manually.\n"
                      "Uninstalling previous rasdaman instances before continuing "
                      "is highly recommended in order to avoid data corruption.")
            exit(1)
        else:
            log.warn("Successfully stopped rasdaman.")
