/*
 * MIT License
 *
 * Copyright (c) 2026 Mark Allyn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/*
 * data_structure_and_constants.h
 * Author: Mark Allyn
 *
 * System-wide data structures, constants, and extern declarations.
 * Include this file in ALL CPU source code files.
 */

#pragma once

#include <cstdint>
#include <ctime>
#include <string>
#include <mutex>
#include <vector>

/* ============================================================
 * TARGET DATA STRUCTURES
 * Components: Traffic Cop (Thread 2), Simulator (Thread 3),
 *             Thread 1 (OpenGL / shader pipeline)
 * ============================================================ */

/* Master target record populated from simulator or Raspberry Pi data.
 * Components: Traffic Cop (Thread 2), Simulator (Thread 3) */
struct target_data_structure {
    double target_longitude;
    double target_latitude;
    std::string vessel_name;      // empty if unavailable
    std::string registration;     // empty if unavailable
    float length;                 // meters
    float beam;                   // meters
    int vessel_type;              // AIS type code or aircraft type
    uint32_t mmsi;                // AIS unique identifier; ICAO hex for aircraft
    float course;                 // degrees, true north
    float speed;                  // knots
    float altitude;               // meters; 0 for surface vessels
    int type;                     // 0 = vessel, 1 = aircraft
    int police_boat;              // 1 = police boat, 0 = not
    time_t timestamp;
};

/* Lean SSBO payload uploaded to shaders via SSBO layout(std430).
 * String fields are stripped before upload.
 * Components: Thread 1 (shader upload), all radar scope shaders */
struct ssbo_target_information {
    float target_x;               // Cartesian offset X, meters from radar
    float target_y;               // Cartesian offset Y, meters from radar
    float length;                 // meters
    float beam;                   // meters
    float course;                 // radians, true north
    float altitude;               // meters; 0 for surface vessels
    time_t timestamp;
    float current_reflectivity;   // derived from vessel_type
    float height_estimate;        // derived from vessel_type
    float noiseglint;             // derived from vessel_type
    int32_t police_boat;          // 1 = police boat
    uint32_t mmsi;
    int type;                     // 0 = vessel, 1 = aircraft
};

/* Intermediate payload passed from Traffic Cop to Thread 1.
 * String fields are present here but stripped before SSBO upload.
 * Components: Traffic Cop (Thread 2) -> Thread 1 */
struct target_data_to_thread_1_structure {
    float target_x;
    float target_y;
    std::string vessel_name;      // stripped before SSBO upload
    std::string registration;     // stripped before SSBO upload
    float length;
    float beam;
    float course;
    float altitude;
    time_t timestamp;
    float current_reflectivity;
    float height_estimate;
    float noiseglint;
    int32_t police_boat;
    int type;
    uint32_t mmsi;
};

/* ============================================================
 * RADAR MANAGEMENT
 * Components: Thread 1 (startup, scope switching), Traffic Cop (Thread 2)
 * ============================================================ */

/* Index constants for radar_management[] and current_radar.
 * Array slot 0 (RADAR_NONE) is unused padding so current_radar
 * can be used as a direct index into radar_management[]. */
constexpr int RADAR_NONE           = 0;
constexpr int RADAR_CHAIN_HOME     = 1;
constexpr int RADAR_MARINE_ASCOPE  = 2;
constexpr int RADAR_MARINE_TRAFFIC = 3;
constexpr int RADAR_POLICE_BOAT    = 4;
constexpr int RADAR_COUNT          = 5; // valid indices: 1-4; 0 is unused

/* Per-radar operational state.
 * Indexed by RADAR_* constants above; slot 0 is unused.
 * Components: Thread 1 (startup init, scope switching),
 *             Traffic Cop (Thread 2, range filtering) */
struct radar_management_structure {
    int radar_type;  // RADAR_* constant identifying which radar this entry represents
    int operatable;  // 1 = radar is built and fully functional, 0 = not yet built
    int available;   // 1 = enabled by exhibit operator at startup, 0 = disabled
    int selected;    // 1 = currently active/displayed, 0 = not active
};

// Array of radar states, indexed by RADAR_* constants.
// radar_management[0] is unused padding.
// Components: Thread 1, Traffic Cop (Thread 2)
extern radar_management_structure radar_management[RADAR_COUNT];

// Index of the currently active radar (RADAR_NONE through RADAR_POLICE_BOAT).
// 0 means no radar selected (e.g. intro screen).
// Components: Thread 1, Traffic Cop (Thread 2), all scope renderers
extern int current_radar;

/* Component identifiers for testing_component.
 * When testing_component is non-zero, only that component is active and
 * no other radars can be made available.
 * Values 2-5 correspond to RADAR_* constants for the four radar types.
 * Components: Thread 1 (startup), all components that gate on test mode */
constexpr int TESTING_NONE           = 0; // normal exhibit operation
constexpr int TESTING_MANAGEMENT     = 1; // setup and radar selection (this module)
constexpr int TESTING_CHAIN_HOME     = 2; // chain home A-scope
constexpr int TESTING_MARINE_ASCOPE  = 3; // marine A-scope
constexpr int TESTING_MARINE_TRAFFIC = 4; // marine traffic control PPI
constexpr int TESTING_POLICE_BOAT    = 5; // police boat PPI
constexpr int TESTING_TRAFFIC_COP    = 6; // traffic cop (Thread 2)
constexpr int TESTING_SIMULATOR      = 7; // simulator (Thread 3)
constexpr int TESTING_RASPBERRY_PI   = 8; // raspberry pi receiver (Thread 5)

// Active component under development; initialized from TESTING_COMPONENT in settings.h.
// Set to TESTING_NONE for normal exhibit operation.
// Components: Thread 1 (startup gating), all components
extern int testing_component;

/* ============================================================
 * THREAD MUTEXES
 * Defined in global_data.cpp; extern declared here.
 * ============================================================ */

// Thread 2 -> Thread 1: protects target data handoff
extern std::mutex mutex_target_data;

// Thread 3 -> Thread 2: protects simulator-to-traffic-cop handoff
extern std::mutex mutex_simulator_to_traffic_cop;

// Thread 4 -> Thread 1: protects physical control data (Thread 4 not yet implemented)
extern std::mutex mutex_control_data_to_shaders;

// Thread 5 -> Thread 2: protects Raspberry Pi receiver data (Thread 5 not yet implemented)
extern std::mutex mutex_raspberry_pi;

/* ============================================================
 * SHADER UNIFORM COPIES
 * Defined in global_data.cpp; extern declared here.
 * Components: Thread 1 (keyboard callbacks and per-frame uniform push),
 *             all radar scope shaders.
 * Note: uniforms are implemented as each scope component is built.
 * ============================================================ */

// Scope intensity — keyboard 3 (lower) / 4 (higher)
// GLSL uniform: float intensity
// Components: all scopes
extern float uniform_intensity;

// Receiver sensitivity — keyboard 5 (lower) / 6 (higher)
// GLSL uniform: float sensitivity
// Components: all scopes
extern float uniform_sensitivity;

// STC sensitivity for close-in targets — keyboard q (lower) / w (higher)
// GLSL uniform: float stc_sensitivity
// Components: all scopes
extern float uniform_stc_sensitivity;

// STC effective range — keyboard e (lower) / r (higher)
// GLSL uniform: float stc_range
// Components: all scopes
extern float uniform_stc_range;

// Rain noise filter, PPI scopes only — keyboard t (decrease) / y (increase)
// GLSL uniform: float noise_filter
// Components: PPI scopes (marine traffic control, on-board boat)
extern float uniform_noise_filter;

// Chain Home radiogoniometer bearing — keyboard u (left) / i (right)
// GLSL uniform: float radiogoniometer
// Components: Chain Home A-scope
extern float uniform_radiogoniometer;

// Maximum radar range, all scopes except Chain Home — keyboard o (lower) / p (higher)
// GLSL uniform: float max_range
// Components: Marine A-scope, PPI scopes
extern float uniform_max_range;

// Range cursor, PPI scopes only — keyboard a (lower) / s (higher)
// GLSL uniform: float range_cursor
// Components: PPI scopes (marine traffic control, on-board boat)
extern float uniform_range_cursor;

// Bearing cursor, PPI scopes only — keyboard d (CCW) / f (CW)
// GLSL uniform: float bearing_cursor
// Components: PPI scopes (marine traffic control, on-board boat)
extern float uniform_bearing_cursor;

// Marine A-scope antenna rotation bearing — keyboard g (CCW) / h (CW)
// GLSL uniform: float marine_a_bearing
// Components: Marine A-scope
extern float uniform_marine_a_bearing;

/* ============================================================
 * TEMPORARY TEST FILE REGISTRY
 * Each active test .cpp stub pushes its filename into test_functions.
 * Each active test .h stub pushes its filename into test_functions_include.
 * Both are printed at startup when any entry is present so it is
 * immediately visible that test infrastructure is compiled in.
 * Components: any temporary test stub; Thread 1 (startup logging)
 * ============================================================ */
extern std::vector<std::string> test_functions;
extern std::vector<std::string> test_functions_include;
