#pragma once

#include "esphome.h"
namespace esphome {
namespace tuya_cover {

// protocol
#define TUYA_COVER_MAX_LEN 640  // Max length of message value
// #define TUYA_COVER_MAX_LEN 256  // Max length of message value
#define TUYA_COVER_BUFFER_LEN 6 // Length of serial buffer for header + type + length
#define TUYA_COVER_HEADER_LEN 2 // Length of fixed header
#define TUYA_COVER_MSG_LEN 5

// enable/disable reversed motor direction
// Normal = header (55AA) + (00060005) + 050100010011 "(55AA00060005050100010011)
// Reversed = header (55AA) + (00060005) + 050100010112 "(55AA00060005050100010112)"
#define TUYA_COVER_DISABLE_REVERSING { 0x69, 0x01, 0x00, 0x01, 0x00 } //dpid = 105, type = bool, len = 1, value = disable
#define TUYA_COVER_ENABLE_REVERSING { 0x69, 0x01, 0x00, 0x01, 0x01 } //dpid = 105, type = bool, len = 1, value = enable
// Curtain commands
//  Open = header (55AA) + (00060005) + 6604000100 "(55aa000600056604000100)"
// Close = header (55AA) + (00060005) + 6604000101 "(55aa000600056604000101)"
//  Stop = header (55AA) + (00060005) + 6604000102 "(55AA000600056604000102)"
#define TUYA_COVER_OPEN { 0x66, 0x04, 0x00, 0x01, 0x00 } //dpid = 101, type = enum, len = 1, value = OPEN
#define TUYA_COVER_CLOSE { 0x66, 0x04, 0x00, 0x01, 0x01 } //dpid = 101, type = enum, len = 1, value = CLOSE
#define TUYA_COVER_STOP { 0x66, 0x04, 0x00, 0x01, 0x02 } //dpid = 101, type = enum, len = 1, value = STOP

#define TUYA_COVER_SET_POSITION { 0x65, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 } //"65020004000000" //dpid = 2, type = value, len = 4,  value = 0x000000 + 1 byte (0x00-0x64)
struct TUYACOVERCommand
{
    uint16_t header;
    uint8_t version;
    uint8_t command;
    uint16_t length;
    uint8_t value[TUYA_COVER_MAX_LEN];
    uint8_t checksum;
};

struct TUYACOVERMessage
{
    uint8_t dpid;
    uint8_t type;
    uint16_t len;
    uint8_t value[TUYA_COVER_MAX_LEN - 4]; //Subtract dpid, type, len
};

class bcm500ds {
public:
    const uint16_t TUYA_COVER_HEADER = 0x55AA;
    //static const uint16_t TUYA_COVER_VERSION = 0x03;
    const uint8_t TUYA_COVER_VERSION = 0x00;

    const uint8_t tuya_cover_enable_reversing[TUYA_COVER_MSG_LEN]; // = TUYA_COVER_ENABLE_REVERSING;
    const uint8_t tuya_cover_disable_reversing[TUYA_COVER_MSG_LEN];// = TUYA_COVER_DISABLE_REVERSING;
    const uint8_t tuya_cover_open[TUYA_COVER_MSG_LEN];// = TUYA_COVER_OPEN;
    const uint8_t tuya_cover_close[TUYA_COVER_MSG_LEN];// = TUYA_COVER_CLOSE;
    const uint8_t tuya_cover_stop[TUYA_COVER_MSG_LEN];// = TUYA_COVER_STOP;
    uint8_t tuya_cover_pos[8] = TUYA_COVER_SET_POSITION;

    #define HEARTBEAT_INTERVAL_MS 10000
    unsigned long previousHeartbeatMillis = 0;
    // Variables
    TUYACOVERCommand command_{TUYA_COVER_HEADER, TUYA_COVER_VERSION, 0, 0, {}, 0};
    uint8_t uart_buffer_[TUYA_COVER_BUFFER_LEN]{0};

    const char *TAG = "tuya_cover.cover";

    enum TUYACOVERCommandType
    {
        TUYA_COVER_HEARTBEAT = 0x00,
        TUYA_COVER_COMMAND = 0x06,
        TUYA_COVER_RESPONSE = 0x07,
        TUYA_COVER_QUERY_STATUS = 0x08
    };

    enum TUYACOVERdpidType
    {
        TUYA_COVER_DPID_POSITION= 0x65,
        TUYA_COVER_DPID_DIRECTION = 0x64,
        TUYA_COVER_DPID_UNKNOWN = 0x67,
        TUYA_COVER_DPID_ERROR = 0x6E
    };
    
    bool read_command();
    void write_command(TUYACOVERCommandType command, const uint8_t *value, uint16_t length);
    uint8_t checksum();
    
    bcm500ds(): tuya_cover_enable_reversing TUYA_COVER_ENABLE_REVERSING,
                tuya_cover_disable_reversing TUYA_COVER_DISABLE_REVERSING,
                tuya_cover_open TUYA_COVER_OPEN,
                tuya_cover_close TUYA_COVER_CLOSE,
                tuya_cover_stop TUYA_COVER_STOP
                {}

    void loop();
    void setup();
    bool read(){return read_command();}
    void command_close();
    void command_open();
    void command_gotoPos(uint8_t pos);
    void command_stop();
    uint8_t query_pos();
    uint8_t query_value(uint8_t index);
    uint8_t query_cmd();

};

} //namespace tuya_cover
} //namespace esphome
