package com.its.vms.domain;

import com.its.vms.domain.enums.eVmsTextAlign;
import com.its.vms.dto.TbVmsFormObjectDto;
import com.its.vms.service.VmsFontService;
import com.its.vms.service.VmsFormService;
import com.its.vms.xnettcp.vms.protocol.enums.eVmsFormObjectKind;
import com.its.vms.xnettcp.vms.protocol.enums.eVmsImageType;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;

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

    private Integer vmsFormId;
    private Integer vmsFormObjectId;
    private eVmsFormObjectKind objectKind;      // 객체종류
    private int    objectType;      // 객체타입
    private int    objectSize;      // 객체크기
    private int    blinking;        // 점멸 여부
    private int    posX;            // 위치 X
    private int    posY;            // 위치 Y
    private int    dsplWidth;       // 객체넓이
    private int    textWidth;       // 객체넓이
    private int    dsplHeight;      // 객체높이
    private int    bkColor;         // 객체배경색상
    private int    fontNameCd;      // 폰트이름

    private String fontName;
    private int    fontColor;       // 폰트색상
    private int    fontSize;        // 폰트크기
    private int    fontBold;        // 폰트굵기
    private int    textAlign;       // 문자열정열방식
    private String textData;        // 문자열데이터
    private String memSymbLibNmbr;  // 이미지아이디

    private Long   ifscId;
    private int    ifscTrafGradCd;
    private String  trfcFillCd;

    private byte[] imageData;
    private Color  fontClr;

    private eVmsImageType bitmapType;
    private int bitmapId;

    public VmsFormObject(Integer vmsFormId, Integer vmsFormObjectId) {
        this.objectKind = eVmsFormObjectKind.OBJECT_TEXT;
        this.vmsFormId = vmsFormId;
        this.vmsFormObjectId = vmsFormObjectId;
        this.ifscId = 0L;
        this.imageData = null;
        this.fontClr = Color.BLACK;
        this.bitmapId = 0;
    }

    public void setFormObjectInfo(String fontName, TbVmsFormObjectDto obj) {
        this.ifscTrafGradCd = 0;
        this.ifscId = 0L;
        this.trfcFillCd = obj.getTrfcFillCd();

        this.fontName   = fontName;
        this.objectType = obj.getVmsFormObjectTypeCd();     // NUMBER(3)	N			VMS FORM OBJECT 유형 코드
        this.fontNameCd = obj.getVmsFontNameCd();           // NUMBER(3)	N			VMS 글꼴 유형 코드
        this.fontColor  = obj.getVmsFontColrCd();           // NUMBER(3)	N			VMS 글꼴 색상 코드
        this.fontBold   = obj.getVmsFontBold();             // NUMBER(3)	Y			VMS 글꼴 방식 코드(0:Normal,1:Bold)
        this.fontSize   = obj.getVmsFontSize();             // NUMBER(3)	Y	0		VMS 글꼴 크기
        this.textAlign  = obj.getVmsFontAlign();            // NUMBER(1)	Y	0		VMS 표출 문자열정열방식(0:LEFT,1:RIGHT,2:CENTER)
        this.posX       = obj.getVmsDsplXcrdn();            // NUMBER(5)	Y			VMS 표출 X좌표
        this.posY       = obj.getVmsDsplYcrdn();            // NUMBER(5)	Y			VMS 표출 Y좌표
        this.dsplWidth = obj.getVmsDsplWidth();             // NUMBER(5)	Y	0		VMS 표출 넓이
        this.textWidth  = obj.getVmsDsplWidth();            // NUMBER(5)	Y	0		VMS 표출 넓이
        this.dsplHeight = obj.getVmsDsplHeight();           // NUMBER(5)	Y	0		VMS 표출 높이
        this.blinking = obj.getVmsDsplBlinking();         // NUMBER(1)	Y	0		VMS 표출 점멸 여부(0:지속, 1:점멸)
        this.bkColor    = obj.getVmsDsplBkColor();          // NUMBER(1)	Y	0		VMS 표출 배경색상코드
        this.objectSize = obj.getVmsDsplSize();             // NUMBER(7)	Y	0		VMS 표출 크기(문자:문자길이,이미지:이미지전체크기)
        this.textData   = obj.getVmsDsplTxt();
        this.memSymbLibNmbr = obj.getSymbLibNmbr() + "0";

        this.bitmapType = obj.getBitmapType();
        this.bitmapId = obj.getBitmapId();

        if (VmsFormService.isObjectBitmapId(this.objectType)) {
            this.objectKind = eVmsFormObjectKind.OBJECT_BITMAP_ID;
        }
        else if (obj.getVmsFormObjectTypeCd() == 3) {
            // 소통정보배경 이미지
            this.objectKind = eVmsFormObjectKind.OBJECT_BITMAP;
        }
        else {
            this.objectKind = eVmsFormObjectKind.OBJECT_TEXT;
        }
    }

    /**
     * 문자열 객체의 위치좌표 X 를 조정한다.
     */
    public void changeTextPosition() {
        if ("".equals(this.textData)) {
            // 표출데이터가 없는 경우
            return;
        }
// 문자열정열방식
//        typedef enum en_text_align
//        {
//            text_align_left,    /* 0:LEFT */
//            text_align_right,   /* 1:RIGHT */
//            text_align_center,  /* 2:CENTER */
//        } EN_TEXT_ALIGN;

        int style = this.fontBold == 0 ? Font.PLAIN : Font.BOLD;
        Font font = new Font(this.fontName, style, this.fontSize);
        font = font.deriveFont(this.fontSize * 1.35f);

//        FontRenderContext frc = new FontRenderContext(null, true, true);
//        Rectangle2D r2 = font.getStringBounds(this.textData, frc);
//        int textWidth = (int)Math.round(r2.getWidth());

        FontMetrics metrics = new FontMetrics(font){};
        Rectangle2D bounds = metrics.getStringBounds(this.textData, null);
        int textWidth = (int) bounds.getWidth();
        //int correctWidth = this.dsplWidth - textWidth;
        if (this.textAlign == eVmsTextAlign.TEXT_ALIGN_RIGHT.getValue()) {
            // 우측정렬: 좌측에서 글자길이를 뺀다음 만약 음수이면 0으로 설정
            this.posX = (this.posX + this.dsplWidth) - textWidth;
            //this.posX += correctWidth;
        }
        else if (this.textAlign == eVmsTextAlign.TEXT_ALIGN_CENTER.getValue()) {
            // 가운데정렬: 원래 글자의 중앙값을 얻은 다음에 조정된 글자의 1/2 크기를 뺀다음 음수이면 0으로 설정
            this.posX = (this.posX+(this.dsplWidth /2)) - (textWidth/2);
            //this.posX += (correctWidth / 2);
        }

        // 좌측정령은 정렬할 필요가 없음, 단 가변문자인 경우 문자길이를 다시 계산해주어야 함....
        if (this.posX < 0) {
            this.posX = 0;
        }
        this.textWidth = textWidth;
        this.dsplWidth = this.textWidth;
    }

    /**
     * 이미지 바이트배열을 Image 객체로 리턴한다.
     * @return
     */
    private Image getImage() {
        if (this.imageData == null || this.imageData.length == 0) {
            log.error("VmsFormObject.getImage: Image Data null: {}, {}, [{}]", this.vmsFormId, this.vmsFormObjectId, this.memSymbLibNmbr);
            return null;
        }

        try (
                ByteArrayInputStream bis = new ByteArrayInputStream(this.imageData);
        ) {
            return ImageIO.read(bis);
        } catch (IOException e) {
            log.error("VmsFormObject.getImage: IOException: {}, {}, {}", this.vmsFormId, this.vmsFormObjectId, e.getMessage());
        }
        return null;
    }

    /**
     * 폼 이미지에 객체 정보를 그린다.
     *
     * @param g2d
     * @param fontService
     */
    public void drawObject(Graphics2D g2d, VmsFormService formService, VmsFontService fontService, int vmsFormColrCd, float fontSizeRatio) {
        if (VmsFormService.isObjectBitmap(this.objectType)) {
            Image imgBmp = getImage();
            if (imgBmp != null) {
                g2d.drawImage(imgBmp, this.posX, this.posY, this.dsplWidth, this.dsplHeight, null);
            }
        }
        else {
            //기타 문자열
            Font txtFont = new Font(this.fontName, (this.fontBold == 1) ? Font.BOLD : Font.PLAIN, this.fontSize);
            txtFont = txtFont.deriveFont(this.fontSize * fontSizeRatio);
            FontMetrics fm = g2d.getFontMetrics(txtFont);
            if (vmsFormColrCd != this.bkColor) {
                Rectangle2D rect = fm.getStringBounds(this.textData, g2d);
                g2d.setColor(formService.getFormColor(this.bkColor));
                g2d.fillRect(this.posX, this.posY, (int) rect.getWidth(), (int) rect.getHeight());
            }
            g2d.setColor(fontService.getFontColor(this.fontColor));
            g2d.setFont(txtFont);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
            g2d.drawString(this.textData, this.posX, this.posY + fm.getAscent());
        }
        this.fontClr = fontService.getFontColor(this.fontColor);
    }

}
