#include <string>

#ifndef DATE_DATE_H
#define DATE_DATE_H

class Date {
 public:
    int year;
    int month;
    int day;

    Date(int year, int month, int day) {
        this->year = year;
        this->month = month;
        this->day = day;
    }

    bool IsLeap() const {
        return ((this->year % 4 == 0 && this->year % 100 != 0) ||
                (this->year % 400 == 0));
    }

    std::string ToString() const {
        std::string res;
        std::string dayStr = std::to_string(day);
        std::string monthStr = std::to_string(month);
        std::string yearStr = std::to_string(year);
        if (dayStr.length() == 1) res += "0";
        res += dayStr + ".";
        if (monthStr.length() == 1) res += "0";
        res += monthStr + ".";
        for (int i = yearStr.length(); i < 4; i++) {
            res += "0";
        }
        res += yearStr;
        return res;
    }

    Date DaysLater(int days) const {
        Date res(this->year, this->month, this->day);
        for (int i = 0; i < days; i++) {
            ++res;
        }
        return res;
    }

    int DaysLeft(const Date &date) const {
        Date target(this->year, this->month, this->day);
        int counter = 0;
        while (!(target == date)) {
            counter++;
            ++target;
        }
        return counter;
    }

    bool operator==(const Date &other) const {
        return (this->day == other.day) &&
               (this->month == other.month) &&
               (this->year == other.year);
    }

    Date &operator++() {
        if (this->day >= 28) {
            switch (this->month) {
                case 1:
                case 3:
                case 5:
                case 7:
                case 8:
                case 10:
                    if (this->day == 31) {
                        this->day = 1;
                        this->month += 1;
                    } else {
                        this->day += 1;
                    }
                    break;

                case 4:
                case 6:
                case 9:
                case 11:
                    if (this->day == 30) {
                        this->day = 1;
                        this->month += 1;
                    } else {
                        this->day += 1;
                    }
                    break;

                case 12:
                    if (this->day == 31) {
                        this->day = 1;
                        this->month = 1;
                        this->year += 1;
                    } else {
                        this->day += 1;
                    }
                    break;

                case 2:
                    if (this->IsLeap() && this->day == 29) {
                        this->day = 1;
                        this->month += 1;
                    } else if (!this->IsLeap() && this->day == 28) {
                        this->day = 1;
                        this->month += 1;
                    } else {
                        this->day += 1;
                    }
                    break;
            }
        } else {
            this->day += 1;
        }
        return *this;
    }
};

#endif  // DATE_DATE_H