# River.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/>.

import logging

from datetime import datetime

logger = logging.getLogger()


class Profile(object):
    def __init__(self, profile, study):
        self._study = study
        self._profile = profile  # Source profile in the study
        self._data = {}  # Dict of dict {<ts>: {<key>: <value>, ...}, ...}

    def __len__(self):
        return len(self._data)

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

    @property
    def rk(self):
        return self._profile.rk

    @property
    def geometry(self):
        return self._profile

    def set(self, timestamp, key, data):
        if timestamp not in self._data:
            self._data[timestamp] = {}

        self._data[timestamp][key] = data

    def get_ts(self, timestamp):
        return self._data[timestamp]

    def get_key(self, key):
        return list(
            map(lambda ts: self._data[ts][key], self._data)
        )

    def get_ts_key(self, timestamp, key):
        return self._data[timestamp][key]

    def has_sediment(self):
        return any(map(lambda ts: "sl" in self._data[ts], self._data))


class Reach(object):
    def __init__(self, reach, study):
        self._study = study
        self._reach = reach  # Source reach in the study
        self._profiles = list(
            map(
                lambda p: Profile(p, self._study),
                reach.profiles
            )
        )

    def __len__(self):
        return len(self._profiles)

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

    @property
    def geometry(self):
        return self._reach

    @property
    def profiles(self):
        return self._profiles.copy()

    def profile(self, id):
        return self._profiles[id]

    def set(self, profile_id, timestamp, key, data):
        self._profiles[profile_id].set(timestamp, key, data)

    def has_sediment(self):
        return any(map(lambda profile: profile.has_sediment(), self._profiles))


class River(object):
    def __init__(self, study):
        self._study = study

        # Dict with timestamps as key
        self._reachs = []

    def __len__(self):
        return len(self._reachs)

    @property
    def reachs(self):
        return self._reachs.copy()

    def reach(self, id):
        return self._reachs[id]

    def has_reach(self, id):
        return 0 <= id < len(self._reachs)

    def add(self, reach_id):
        reachs = self._study.river.enable_edges()

        new = Reach(reachs[reach_id].reach, self._study)

        self._reachs.append(new)
        return new

    def get_reach_by_geometry(self, geometry_reach):
        return next(
            filter(
                lambda r: r.geometry is geometry_reach,
                self._reachs
            )
        )
