#pragma once

#include <maps/wikimap/mapspro/libs/masstransit/mtr_object_handler.h>
#include <maps/wikimap/mapspro/libs/masstransit/ymapsdf_object_handler.h>

#include <yandex/maps/wiki/common/schedule.h>
#include <maps/libs/introspection/include/comparison.h>

#include <map>
#include <tuple>

namespace maps::wiki::masstransit {

struct MtrCalendarData {
    DBID threadId;
    common::Date startDate;
    common::Date endDate;
    common::WeekdayFlags weekdays;

    auto introspect() const
    { return std::tie(threadId, startDate, endDate, weekdays); }
};

using introspection::operator<;

struct Calendar : public Object {
    DBID threadId;
    common::Schedules mtrSchedules;
    common::Schedules altMtrSchedules;
};

class YmapsdfCalendarHandler : public YmapsdfObjectHandler {
public:
    explicit YmapsdfCalendarHandler(Masstransit& masstransit);

private:
    std::string name() const override { return "calendar"; }

    std::vector<FtType> ftTypes() const override;
    StringVector attrs() const override;
    StringVector rolesToMasters() const override;
    std::string extraSelectColumns() const override;

    void addObject(const pqxx::row& tuple) override;
    void update() override;
};

class MtrCalendarHandler : public MtrObjectHandler {
public:
    explicit MtrCalendarHandler(Masstransit& masstransit);

private:
    StringVector fileNames() const override
    { return {filename::CALENDAR, filename::FREQUENCY, filename::TIMETABLE}; }

    void writeObject(StreamMap& ostreams, const Object& object) override;

    DBID writeCalendar(
        std::ofstream& ostream,
        DBID threadId,
        const common::IntRange& dayRange,
        const common::WeekdayFlags weekdays);

    void writeFrequency(
        std::ofstream& ostream,
        DBID threadId,
        DBID scheduleId,
        const common::Time& startTime,
        const common::Time& endTime,
        size_t frequency);

    void writeTimetable(
        std::ofstream& ostream,
        DBID threadId,
        DBID scheduleId,
        const common::Time& departureTime);

    std::map<MtrCalendarData, DBID> usedCalendars_;
};

} // namespace maps::wiki::masstransit
