#include <yandex/maps/wiki/social/feedback/enums.h>

#include <maps/libs/enum_io/include/enum_io.h>
#include <maps/wikimap/mapspro/libs/social/magic_strings.h>

#include <unordered_map>

namespace maps::wiki::social::feedback {

namespace {

constexpr enum_io::Representations<TaskState>
    TASK_STATE_STRINGS{
    {TaskState::Incoming,   "incoming"},
    {TaskState::Deferred,   "deferred"},
    {TaskState::Opened,     "opened"},
    {TaskState::NeedInfo,   "need-info"},
    {TaskState::Accepted,   "accepted"},
    {TaskState::Rejected,   "rejected"},
    {TaskState::Deployed,   "deployed"},
};

constexpr enum_io::Representations<UIFilterStatus>
    FEEDBACK_STATUS_TYPE_STRINGS {
    {UIFilterStatus::Opened,   "opened"},
    {UIFilterStatus::NeedInfo, "need-info"},
    {UIFilterStatus::Resolved, "resolved"},
};

constexpr enum_io::Representations<Verdict>
VERDICT_STRINGS {
    {Verdict::Accepted, "accepted"},
    {Verdict::Rejected, "rejected"}
};

constexpr enum_io::Representations<RejectReason>
REJECT_REASON_STRINGS {
    {RejectReason::AutoCleanWeb, "auto-clean-web"},
    {RejectReason::IncorrectData, "incorrect-data"},
    {RejectReason::NoData, "no-data"},
    {RejectReason::NoInfo, "no-info"},
    {RejectReason::NoProcess, "no-process"},
    {RejectReason::ProhibitedByRules, "prohibited-by-rules"},
    {RejectReason::RedirectToContentAuto, "redirect-to-content-auto"},
    {RejectReason::RedirectToContentBicycle, "redirect-to-content-bicycle"},
    {RejectReason::RedirectToContentBigTask, "redirect-to-content-big-task"},
    {RejectReason::RedirectToContentMasstransit, "redirect-to-content-masstransit"},
    {RejectReason::RedirectToContentOther, "redirect-to-content-other"},
    {RejectReason::RedirectToContentPedestrian, "redirect-to-content-pedestrian"},
    {RejectReason::RedirectToContentRoadEvents, "redirect-to-content-road-events"},
    {RejectReason::RedirectToContentToponym, "redirect-to-content-toponym"},
    {RejectReason::RedirectToContentTruck, "redirect-to-content-truck"},
    {RejectReason::RedirectToPlatformAuto, "redirect-to-platform-auto"},
    {RejectReason::RedirectToPlatformBicycle, "redirect-to-platform-bicycle"},
    {RejectReason::RedirectToPlatformMasstransit, "redirect-to-platform-masstransit"},
    {RejectReason::RedirectToPlatformToponym, "redirect-to-platform-toponym"},
    {RejectReason::RedirectToPlatformTruck, "redirect-to-platform-truck"},
    {RejectReason::RedirectToSprav, "redirect-to-sprav"},
    {RejectReason::RedirectToSupport, "redirect-to-support"},
    {RejectReason::Spam, "spam"},
};


constexpr enum_io::Representations<Bucket>
BUCKET_STRINGS {
    {Bucket::Outgoing, "outgoing"},
    {Bucket::Incoming, "incoming"},
    {Bucket::Deferred, "deferred"},
    {Bucket::NeedInfo, "need-info"}
};

constexpr enum_io::Representations<Workflow>
WORKFLOW_STRINGS {
    {Workflow::Feedback, "feedback"},
    {Workflow::Task, "task"}
};

constexpr enum_io::Representations<AgeType>
AGE_TYPE_STRINGS {
    {AgeType::New, "new"},
    {AgeType::Old, "old"}
};

constexpr enum_io::Representations<SuggestedAction>
SUGGESTED_ACTION_TYPE_STRINGS {
    {SuggestedAction::Modify, "modify"},
    {SuggestedAction::Delete, "delete"},
    {SuggestedAction::CreateIndoorPoi, "create-indoor-poi"},
    {SuggestedAction::CreatePoi, "create-poi"},
    {SuggestedAction::VerifyPosition, "verify-position"},
};

// N.B.: fields order in the folowing list is crucial for UI
//
constexpr enum_io::Representations<Type> TYPE_STRINGS_UI_ORDERED {
    // Category Roads
    {Type::Road, "road"},
    {Type::NoRoad, "no-road"},
    {Type::StreetName, "street-name"},
    {Type::RoadSpeedLimit, "road-speed-limit"},
    {Type::RoadDirection, "road-direction"},
    {Type::RoadSurface, "road-surface"},
    {Type::RouteGap, "route-gap"},
    {Type::RouteLost, "route-lost"},

    // Category Routes
    {Type::CarRoute, "car-route"},
    {Type::PedestrianRoute, "pedestrian-route"},
    {Type::BicycleRoute, "bicycle-route"},
    {Type::MtRoute, "mt-route"},
    {Type::ScooterRoute, "scooter-route"},
    {Type::TruckRoute, "truck-route"},
    {Type::TaxiRoute, "taxi-route"},

    // Category Buildings
    {Type::Building, "building"},
    {Type::Address, "address"},
    {Type::AddressExperiment, "address-experiment"},
    {Type::Entrance, "entrance"},
    {Type::EntranceExperiment, "entrance-experiment"},

    // Category RoadInfrastructure
    {Type::Fence, "fence"},
    {Type::PublicTransportStop, "public-transport-stop"},
    {Type::Parking, "parking"},
    {Type::Maneuver, "maneuver"},
    {Type::Barrier, "barrier"},
    {Type::RoadClosure, "road-closure"},
    {Type::RoadAnnotation, "road-annotation"},
    {Type::TrafficLight, "traffic-light"},
    {Type::Subway, "subway"},

    // Category Signs
    {Type::MandatoryDirectionTrafficSign, "mandatory-direction-traffic-sign"},
    {Type::ProhibitedTurnSign, "prohibited-turn-sign"},
    {Type::OneWayTrafficSign, "one-way-traffic-sign"},
    {Type::TrafficLaneSign, "traffic-lane-sign"},
    {Type::TrafficProhibitedSign, "traffic-prohibited-sign"},
    {Type::TrafficCircleSign, "traffic-circle-sign"},
    {Type::TrucksProhibitedSign, "trucks-prohibited-sign"},
    {Type::TrucksManeuverRestrictionSign, "trucks-maneuver-restriction-sign"},
    {Type::TrucksSpeedLimitSign, "trucks-speed-limit-sign"},
    {Type::WeightLimitingSign, "weight-limiting-sign"},
    {Type::DimensionsLimitingSign, "dimensions-limiting-sign"},
    {Type::SpeedBumpSign, "speed-bump-sign"},

    {Type::ConstructiveSignDisappearance, "constructive-sign-disappearance"},
    {Type::AutomotiveSignDisappearance, "automotive-sign-disappearance"},
    {Type::PedestrianSignDisappearance, "pedestrian-sign-disappearance"},
    {Type::HeavyVehicleSignDisappearance, "heavy-vehicle-sign-disappearance"},
    {Type::SpeedLimitSignDisappearance, "speed-limit-sign-disappearance"},
    {Type::ParkingSignDisappearance, "parking-sign-disappearance"},
    {Type::PublicTransportSignDisappearance, "public-transport-sign-disappearance"},
    {Type::TrafficLanesSignDisappearance, "traffic-lanes-sign-disappearance"},

    // Category Poi
    {Type::Indoor, "indoor"},
    {Type::Poi, "poi"},
    {Type::Bench, "bench"},
    {Type::Playground, "playground"},

    // Category Indoor
    {Type::IndoorBarrier, "indoor-barrier"},

    // Category Other
    {Type::Other, "other"},
    {Type::SettlementScheme, "settlement-scheme"},
    {Type::OtherHeavy, "other-heavy"},
};

constexpr enum_io::Representations<TypeCategory>
TYPE_CATEGORY_STRINGS_UI_ORDERED {
    {TypeCategory::Roads, "roads"},
    {TypeCategory::Routes, "routes"},
    {TypeCategory::Buildings, "buildings"},
    {TypeCategory::RoadInfrastructure, "road-infrastructure"},
    {TypeCategory::Signs, "signs"},
    {TypeCategory::Poi, "poi"},
    {TypeCategory::Indoor, "indoor"},
    {TypeCategory::Other, "other"},
};

constexpr enum_io::Representations<Movement>
MOVEMENT_STRINGS {
    {Movement::Forward, "forward"},
    {Movement::LeftTurn, "left-turnt"},
    {Movement::RightTurn, "right-turn"},
    {Movement::Uturn, "u-turn"},
};

const enum_io::Representations<Column>
COLUMN_STRINGS {
    {Column::Workflow, "workflow"},
    {Column::Source, sql::col::SOURCE},
    {Column::Type, sql::col::TYPE},
};

const enum_io::Representations<ProcessingLvl>
PROCESSING_LVL_STRINGS {
    {ProcessingLvl::Level0, "level_0"},
    {ProcessingLvl::Level1, "level_1"},
    {ProcessingLvl::Level2, "level_2"},
    {ProcessingLvl::BigTask, "big-task"},
};

} // namespace


DEFINE_ENUM_IO(TaskState, TASK_STATE_STRINGS);

DEFINE_ENUM_IO(UIFilterStatus, FEEDBACK_STATUS_TYPE_STRINGS);

DEFINE_ENUM_IO(Verdict, VERDICT_STRINGS);

DEFINE_ENUM_IO(RejectReason, REJECT_REASON_STRINGS);

DEFINE_ENUM_IO(Bucket, BUCKET_STRINGS);

DEFINE_ENUM_IO(AgeType, AGE_TYPE_STRINGS);

DEFINE_ENUM_IO(Workflow, WORKFLOW_STRINGS);

DEFINE_ENUM_IO(SuggestedAction, SUGGESTED_ACTION_TYPE_STRINGS);

DEFINE_ENUM_IO(Type, TYPE_STRINGS_UI_ORDERED);

DEFINE_ENUM_IO(TypeCategory, TYPE_CATEGORY_STRINGS_UI_ORDERED);

DEFINE_ENUM_IO(Movement, MOVEMENT_STRINGS);

DEFINE_ENUM_IO(Column, COLUMN_STRINGS);

DEFINE_ENUM_IO(ProcessingLvl, PROCESSING_LVL_STRINGS);

Buckets allRevealedBuckets()
{
    return {
        Bucket::Outgoing,
        Bucket::NeedInfo,
    };
}

AgeTypes allAgeTypes()
{
    return enum_io::enumerateValues<AgeType>();
}

Workflows allWorkflows()
{
    return enum_io::enumerateValues<Workflow>();
}

Types allTypes()
{
    return enum_io::enumerateValues<Type>();
}

TypeCats allTypeCats()
{
    return enum_io::enumerateValues<TypeCategory>();
}

TypeCategory typeCategoryByType(Type type)
{
    switch (type) {
        case Type::Road:
        case Type::NoRoad:
        case Type::StreetName:
        case Type::RoadSpeedLimit:
        case Type::RoadDirection:
        case Type::RoadSurface:
        case Type::RouteGap:
        case Type::RouteLost:
            return TypeCategory::Roads;

        case Type::CarRoute:
        case Type::PedestrianRoute:
        case Type::BicycleRoute:
        case Type::MtRoute:
        case Type::ScooterRoute:
        case Type::TruckRoute:
        case Type::TaxiRoute:
            return TypeCategory::Routes;

        case Type::Building:
        case Type::Address:
        case Type::AddressExperiment:
        case Type::Entrance:
        case Type::EntranceExperiment:
            return TypeCategory::Buildings;

        case Type::Fence:
        case Type::PublicTransportStop:
        case Type::Parking:
        case Type::Maneuver:
        case Type::Barrier:
        case Type::RoadClosure:
        case Type::RoadAnnotation:
        case Type::TrafficLight:
        case Type::Subway:
            return TypeCategory::RoadInfrastructure;

        case Type::MandatoryDirectionTrafficSign:
        case Type::ProhibitedTurnSign:
        case Type::OneWayTrafficSign:
        case Type::TrafficLaneSign:
        case Type::TrafficProhibitedSign:
        case Type::TrafficCircleSign:
        case Type::TrucksProhibitedSign:
        case Type::TrucksManeuverRestrictionSign:
        case Type::TrucksSpeedLimitSign:
        case Type::WeightLimitingSign:
        case Type::DimensionsLimitingSign:
        case Type::SpeedBumpSign:
        case Type::ConstructiveSignDisappearance:
        case Type::AutomotiveSignDisappearance:
        case Type::PedestrianSignDisappearance:
        case Type::HeavyVehicleSignDisappearance:
        case Type::SpeedLimitSignDisappearance:
        case Type::ParkingSignDisappearance:
        case Type::PublicTransportSignDisappearance:
        case Type::TrafficLanesSignDisappearance:
            return TypeCategory::Signs;

        case Type::Indoor:
        case Type::Poi:
        case Type::Bench:
        case Type::Playground:
            return TypeCategory::Poi;

        case Type::IndoorBarrier:
            return TypeCategory::Indoor;

        case Type::Other:
        case Type::SettlementScheme:
        case Type::OtherHeavy:
            return TypeCategory::Other;
    }
}

TypeCatToTypes typeCategoryToTypes()
{
    TypeCatToTypes map;
    for (auto cat : allTypeCats()) {
        map.push_back({cat, {}});
    }

    for (auto type : allTypes()) {
        auto cat = typeCategoryByType(type);

        auto catTypesIt = std::find_if(map.begin(), map.end(),
            [&](const auto& val) { return cat == val.first; }
        );
        ASSERT(catTypesIt != map.end());

        auto& [mapCat, mapTypes] = *catTypesIt;
        mapTypes.push_back(type);
    }

    return map;
}

} // namespace maps::wiki::social::feedback
