# ASolver.py -- Pamhyr
# Copyright (C) 2023  INRAE
#
# This program 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.
#
# This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.

# -*- coding: utf-8 -*-

import os
import logging

from tools import timer

try:
    # Installation allow Unix-like signal
    from signal import SIGTERM, SIGSTOP, SIGCONT
    _signal = True
except Exception:
    _signal = False

from enum import Enum

from Model.Except import NotImplementedMethodeError

from Model.Results.Results import Results
from Model.Results.River.River import River, Reach, Profile

logger = logging.getLogger()


class STATUS(Enum):
    NOT_LAUNCHED = -1
    STOPED = 0
    RUNNING = 1
    PAUSED = 5


class AbstractSolver(object):
    _type = ""

    def __init__(self, name):
        super(AbstractSolver, self).__init__()

        self._current_process = None
        self._status = STATUS.NOT_LAUNCHED

        # Informations
        self._type = ""
        self._name = name
        self._description = ""

        # Last study running
        self._study = None

    def __str__(self):
        return f"{self._name} : {self._type} : {self._description}"

    def __getitem__(self, key):
        ret = None
        if key == "name":
            ret = self._name
        elif key == "description":
            ret = self._description
        elif key == "type":
            ret = self._type
        return ret

    @classmethod
    def default_parameters(cls):
        lst = [
            ("all_init_time", "000:00:00:00"),
            ("all_final_time", "999:99:00:00"),
            ("all_timestep", "300.0"),
        ]

        return lst

    @classmethod
    def checkers(cls):
        lst = [
        ]

        return lst

    @property
    def name(self):
        return self._name

    @property
    def description(self):
        return self._description

    @property
    def status(self):
        return self._status

    @property
    def type(self):
        return self._type

    @status.setter
    def status(self, status):
        self._status = status

    def is_running(self):
        return self._status == STATUS.RUNNING

    def is_paused(self):
        return self._status == STATUS.PAUSED

    def is_stoped(self):
        return self._status == STATUS.STOPED

    def has_results_loaded(self):
        self._status = STATUS.NOT_LAUNCHED

    @name.setter
    def name(self, name):
        self._name = name

    @description.setter
    def description(self, description):
        self._description = description

    ##########
    # Export #
    ##########

    def export(self, study, repertory, qlog=None):
        raise NotImplementedMethodeError(self, self.export)

    ###########
    # RESULTS #
    ###########

    @timer
    def results(self, study, repertory, qlog=None):
        results = Results(study=study)
        return results

    #######
    # Run #
    #######

    def run(self, study):
        raise NotImplementedMethodeError(self, self.run)

    def kill(self):
        raise NotImplementedMethodeError(self, self.kill)

    def start(self, study, process=None):
        raise NotImplementedMethodeError(self, self.start)

    def pause(self):
        raise NotImplementedMethodeError(self, self.pause)

    def stop(self):
        raise NotImplementedMethodeError(self, self.stop)