"""
 *
 * 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


class Configurer:

    def __init__(self):
        """
        Abstract class for configurers
        """
        pass

    @abstractmethod
    def configure(self):
        """
        Returns the configuration parameter set for the whole configurer hierarchy
        :rtype: set
        """
        pass


class BasisConfigurer(Configurer):
    def __init__(self):
        """
        The base configurer that will be wrapped by other configurer
        :param str install_path: the path to the install directory
        """
        Configurer.__init__(self)

    def configure(self):
        """
        Implementation of the configure base method
        :rtype: set
        """
        return {""}


class ConfigurerDecorator(Configurer):
    def __init__(self, configurer):
        """
        The configurer decorator allows you to compose several configurers into one.
        :param Configurer configurer: the configurer that this decorator wraps
        """
        Configurer.__init__(self)
        self.configurer = configurer

    def configure(self):
        """
        Implementation of the base method
        :return: the configuration parameters set used
        :rtype: set
        """
        configure_params = self.configurer.configure()
        configure_params = configure_params.union(self.cmake_param())
        return configure_params

    @abstractmethod
    def cmake_param(self):
        """
        Returns the configuration parameters for the current configurer that is using cmake
        :return:
        """
        pass


class InstallPrefixConfigurer(ConfigurerDecorator):
    def __init__(self, configurer, install_path):
        """
        Configurer for the debug option of rasdaman
        :param Configurer configurer: the configurer to decorate against
        :param str install_path: the path to the install directory
        """
        ConfigurerDecorator.__init__(self, configurer)
        self.install_path = install_path

    def cmake_param(self):
        return {"-DCMAKE_INSTALL_PREFIX=" + self.install_path}


class EnableStrictConfigurer(ConfigurerDecorator):
    def __init__(self, configurer):
        ConfigurerDecorator.__init__(self, configurer)

    def cmake_param(self):
        return {"-DENABLE_STRICT=ON"}


class ReleaseConfigurer(ConfigurerDecorator):
    def __init__(self, configurer):
        ConfigurerDecorator.__init__(self, configurer)

    def cmake_param(self):
        return {"-DCMAKE_BUILD_TYPE=Release"}


class DebugConfigurer(ConfigurerDecorator):
    def __init__(self, configurer):
        ConfigurerDecorator.__init__(self, configurer)

    def cmake_param(self):
        return {"-DCMAKE_BUILD_TYPE=Debug", "-DENABLE_DEBUG=ON"}


class DebugLogsConfigurer(ConfigurerDecorator):
    def __init__(self, configurer):
        ConfigurerDecorator.__init__(self, configurer)

    def cmake_param(self):
        return {"-DENABLE_DEBUG=ON"}


class NetcdfConfigurer(ConfigurerDecorator):
    def __init__(self, configurer):
        ConfigurerDecorator.__init__(self, configurer)

    def cmake_param(self):
        return {"-DUSE_NETCDF=ON"}


class HdfConfigurer(ConfigurerDecorator):
    def __init__(self, configurer):
        ConfigurerDecorator.__init__(self, configurer)

    def cmake_param(self):
        return {"-DUSE_HDF4=ON"}


class GribConfigurer(ConfigurerDecorator):
    def __init__(self, configurer):
        ConfigurerDecorator.__init__(self, configurer)

    def cmake_param(self):
        return {"-DUSE_GRIB=ON"}


class InternalConverterConfigurer(ConfigurerDecorator):
    def __init__(self, configurer):
        ConfigurerDecorator.__init__(self, configurer)

    def cmake_param(self):
        return {"-DUSE_TIFF=ON", "-DUSE_JPEG=ON", "-DUSE_PNG=ON"}


class PostgresConfigurer(ConfigurerDecorator):
    def __init__(self, configurer):
        ConfigurerDecorator.__init__(self, configurer)

    def cmake_param(self):
        return {"-DDEFAULT_BASEDB=postgresql"}


class SqliteConfigurer(ConfigurerDecorator):
    def __init__(self, configurer, data_directory=None):
        ConfigurerDecorator.__init__(self, configurer)
        self.data_directory = data_directory

    def cmake_param(self):
        ret_set = {"-DDEFAULT_BASEDB=sqlite"}
        if self.data_directory is not None:
            ret_set.add("-DFILE_DATA_DIR=" + self.data_directory)
        return ret_set


class WebappStandaloneConfigurer(ConfigurerDecorator):
    def __init__(self, configurer):
        ConfigurerDecorator.__init__(self, configurer)

    def cmake_param(self):
        return {"-DJAVA_SERVER=embedded"}


class GenerateDocsConfigurer(ConfigurerDecorator):
    def __init__(self, configurer, generate_docs=False):
        ConfigurerDecorator.__init__(self, configurer)
        self.generate_docs = "ON" if generate_docs else "OFF"

    def cmake_param(self):
        return {"-DGENERATE_DOCS=" + self.generate_docs}


class SetSimdExtensionsConfigurer(ConfigurerDecorator):
    def __init__(self, configurer, simd_extensions):
        ConfigurerDecorator.__init__(self, configurer)
        self.simd_extensions = simd_extensions

    def cmake_param(self):
        ret = set()
        for ext in ["AVX", "AVX2", "AVX512"]:
            value = "ON" if ext == self.simd_extensions else "OFF"
            ret.add("-DENABLE_" + ext + "=" + value)
        return ret

class UnityBuildConfigurer(ConfigurerDecorator):
    def __init__(self, configurer, enable=True):
        ConfigurerDecorator.__init__(self, configurer)
        self.enable = "ON" if enable is True else "OFF"

    def cmake_param(self):
        return {"-DENABLE_UNITY_BUILD=" + self.enable}
