#pragma once
#include <cereal/archives/binary.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/string.hpp>

namespace fm
{
    enum class side_type
    {
        local  = 0,
        tftp   = 1,
        config = 2
    };

    struct side_description
    {
        side_type   s_type;
        std::string filepath;

        template<class Archive>
        void serialize(Archive & archive)
        {
            archive(s_type, filepath);
        }
    };
}

enum class cmd_dma_debugg
{
    start = 0,
    stop = 1,
    reset = 2,
    reinit = 3,
    modcod = 4,
    log_bool = 5,
    data_mode = 6,
    default_params = 7,
    buc_voltage = 8,
    lnb_voltage = 9,
    _10mhz_tx = 10,
    _10mhz_rx = 11,
    powerdown_plata = 12,
    _10MHz_out = 13,
    current_state_tx = 14,
    current_state_oib = 15,
    save_config = 16,
    begin_save_config = 17
};

enum class name_classes_qos
{
    realtime1 = 0,
    realtime2,
    realtime3,
    critical1,
    critical2,
    critical3,
    cir,
    pir,
    wcr1,
    wcr2,
    wcr3,
    enable,
    ful_node
};

enum class cmd_get_dma_debugg_enum
{
    speed_tx = 0,
    speed_rx = 1,
    modcod = 2,
    drop_bad_rx = 3,
    drop_full_rx = 4,
    packet_ok_rx = 5,
    packet_little_tx = 6,
    packet_big_tx = 7,
    bad_modcod_tx = 8,
    bad_length_tx = 9,
    reset_cnt_rx = 10,
    data_mode = 11,
    buc_voltage = 12,
    lnb_voltage = 13,
    _10mhz_tx = 14,
    _10mhz_rx = 15,
    powerdown_plata = 16,
    _10MHz_out = 17,
    current_state_tx = 18,
    real_dpdi_shift = 19,
    freq_error_offset = 20,
    freq_fine_estimate = 21,
    speed_tx_iface = 22,
    speed_rx_iface = 23,
    current_state_oib = 24,
    ratio_signal_signal = 25,
    status_init = 26
};

enum class cmd_10g_config
{
    udp_payload_lenght = 0,
    local_ip = 1,
    dest_ip = 2,
    gateway_ip = 3,
    subnet_mask = 4,
    udp_source_port = 5,
    udp_dest_port = 6,
    local_mac_31_0 = 7,
    local_mac_32_47 = 8,
    mtx_chan0 = 9,
    mtx_chan1 = 10
};

enum class cmd_level_dem
{
    //! ОСШ на входе
    snr = 0,
    //! RSSI на входе
    rssi = 1,
    sym_sync_lock = 2,
    freq_search_lock = 3,
    afc_lock = 4,
    pkt_sync = 5,
    phase_inv = 6,
    afc_error = 7,
    sym_error = 8,
    fine_freq_error = 9,
    crs_freq_error = 10,
    gc_gain_aru = 11,
    rollof = 12,
    carrier_lock = 13,
    filt_adapt_lock = 14,
    snr_acm = 15,
    modcod_tx = 16
};

enum class interface_value
{
    all         = 0,
    sat0        = 1,
    gigabit     = 2,
    modulator   = 3,
    demodulator = 4
};

enum class zynq_value
{
    ps_volt = 0,
    pl_volt = 1,
    adrv_temp = 2,
    pl_temp = 3,
    ps_temp = 4,
    adrv_temp2 = 5
};

enum class modulator_value
{
    lo_freaquency = 0,
    baud_rate = 1,
    temp_treshold = 2,
    mod_reset = 3,
    modcod = 4,
    rollof = 5,
    mode_transmitt = 6,
    if_overload = 7,
    gold_seq = 8
};

enum class demodulator_value
{
    lo_freaquency = 0,
    baud_rate = 1,
    freq_search = 2,
    demod_reset = 3,
    fec_frame_size = 4,
    rvt = 5,
    mode_gain_control = 6,
    sig_min = 7,
    sig_max = 8,
    afc_rst = 9,
    mode_demod = 10,
    gold_seq = 11,
    attitude_signals = 12,
    is_reset_CinC = 13
};
enum class getdemodulator_value
{
    lo_freaquency = 0,
    baud_rate = 1,
    dummy_counter = 2,
    modcod = 3,
    mode_gain_control = 4,
    sig_min = 5,
    sig_max = 6,
    rvt = 7,
    fec_size = 8,
    mode_demod = 9,
    cnt_bad_lock_cinc = 10,
    gold_seq = 11,
    attitude_signals = 12,
    cnt_dem_time_sinc = 13,
    cnt_dem_lock_afc = 14,
    cnt_dem_sync_pack = 15,
    cnt_dem_sinc_frec_corse = 16,
    freq_lock_estimate = 17,
    freq_fine_estimate = 18,
    is_reset_CinC = 19,
    type_pack = 20,
    is_pilots = 21
};

enum class gain_value
{
    tx1 = 0,
    tx2 = 1,
    rx1 = 2,
    rx2 = 3,
    txpwd = 4,
    rxpwd = 5
};

enum class acm_value
{
    enable = 0,
    modcod_min = 1,
    modcod_max = 2,
    attenuation_min = 3,
    attenuatin_max = 4,
    required_snr = 5
};

enum class cmd_radio
{
    tx1 = 0,
    tx2 = 1,
    rx1 = 2,
    rx2 = 3,
    global = 4,
    global2 = 5
};

enum class network_value
{
    network = 0,
    mode_interface = 1,
    version = 2,
    mask = 3,
    gateway = 4,
    dhcp_on = 5,
    dhcp_range = 6,
    network_data = 7,
    chip_id = 8,
    serial = 9,
    mac_eth0 = 10,
    mac_eth1 = 11,
    name_serv = 12,
    network_debug_send = 13,
    network_port_metric = 14,
    network_port_data = 15,
    periodic_send_metrics = 16,
    if_debug_mode = 17
};

enum class cmd_type
{
    login     = 0,
    exit      = 1,
    ping      = 2,
    tracert   = 3,
    interface = 4,
    copy      = 5,
    abort     = 6,
    set_demodulator_frequency = 7,
    get_demodulator_frequency = 8,
    set_gain_param = 9,
    get_gain_param = 10,
    radio_on_of = 11,
    modulator_param = 12,
    zynq_param = 13,
    set_demodulator_param = 14,
    get_demodulator_param = 15,
    get_modulator_param = 16,
    set_network = 17,
    get_level_dmd = 18,
    set_10g_config = 19,
    set_dma_debugg = 20,
    get_dma_debugg = 21,
    set_baudrate_rollof_dmd = 22,
    set_acm_params = 23,
    get_acm_params = 24,
    set_params_dpdi = 25,
    get_params_dpdi = 26,
    get_network = 27,
    set_qos_settings = 28,
    get_qos_settings = 29,
    set_lbq_params = 30
};

struct cmd_lbq_params
{
    uint32_t tick_ms;
    uint32_t bucket_size;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(tick_ms, bucket_size);
    }
};


struct cmd_get_network
{
    std::string network;
    network_value net_val;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(net_val, network);
    }
};

struct cmd_set_network
{
    std::string network;
    network_value net_val;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(net_val, network);
    }
};

struct dpdi_parameters
{
    uint8_t latitude_station_grad = 0;
    uint8_t latitude_station_minute = 0;
    uint8_t longitude_station_grad = 0;
    uint8_t longitude_station_minute = 0;
    uint8_t longitude_sattelite_grad = 0;
    uint8_t longitude_sattelite_minute = 0;
    bool is_delay_window = 0;
    uint32_t max_delay = 1;
    uint32_t min_delay = 0;
    uint32_t freq_offset = 0;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(latitude_station_grad, latitude_station_minute,
                longitude_station_grad, longitude_station_minute,
                longitude_sattelite_grad, longitude_sattelite_minute,
                is_delay_window, max_delay, min_delay, freq_offset);
    }
};


struct ACM_parameters_serv
{
    double snr_treashold = 0;
    double snr_treashold_acm = 0.5;
    uint32_t period_pack = 15;
    uint8_t max_modcod = 4;
    uint8_t min_modcod = 4;
    int max_attenuation = 0;
    int min_attenuation = 0;
    bool enable = false;
    bool enable_auto_atten = false;
};

struct cmd_get_acm_param
{
    double snr_treashold = 0;
    double snr_treashold_acm = 0.5;
    uint32_t period_pack = 15;
    uint8_t max_modcod = 4;
    uint8_t min_modcod = 4;
    int max_attenuation = 0;
    int min_attenuation = 0;
    bool enable = false;
    bool enable_auto_atten = false;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(enable, max_attenuation, max_modcod, min_attenuation, min_modcod, snr_treashold, enable_auto_atten, snr_treashold_acm, period_pack);
    }
};

struct cmd_set_qos_settings
{
    std::string node;
    name_classes_qos class_qos;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(node, class_qos);
    }
};

struct cmd_get_qos_settings
{
    std::string node;
    name_classes_qos class_qos;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(node, class_qos);
    }
};

struct cmd_set_acm_param
{
    ACM_parameters_serv acm_params;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(acm_params.enable, acm_params.max_attenuation, acm_params.max_modcod, acm_params.min_attenuation, acm_params.min_modcod, acm_params.snr_treashold, acm_params.enable_auto_atten, acm_params.snr_treashold_acm, acm_params.period_pack);
    }
};


struct cmd_get_dma_debug
{
    std::string value;
    cmd_get_dma_debugg_enum dma_debugg;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(dma_debugg, value);
    }
};

struct cmd_set_dma_debug
{
    std::string value;
    cmd_dma_debugg dma_debugg;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(dma_debugg, value);
    }
};

struct cmd_set_10g_config
{
    std::string value;
    cmd_10g_config _10g_config;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(_10g_config, value);
    }
};

struct cmd_get_level_dem
{
    double value;
    cmd_level_dem lvl_dem;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(lvl_dem, value);
    }
};

struct cmd_zynq_param
{
    zynq_value cmd_zynq;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(cmd_zynq);
    }
};

struct radio_enable
{
    cmd_radio cmd_radio_;
    bool enbl;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(cmd_radio_, enbl);
    }
};

struct cmd_set_modulator_param
{
    modulator_value mod_val;
    long long value;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(mod_val,value);
    }
};
struct cmd_get_modulator_param
{
    modulator_value mod_val;
    uint32_t value;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(mod_val,value);
    }
};

struct cmd_set_rollof_and_demod
{
    double baudrate;
    double rollof;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(baudrate,rollof);
    }
};


struct cmd_set_demodulator_param
{
    demodulator_value demod_val;
    uint32_t value;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(demod_val,value);
    }
};

struct cmd_get_demodulator_param
{
    getdemodulator_value demod_val;
    uint32_t value;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(demod_val,value);
    }
};

struct set_gain_par
{
    gain_value g_val;
    double _gain;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(g_val,_gain);
    }
};

struct get_gain_par
{
    gain_value g_val;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(g_val);
    }
};

struct set_dem_freq_cmd
{
    uint32_t frequency;
    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(frequency);
    }
};

enum class response_type
{
    ok          = 0,
    error       = 1,
    in_progress = 3,
    abort       = 4,
    busy        = 5
};

enum class access_rights
{
    not_allowed = 0,
    user        = 1,
    admin       = 2
};

struct cmd_header
{
    uint32_t id;
    cmd_type cmd;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(id, cmd);
    }
};

struct login_cmd
{
    std::string username;
    std::string pass;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(username, pass);
    }
};

struct ping_cmd
{
    std::string ip_address;
    size_t      count;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(ip_address, count);
    }
};

struct tracert_cmd
{
    std::string ip_address;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(ip_address);
    }
};

struct interface_cmd
{
    interface_value val;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(val);
    }
};

struct copy_cmd
{
    fm::side_description src;
    fm::side_description dst;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(src, dst);
    }
};

struct response_header
{
    uint32_t      id;
    cmd_type      cmd;
    response_type rsp;

    template<class Archive>
    void serialize(Archive & archive)
    {
        archive(id, cmd, rsp);
    }
};
