#pragma once

#include "Task/AbstractTask.h"

#include "Common/AsstBattleDef.h"
#include "Common/AsstTypes.h"
#include "Config/Miscellaneous/TilePack.h"

#include <meojson/json.hpp>

namespace cv
{
class VideoCapture;
}

namespace asst
{
class VisionHelper;

class CombatRecordRecognitionTask : public AbstractTask
{
public:
    using AbstractTask::AbstractTask;
    virtual ~CombatRecordRecognitionTask() override = default;

    bool set_video_path(const std::filesystem::path& path);

protected:
    virtual bool _run() override;

private:
    struct BattlefieldOper
    {
        bool new_here = false;
        battle::DeployDirection direction = battle::DeployDirection::None;
        std::string name;
    };

    struct ClipInfo
    {
        size_t start_frame_index = 0;
        size_t end_frame_index = 0;
        cv::Mat start_frame;
        cv::Mat end_frame;
        std::vector<battle::DeploymentOper> deployment;
        bool deployment_changed = true;
        std::unordered_map<Point, BattlefieldOper> battlefield;
        std::vector<cv::Mat> random_frames;
        std::string ends_oper_name;
    };

    bool analyze_formation();
    bool analyze_stage();
    bool analyze_deployment();
    bool slice_video();
    bool compare_skill(ClipInfo& clip, ClipInfo& pre_clip);

    bool analyze_clip(ClipInfo& clip, ClipInfo* pre_clip_ptr);
    bool detect_operators(ClipInfo& clip, ClipInfo* pre_clip_ptr);
    bool classify_direction(ClipInfo& clip, ClipInfo* pre_clip_ptr);
    bool process_changes(ClipInfo& clip, ClipInfo* pre_clip_ptr);
    void ananlyze_deployment_names(ClipInfo& clip);

    json::object analyze_action_condition(ClipInfo& clip, ClipInfo* pre_clip_ptr);
    size_t skip_frames(size_t count);

    static std::string analyze_detail_page_oper_name(const cv::Mat& frame);

    std::filesystem::path m_video_path;
    std::shared_ptr<cv::VideoCapture> m_video_ptr = nullptr;
    std::string m_stage_name;
    double m_video_fps = 0;
    size_t m_video_frame_count = 0;
    double m_scale = 0;

    int m_formation_fps = 2;
    int m_stage_ocr_fps = 2;
    int m_deployment_fps = 5;

    size_t m_formation_end_frame = 0;
    size_t m_stage_ocr_end_frame = 0;
    size_t m_battle_start_frame = 0;
    size_t m_battle_end_frame = 0;

    std::vector<ClipInfo> m_clips;
    std::vector<std::pair<size_t /*frame*/, int /*kills*/>> m_frame_kills;

    std::unordered_map<Point, TilePack::TileInfo> m_normal_tile_info;
    std::unordered_map<std::string, cv::Mat> m_formation;
    std::unordered_map<std::string, cv::Mat> m_all_avatars;

    std::unordered_map<std::string, Point> m_operator_locations;
    std::unordered_map<Point, std::string> m_location_operators;

    json::value m_copilot_json;
    int m_pre_action_costs = -1;

#ifdef ASST_DEBUG
    inline static const std::string DrawWindow = "CombatRecord";
#endif
};
} // namespace asst
