# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg
#
# This file is part of Timeline.
#
# Timeline 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.
#
# Timeline 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 Timeline.  If not, see <http://www.gnu.org/licenses/>.


class DateModifier:
    """
    DateModifier functions are used when the arrow keys are used in a
    DatePicker control.
    """

    def __init__(self, time_type=None, delta=None, date_time=None, max_month=12):
        self._time_type = time_type
        self._delta = delta
        self._date_time = date_time
        self._max_month = max_month
        self._max_time = self._date_time.from_time(self._time_type.get_max_time()).to_date_tuple()
        self._min_time = self._date_time.from_time(self._time_type.get_min_time()).to_date_tuple()

    def increment_year(self, date: tuple):
        year, month, day = date
        year += 1
        return self._newtime_or_maxtime(date, day, month, year)

    def decrement_year(self, date: tuple):
        year, month, day = date
        year -= 1
        return self._newtime_or_mintime(date, day, month, year)

    def increment_month(self, date: tuple):
        year, month, day = date
        month += 1
        if month > self._max_month:
            year += 1
            month = 1
        return self._newtime_or_maxtime(date, day, month, year)

    def decrement_month(self, date: tuple):
        year, month, day = date
        month -= 1
        if month < 1:
            year -= 1
            month = self._max_month
        return self._newtime_or_mintime(date, day, month, year)

    def increment_day(self, date: tuple):
        year, month, day = date
        day += 1
        try:
            self._date_time.from_ymd(year, month, day)
        except ValueError:
            day = 1
            month += 1
            if month > self._max_month:
                year += 1
                month = 1
        return self._newtime_or_maxtime(date, day, month, year)

    def decrement_day(self, date: tuple):
        year, month, day = date
        day -= 1
        if day < 1:
            day = 31
            month -= 1
        if month < 1:
            month = self._max_month
            year -= 1
        return self._newtime_or_mintime(date, day, month, year)

    def _newtime_or_maxtime(self, date, day, month, year):
        if (year, month, day) > self._max_time:
            return self._max_time
        return self._set_valid_day(year, month, day)

    def _newtime_or_mintime(self, date, day, month, year):
        if (year, month, day) < self._min_time:
            return self._min_time
        return self._set_valid_day(year, month, day)

    def _set_valid_day(self, new_year, new_month, new_day):
        done = False
        date = None
        while not done:
            try:
                date = self._date_time.from_ymd(new_year, new_month, new_day)
                done = True
            except ValueError:
                new_day -= 1
        return date.to_date_tuple()
