package com.its.vms.domain;

import com.its.app.utils.ItsUtils;
import com.its.vms.config.ApplicationConfig;
import com.its.vms.dto.TbVmsCtlrDto;
import com.its.vms.dto.TbVmsFormDto;
import com.its.vms.dto.TbVmsScheduleDto;
import com.its.vms.service.VmsFontService;
import com.its.vms.service.VmsFormService;
import com.its.vms.xnettcp.vms.protocol.VmsProtocolConst;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 *  DTO Class
 */
@Slf4j
@Data
public class VmsForm implements Serializable {
    private static final long serialVersionUID = 1L;

    private int     scenarioSeq;        // 폼 표출순서
    private Integer vmsFormId;          // TB_VMS_FORM - VMS FORM ID
    private int     width;              // 폼넓이
    private int     height;             // 폼높이

    private int     dsplHh;             // TB_VMS_FORM - 표출시간(초)
    private int     vmsFormDsplDrctCd;  // TB_VMS_FORM - VMS 메시지 표출 방향 코드
    private int     vmsFormDsplMthdCd;  // TB_VMS_FORM - VMS 메시지 표출 방법 코드
    private int     vmsFormTypeCd;      // TB_VMS_FORM - 폼 종류
    private int     vmsFormColrCd;      // TB_VMS_FORM - 배경색상

    private Integer trfBakImgId;

    private String  vmsSchType;
    int             vmsSchFormType;
    private String  symbLibNmbr;
    private String  strmAddr;

    private boolean success;
    private boolean svcRes;             // 제공결과
    private boolean ftpRes;             // 제공결과

    private String  ftpFileName;
    private String  localFileName;

    // 프로토콜 적용을 위해서
    private byte    fileType;      // 0x01 : 이미지 (JPG)
                                        // 0x02 : 동영상 (AVI)
                                        // 0x03 : URL(스트리밍)
                                        // 0x04 : 소통 이미지
                                        // 0x05 : 표출문구 이미지

    private int     totalCount;
    private int     objectCount;
    private BufferedImage formImage;
    private Graphics2D g2d;
    private List<VmsFormObject> objects;
    private byte[] imageData;

    public VmsForm(Integer vmsFormId) {
        this.vmsFormId = vmsFormId;
        this.totalCount = 0;
        this.objectCount = 0;

        this.success = false;
        this.svcRes = false;
        this.ftpRes = false;
        this.trfBakImgId = 0;

        this.ftpFileName = "";
        this.localFileName = "";
        this.formImage = null;
        this.g2d = null;
        this.objects = new ArrayList<>();
        this.imageData  = null;
    }

    public void clear() {
        this.svcRes = false;
        this.ftpRes = false;
        this.objectCount = 0;
    }

    public void init(int width, int height) {
        this.width = width;
        this.height = height;
        this.formImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        this.g2d = (Graphics2D)formImage.createGraphics();
        this.g2d.setColor(Color.BLACK);
        this.g2d.fillRect(0, 0, this.width, this.height);
    }
    public void initDownload(TbVmsCtlrDto vmsObj, TbVmsFormDto vmsForm, TbVmsScheduleDto schedule) {
        setSuccess(false);
        setSvcRes(false);
        setFtpRes(false);
        setFtpFileName(vmsForm.getFtpFileName());
        setLocalFileName(vmsForm.getLocalFileName());
        setVmsSchType(schedule.getVmsSchType());
        setVmsSchFormType(schedule.getVmsSchFormType());
        setSymbLibNmbr(schedule.getSymbLibNmbr()+"0");
        setStrmAddr(schedule.getStrmAddr());

        setScenarioSeq(vmsObj.getFormManager().count());
        setVmsFormId(vmsForm.getVmsFormId());
        setDsplHh(schedule.getDsplHh());
        setVmsFormDsplDrctCd(vmsForm.getVmsFormDsplDrctCd());
        setVmsFormDsplMthdCd(vmsForm.getVmsFormDsplMthdCd());
        setVmsFormTypeCd(vmsForm.getVmsFormTypeCd());
        setVmsFormColrCd(vmsForm.getVmsFormColrCd());
        setWidth(vmsObj.getVmsWidth());
        setHeight(vmsObj.getVmsHeight());
    }

    public int count() { return this.objectCount; }
    public int total() { return this.totalCount; }

    public VmsFormObject getItem(int idx) {
        if (this.objects.size() > idx) {
            return this.objects.get(idx);
        }
        return null;
    }

    public int addFormObject(VmsFormObject formObj) {
        this.objects.add(formObj);
        this.objectCount = this.objects.size();
        return this.objectCount;
    }

    public VmsFormObject addFormObject(int vmsFormObjectId) {
        VmsFormObject formObj = null;
        if (this.objectCount < this.totalCount) {
            formObj = getItem(this.objectCount);
        }
        else {
            formObj = new VmsFormObject(this.vmsFormId, vmsFormObjectId);
            this.objects.add(formObj);
            this.totalCount++;
        }
        this.objectCount++;
        return formObj;
    }

    private void formClear(Color bkColor) {
        if (this.formImage == null || this.g2d == null) {
            this.formImage = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB);
            this.g2d = (Graphics2D) formImage.createGraphics();  //createGraphics();getGraphics();
        }
        //this.g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        this.g2d.setColor(bkColor);
        this.g2d.fillRect(0, 0, this.width, this.height);
    }

    /**
     * 폼 이미지를 그린다.
     * @param formService
     * @param fontService
     */
    public void drawForm(VmsFormService formService, VmsFontService fontService) {
        formClear(formService.getFormColor(this.vmsFormColrCd));

        // 폼에 속한 객체를 모두 그린다.
        int objCnt = count();
        for (int jj = 0; jj < objCnt; jj++) {
            VmsFormObject pFormObj = getItem(jj);
            pFormObj.drawObject(this, fontService);
        } // 폼의 객체수 만큼 객체를 폼에 그린다.

        // 이미지를 바이트배열로 변환
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(this.formImage, "bmp", out);
        } catch (IOException e) {
            log.error("VmsForm.drawForm: Image to byte array failed: {}, {}", this.vmsFormId, e.getMessage());
        }
        this.imageData = out.toByteArray();
    }

    /**
     * 폼의 스케쥴 유형에 따라 폼 파일 형식을 결정한다.
     */
    public void calVmsSchFormType() {
        this.success = true;
        switch (eVmsScheduleType.getValue(this.vmsSchFormType)) {
            case eSchTp_traffic:    //  = 0,    //0:교통,
            case eSchTp_incident:   //  = 1,    //1:돌발,
            case eSchTp_gongsa:     //  = 2,    //2:공사행사,
            case eSchTp_deture:     //  = 4,    //4:우회,
            case eSchTp_congest:    //  = 5,    //5:정체,
                this.fileType = VmsProtocolConst.P_FILE_TYPE_TRAFFIC;
                break;
            case eSchTp_hongbo:     //  = 3,    //3:홍보,
            case eSchTp_safe:       //  = 6,    //6:안전,
            case eSchTp_atmp:       //  = 9,    //9:대기환경
            case eSchTp_park:       //  = 10,   //10:주차정보
            case eSchTp_evehicle:   //  = 11,   //11:긴급차량우선신호
                this.fileType = VmsProtocolConst.P_FILE_TYPE_TEXT;
                break;
            case eSchTp_video:      //  = 7,    //7:동영상,
                this.fileType  = VmsProtocolConst.P_FILE_TYPE_VIDEO;
                this.ftpFileName = ApplicationConfig.FTP_VIDEO + File.separator + this.strmAddr;
                //폼디렉토리에 동영상파일을 복사해서 처리하도록 수정해야지..........
                break;
            case eSchTp_stream:     //  = 8,    //8:스트리밍영상
                this.fileType    = VmsProtocolConst.P_FILE_TYPE_STREAM;
                this.ftpFileName = this.strmAddr;
                break;
            default:
                this.fileType = VmsProtocolConst.P_FILE_TYPE_TEXT;
                this.success = false;
                break;
        }
    }

    public void saveToFile() {
        File formFile = new File(this.localFileName);
        if (formFile.exists()) {
            formFile.delete();
        }
        if (this.imageData != null) {
            ItsUtils.saveByteArrayToFile(this.localFileName, this.imageData);
        }
        else {
            log.error("VmsForm.saveToFile: Image data is null: {}", this.vmsFormId);
        }
    }
}

