#ifndef PICO_API_HPP
#define PICO_API_HPP

#define OK_CODE 0xBB

#include "src/basic_proto_dispatcher.hpp"

class pico_server_dispatcher : public basic_proto_dispatcher {
    protected:
        int32_t points_value = 0;
        uint32_t sample_rate = 0;
        uint32_t measurement_times = 0;
        uint32_t number_channels = 0;
        std::vector<PS4000A_CHANNEL> channels;
        std::vector<uint32_t> points_vector;
        uint32_t premeasurement_percentage = 0;
        PS4000A_CONDITION* conditions;
        PS4000A_CHANNEL trig_channel = PS4000A_CHANNEL_A;
        PS4000A_THRESHOLD_DIRECTION th_direction = PS4000A_ABOVE;
        int16_t threshold = 0;
        int16_t trig_delay = 0;
        int16_t trig_autoTrigger_ms = 0;
        int16_t handle = 0; // *
        uint32_t nbytes_sent = 0; // *

        std::vector<std::vector<int16_t*>> data_buffer_vec;
        bool is_buffers_allocated = false;

        std::string statusString;

        int pico_stop();
        int pico_open();
        int pico_close();
        int pico_get_params();
        int pico_set_rate();
        int pico_set_points();
        int pico_set_times();
        int pico_channel_configure();
        int pico_trigger_configure();
        int pico_set_premeasurement();
        int pico_measurement();
        int pico_status();

        std::vector<std::vector<int16_t>> split_packets(int i, int j);
        int pico_send_points();

    public:
        inline pico_server_dispatcher(CActiveSocket* SocketActive) : basic_proto_dispatcher(SocketActive) {
            // Map protocol command values to matching no-arg handlers
            command_callbacks[0x01] = [this]() { return this->pico_open(); };
            command_callbacks[0x03] = [this]() { return this->pico_close(); };
            command_callbacks[0x04] = [this]() { return this->pico_get_params(); };
            command_callbacks[0x06] = [this]() { return this->pico_set_points(); };
            command_callbacks[0x07] = [this]() { return this->pico_set_rate(); };
            command_callbacks[0x08] = [this]() { return this->pico_set_times(); };
            command_callbacks[0x09] = [this]() { return this->pico_channel_configure(); };
            command_callbacks[0x0A] = [this]() { return this->pico_trigger_configure(); };
            command_callbacks[0x0B] = [this]() { return this->pico_set_premeasurement(); };
            command_callbacks[0x0E] = [this]() { return this->pico_stop(); };
            command_callbacks[0x20] = [this]() { return this->pico_measurement(); };
            command_callbacks[0x30] = [this]() { return this->pico_status(); };
            command_callbacks[0x1E] = [this]() { return this->stopSession(); };
            command_callbacks[0xBB] = [this]() { return this->pico_send_points(); };
            command_callbacks[0x3D] = [this]() { return 0; }; // packet ACK callback
            command_callbacks[0x3E] = [this]() { return 0; }; // all packets ACK callback
        }
};

#endif