#include "bsp_gate.h"
#include "bsp_modbus.h"

#include "kit_data.h"
#include "kit_debug.h"

extern ModbusCommData modbus_comm_data;
int16_t bsp_gate_get_read_buf_addr(GateItem *item, uint8_t len)
{
    int16_t addr = -1;
    if((item != NULL) && (item->read_buf_idx + len < item->read_buf_size))
    {
        addr = item->read_buf_idx;
        item->read_buf_idx += len;
    }
    return addr;
}

int16_t bsp_gate_get_write_buf_addr(GateItem *item, uint8_t len)
{
    int16_t addr = -1;
    if((item != NULL) && (item->write_buf_idx + len < item->write_buf_size))
    {
        addr = item->write_buf_idx;
        item->write_buf_idx += len;
    }
    return addr;
}

void bsp_gate_push_read_data(GateItem *item, uint16_t addr, uint8_t *buf, uint8_t len)
{
    if((item != NULL) && (addr + len < item->read_buf_size))
    {
        kit_copy_buf(&item->read_buf[addr], buf, len);
    }
}

void bsp_gate_push_write_data(GateItem *item, uint16_t addr, uint8_t *buf, uint8_t len)
{
    if((item != NULL) && (addr + len < item->write_buf_size))
    {
        kit_copy_buf(&item->write_buf[addr], buf, len);
    }
}

uint16_t bsp_gate_get_read_data(GateItem *item, uint16_t addr)
{
    uint16_t data = 0;
    if((item != NULL) && (addr < item->read_buf_size))
    {
        data = item->read_buf[addr];
    }
    return data;
}


uint16_t bsp_gate_get_write_data(GateItem *item, uint16_t addr)
{
    uint16_t data = 0;
    if((item != NULL) && (addr < item->write_buf_size))
    {
        data = item->write_buf[addr];
        
    }
    return data;
}


//addr为gate 写bug中的相对地址,返回值表示是否可以写数据
bool bsp_gate_set_data(GateItem *item, uint16_t addr, uint16_t data)
{
    bool res = false;
    ModbusHead *head;
    ModbusTask *cur_task;
    int32_t i, idx, acc_addr;
    ModbusItem * mb_item = modbus_comm_data.head_item;
    
    if(item->is_user_write_fun == true)
    {
       res = false;        
    }
    if((item != NULL) && (addr < modbus_comm_data.gate_write_data_cnt) && (item->is_user_write_fun == false)
    && ((item->is_write_check == false) || (item->write_buf[addr] != data)))
    {
        idx = 0;
        while(mb_item != NULL)
        {
            if((addr >= mb_item->gate_write_data_start_addr) 
            && (addr < mb_item->gate_write_data_end_addr))
            {
                acc_addr = mb_item->gate_write_data_start_addr;
                for(i = 0; i < mb_item->task_num; i++)
                {
                    cur_task = &mb_item->modbus_task[i];
                    head = cur_task->head;
                    if((head->fun_code == 0x06) || (head->fun_code == 0x05))
                    {
                        //gate中地址为相对地址，需要查询到绝对地址
                        if((addr >= acc_addr) && (addr < (head->reg_num + acc_addr)))
                        {
                            if(mb_item->gate_write_data_absolute_addr == MODBUS_GATE_FREE_ADDR)
                            {
                                mb_item->gate_write_try_cnt = 0;
                                mb_item->gate_write_data_addr = addr;
                                mb_item->gate_write_data_head = head;
                                mb_item->gate_write_data_value = data;
                                mb_item->gate_write_dev_addr = head->slave_addr;
                                item->write_data_addr_list[idx] = addr;
                                item->write_data_mb_list[idx] = mb_item;
                                //计算出modbus绝对地址
                                mb_item->gate_write_data_absolute_addr = head->reg_addr + addr - acc_addr;
                                res = true;
                            }
                            return res;
                        }
                        acc_addr += head->reg_num;
                    }
                }
            }
            idx++;
            mb_item = mb_item->next_item;
        }
    }

    return res;
}

uint16_t bsp_gate_copy_from_write_data(GateItem *item, uint8_t *buf)
{
    uint16_t len = item->write_buf_idx << 1;
    kit_copy_buf(buf, item->write_buf, len);
    
    return len;
}


bool bsp_gate_has_data_change(GateItem *item, uint16_t addr)
{
    uint32_t i;
    bool res = false;
    for(i = 0; i < MODBUS_INSTANCE_NUM; i++)
    {
        if((item->write_data_addr_list[i] == addr)
        && (item->write_data_mb_list[i] != NULL))  
        {
            bsp_modbus_poll(item->write_data_mb_list[i], false);
            res = (item->write_data_mb_list[i]->gate_write_data_absolute_addr != MODBUS_GATE_FREE_ADDR);
            break;
        }
    }
    return res;
}

