#include "Flight_VTO.h"
#include <algorithm>
#include <cmath>
namespace {
double to_radians(double degrees) {
    return degrees * 3.14159265358979323846 / 180.0;
}
double track_heading_from_points(const SSR::Position_Info& first, const SSR::Position_Info& second) {
    auto lat1 = to_radians(first.lat);
    auto lat2 = to_radians(second.lat);
    auto dlon = to_radians(second.lon - first.lon);
    auto y = std::sin(dlon) * std::cos(lat2);
    auto x = std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(dlon);
    auto angle = std::atan2(y, x) * 180.0 / 3.14159265358979323846;
    return angle < 0 ? angle + 360.0 : angle;
}
double ground_distance_meters(const SSR::Position_Info& first, const SSR::Position_Info& second) {
    auto dlat = to_radians(second.lat - first.lat);
    auto dlon = to_radians(second.lon - first.lon);
    auto lat1 = to_radians(first.lat);
    auto lat2 = to_radians(second.lat);
    auto a =
    std::sin(dlat / 2) * std::sin(dlat / 2) + std::cos(lat1) * std::cos(lat2) * std::sin(dlon / 2) * std::sin(dlon / 2);
    auto safe_a = std::min(1.0, std::max(0.0, a));
    return 6371000.0 * 2 * std::atan2(std::sqrt(safe_a), std::sqrt(1 - safe_a));
}
double track_pitch_from_points(const SSR::Position_Info& first, const SSR::Position_Info& second) {
    auto distance = ground_distance_meters(first, second);
    return std::atan2(second.alt - first.alt, distance) * 180.0 / 3.14159265358979323846;
}
Flight_Track_Orientation track_orientation_from_points(const SSR::Position_Info& first,
                                                       const SSR::Position_Info& second) {
    return {track_heading_from_points(first, second), track_pitch_from_points(first, second), 0.0};
}
} // namespace
Psc::JSON Flight_Track_Orientation::to_json() const {
    auto ret = Psc::JSON::object();
    ret.append({"heading", heading});
    ret.append({"pitch", pitch});
    ret.append({"roll", roll});
    return ret;
}
Psc::JSON Flight_VTO::to_json() {
    return to_json(true);
}
Psc::JSON Flight_VTO::to_base_info_json() {
    return to_json(false);
}
Psc::JSON Flight_VTO::to_json(bool include_runtime_fields) {
    auto ret = Psc::JSON::object();
    ADD_Json(icao);
    ADD_Json(mlat);
    ret.children.emplace_back("time_stamp", time_to_string(time_stamp));
    if (pos.has_value()) {
        ret.children.emplace_back("latitude", pos.value().lat);
        ret.children.emplace_back("longitude", pos.value().lon);
    }
    else {
        ret.children.emplace_back("latitude", nullptr);
        ret.children.emplace_back("longitude", nullptr);
    }
    ADD_Json_RET(track);
    if (include_runtime_fields) {
        if (track_orientation.has_value()) {
            ret.append({"track_orientation", track_orientation.value().to_json()});
        }
        else {
            ret.append({"track_orientation", nullptr});
        }
    }
    ADD_Json_RET(speed);
    ADD_Json_RET(altitude);
    ADD_Json_RET(vert_speed);
    ADD_Json_RET(call_sign);
    ADD_Json_RET(squawk);
    if (include_runtime_fields) {
        if (vortex_type.has_value()) {
            auto value = vortex_type.value();
            ret.append({"vortex_type", static_cast<int>(value)});
            ret.append({"vortex_type_key", std::string(SSR::Vortex_Type_to_key(value))});
            ret.append({"vortex_type_label", std::string(SSR::Vortex_Type_to_label(value))});
        }
        else {
            ret.append({"vortex_type", nullptr});
            ret.append({"vortex_type_key", nullptr});
            ret.append({"vortex_type_label", nullptr});
        }
    }
    return ret;
}
std::string Flight_VTO::time_to_string(time_t time_stamp) {
    const std::tm* utc_time = std::gmtime(&time_stamp);
    char buffer[80];
    std::strftime(buffer, sizeof(buffer), "%H:%M:%S", utc_time);
    return {buffer};
}
Flight_VTO Flight_VTO::to_VTO(SSR::Aircraft_Info* info) {
    Flight_VTO vto;
    vto.icao = info->icao;
    vto.mlat = info->mlat;
    vto.time_stamp = info->timestamp;
    vto.speed = info->speed();
    // 这个地 是相对于地的意思
    vto.track = info->surface_magnetic_heading();
    auto last_two = info->air_pos_track_list.last_two();
    if (last_two.has_value()) {
        auto orientation = track_orientation_from_points(last_two->first, last_two->second);
        vto.track = orientation.heading;
        vto.track_orientation = orientation;
    }
    // vto.pos = info->pos();
    auto opt = info->air_pos_track_list.last();
    vto.pos = opt;
    if (opt.has_value()) {
        SSR::Position_Info& a = opt.value();
        vto.altitude = a.alt;
    }
    // auto val = info->surface_pos_track_list.last();
    // vto.pos = val;
    // if (val.has_value()) {
    //     vto.altitude = val.value().alt;
    //     std::cout << "222222" << std::endl;
    // }
    vto.vert_speed = info->vertical_rate();
    vto.call_sign = info->bds20_call_sign();
    vto.squawk = info->squawk();
    vto.vortex_type = info->vortex_type();
    return vto;
}
