package org.wcs.plugin.lxLed;

import org.wcs.model.bo.tuple.Tuple2;
import org.wcs.plugin.lxLed.model.LedAreaData;
import org.wcs.utils.AppListUtils;
import org.wcs.utils.Converter;

import java.util.ArrayList;
import java.util.List;

/**
 * 灵信LED屏数据创建器
 */
public class LedDataCreator {

    /**
     * 屏幕宽
     */
    private short ledWight = 0;

    /**
     * 屏幕高
     */
    private short ledHeight = 0;

    /**
     * 颜色类型：1-单色；2-双色；3-三色
     */
    private byte ledColorType = 1;

    /**
     * 区域数据列表
     */
    public List<LedAreaData> areaDataList;


    /**
     * 设置屏幕参数
     * @param ledWight 屏幕宽
     * @param ledHeight 屏幕高
     * @param ledColorType 颜色类型：1-单色；2-双色；3-三色
     */
    public void setLedParam(short ledWight, short ledHeight, byte ledColorType) {
        this.ledWight = ledWight;
        this.ledHeight = ledHeight;
        this.ledColorType = ledColorType;
    }

    /**
     * 添加区域数据
     * @param areaData 区域数据
     */
    public void addAreaData(LedAreaData areaData) {
        if (areaDataList == null) {
            areaDataList = new ArrayList<>();
        }
        areaDataList.add(areaData);
    }

    /**
     * 创建数据
     * @return 数据
     */
    public Tuple2<String,List<Byte>> create() {
        if(ledWight <= 0 || ledHeight <= 0) {
            return new Tuple2<>("屏幕宽或屏幕高不能小于等于0", null);
        }
        Tuple2<String, List<Byte>> program = createProgram();
        if(program.item1 != null) {
            return program; // 创建失败
        }
        List<Byte> dataBytes = new ArrayList<>();
        // 起始数据
        dataBytes.addAll(createStartBytes());
        // 控制器型号 ---- 默认全部型号
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        // 屏幕参数
        dataBytes.addAll(AppListUtils.transfer(Converter.toBytes(ledWight)).reversed()); // 屏幕宽
        dataBytes.addAll(AppListUtils.transfer(Converter.toBytes(ledHeight)).reversed()); // 屏幕高
        // 颜色类型
        dataBytes.add(ledColorType);
        // 节目个数
        dataBytes.add((byte) 1);
        // 不用字节
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        dataBytes.add((byte) 0);
        // 节目数据
        dataBytes.addAll(program.item2);
        // 结束数据
        dataBytes.addAll(createEndBytes());
        return new Tuple2<>(null, dataBytes);
    }

    /**
     * 创建节目
     * @return 节目
     */
    private Tuple2<String,List<Byte>> createProgram() {
        if(areaDataList == null || areaDataList.isEmpty()) {
            return new Tuple2<>("节目未添加区域", null);
        }

        List<Byte> bytes = new ArrayList<>();
        // 节目号
        bytes.add((byte) 0);
        // 节目数据大小 ---- 先临时赋值
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        //节目中区域个数
        bytes.add((byte) areaDataList.size());
        // 节目循环播放数
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        // 循环播放次数
        bytes.add((byte) 1);
        // 节目定时属性 ---- 无效
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        bytes.add((byte) 0);
        // 区域数据
        for (LedAreaData areaData : areaDataList) {
            bytes.addAll(areaData.create());
        }
        // 节目数据大小
        int size = bytes.size();
        byte[] bytesSize = Converter.toBytes(size);
        bytes.set(1, bytesSize[3]);
        bytes.set(2, bytesSize[2]);
        bytes.set(3, bytesSize[1]);
        bytes.set(4, bytesSize[0]);
        bytes.addAll(createEndBytes());
        return new Tuple2<>(null, bytes);
    }

    /**
     * 创建起始字节
     * @return 起始字节
     */
    private List<Byte> createStartBytes() {
        List<Byte> bytes = new ArrayList<>();
        // 起始字节
        bytes.add((byte) 0x55);
        bytes.add((byte) 0xAA);
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x00);
        // 地址
        bytes.add((byte) 0x01);
        // 标志
        bytes.add((byte) 0x01);
        // 操作码
        bytes.add((byte) 0x00);
        bytes.add((byte) 0xD9);
        // 保留
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x00);
        // 帧序号
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x00);
        // 总长度 ---- 默认不给，控制卡可自动计算
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x00);
        // 帧长度 ---- 默认不给，控制卡可自动计算
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x00);

        return bytes;
    }

    /**
     * 创建结束字节
     * @return 结束字节
     */
    private List<Byte> createEndBytes() {
        List<Byte> bytes = new ArrayList<>();
        // 结束字节
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x00);
        bytes.add((byte) 0x0D);
        bytes.add((byte) 0x0A);

        return bytes;
    }

}
