# test_Model.py -- Pamhyr
# Copyright (C) 2023-2026  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 unittest
import tempfile

from Model.Status import StudyStatus
from Model.Study import Study
from Model.River import River


class StudyTestCase(unittest.TestCase):
    def test_create_study(self):
        study = Study.new("foo", "bar")
        self.assertEqual(study.name, "foo")
        self.assertEqual(study.description, "bar")

    def test_open_study(self):
        study = Study.open(
            os.path.join(
                "..", "tests_cases", "Enlargement", "Enlargement.pamhyr"
            )
        )
        self.assertNotEqual(study, None)
        self.assertEqual(study.name, "Enlargement")

    def test_save_open_study(self):
        study = Study.new("foo", "bar")
        dir = tempfile.mkdtemp()
        f = os.path.join(dir, "foo.pamhyr")

        # Save study
        study.filename = f
        study.save()
        study.close()

        # Reopen study
        study = Study.open(f)

        # Check
        self.assertNotEqual(study, None)
        self.assertEqual(study.name, "foo")
        self.assertEqual(study.description, "bar")

    def test_create_study_river(self):
        study = Study.new("foo", "bar")
        self.assertNotEqual(study.river, None)

    def test_save_open_study_weather_parameters_default(self):
        study = Study.new("foo", "bar")
        defaults = study.river.weather_parameters.default

        self.assertEqual(len(defaults), 9)
        defaults[0].value = 12.5

        dir = tempfile.mkdtemp()
        f = os.path.join(dir, "foo.pamhyr")

        study.filename = f
        study.save()
        study.close()

        study = Study.open(f)
        defaults = study.river.weather_parameters.default

        self.assertEqual(len(defaults), 9)
        self.assertEqual(defaults[0].type, "AT")
        self.assertEqual(defaults[0].value, 12.5)


class StudyScenarioTestCase(unittest.TestCase):
    def test_create_study(self):
        study = Study.new("foo", "bar")
        self.assertEqual(study.name, "foo")
        self.assertEqual(study.description, "bar")
        self.assertEqual(study.status.scenario_id, 0)

    def test_create_new_scenario_study(self):
        study = Study.new("foo", "bar")
        old = study.status.scenario
        new = study.new_scenario_from_current()

        self.assertEqual(study.name, "foo")
        self.assertEqual(study.description, "bar")

        self.assertNotEqual(study.status.scenario_id, 0)
        self.assertEqual(study.status.scenario_id, new.id)

        self.assertNotEqual(old, new)

    def test_open_study(self):
        study = Study.open(
            os.path.join(
                "..", "tests_cases", "Enlargement", "Enlargement.pamhyr"
            )
        )
        self.assertNotEqual(study, None)
        self.assertEqual(study.name, "Enlargement")
        self.assertEqual(study.status.scenario_id, 0)

    def test_open_study_2(self):
        study = Study.open(
            os.path.join(
                "..", "tests_cases", "MassZero", "TestMultibiefs.pamhyr"
            )
        )
        self.assertNotEqual(study, None)
        self.assertEqual(study.name, "TestMultibiefs")
        self.assertEqual(study.status.scenario_id, 0)

    def test_save_open_study(self):
        study = Study.new("foo", "bar")
        new = study.new_scenario_from_current()
        nid = new.id

        dir = tempfile.mkdtemp()
        f = os.path.join(dir, "foo.pamhyr")

        # Save study
        study.filename = f
        study.save()
        study.close()

        # Reopen study
        study = Study.open(f)

        # Check
        self.assertNotEqual(study, None)
        self.assertEqual(study.name, "foo")
        self.assertEqual(study.description, "bar")
        self.assertEqual(study.status.scenario_id, nid)

    def test_save_study_add_files(self):
        study = Study.new("foo", "bar")
        study.river.additional_files.new(0)

        dir = tempfile.mkdtemp()
        f = os.path.join(dir, "foo.pamhyr")
        study.filename = f
        study.save()
        study.close()

        study = Study.open(f)
        self.assertNotEqual(study, None)
        self.assertEqual(study.name, "foo")
        self.assertEqual(study.description, "bar")
        self.assertEqual(len(study.river.additional_files), 1)

        new = study.new_scenario_from_current()
        nid = new.id

        study.river.additional_files.new(1)

        study.save()
        study.close()

        study = Study.open(f)
        self.assertEqual(len(study.river.additional_files), 2)

    def test_save_study_add_files_reload(self):
        study = Study.new("foo", "bar")
        study.river.additional_files.new(0)

        dir = tempfile.mkdtemp()
        f = os.path.join(dir, "foo.pamhyr")
        study.filename = f
        study.save()

        new = study.new_scenario_from_current()
        nid = new.id

        study.river.additional_files.new(1)
        self.assertEqual(len(study.river.additional_files), 2)

        study.save()
        study.reload_from_scenario(study.scenarios[0])
        self.assertEqual(len(study.river.additional_files), 1)

        study.reload_from_scenario(study.scenarios[nid])
        self.assertEqual(len(study.river.additional_files), 2)

    def test_scenario_river_nodes(self):
        study = Study.new("foo", "bar")
        study.river.additional_files.new(0)

        self.assertNotEqual(study.river, None)

        dir = tempfile.mkdtemp()
        f = os.path.join(dir, "foo.pamhyr")

        study.filename = f
        study.save()

        # Add nodes
        n0 = study.river.add_node()
        n1 = study.river.add_node(x=1.0, y=0.0)
        n2 = study.river.add_node(x=0.0, y=1.0)

        self.assertEqual(study.river.nodes_counts(), 3)

        study.save()

        # New scenario
        new = study.new_scenario_from_current()
        nid = new.id

        n3 = study.river.add_node(x=0.0, y=1.0)
        study.save()

        self.assertEqual(study.river.nodes_counts(), 4)

        study.reload_from_scenario(study.scenarios[0])
        self.assertEqual(study.river.nodes_counts(), 3)

        study.reload_from_scenario(study.scenarios[nid])
        self.assertEqual(study.river.nodes_counts(), 4)

        study.save()


class RiverTestCase(unittest.TestCase):
    def test_create_river(self):
        status = StudyStatus()
        river = River(status=status)

        self.assertNotEqual(river, None)

    def test_create_river_nodes(self):
        status = StudyStatus()
        river = River(status=status)

        self.assertNotEqual(river, None)

        # Add nodes
        n0 = river.add_node()
        n1 = river.add_node(x=1.0, y=0.0)
        n2 = river.add_node(x=0.0, y=1.0)

        # Checks
        self.assertEqual(river.nodes_counts(), 3)

        nodes = river.nodes()
        self.assertEqual(nodes[0], n0)
        self.assertEqual(nodes[1], n1)
        self.assertEqual(nodes[2], n2)

    def test_create_river_edges(self):
        status = StudyStatus()
        river = River(status=status)

        self.assertNotEqual(river, None)

        # Add nodes
        n0 = river.add_node()
        n1 = river.add_node(x=1.0, y=0.0)
        n2 = river.add_node(x=0.0, y=1.0)

        self.assertEqual(river.nodes_counts(), 3)

        # Add edges
        e0 = river.add_edge(n0, n1)
        e1 = river.add_edge(n1, n2)

        # Checks
        self.assertEqual(river.edges_counts(), 2)

        edges = river.edges()
        self.assertEqual(edges[0], e0)
        self.assertEqual(edges[1], e1)
