package com.its.op.entity.its.scrs;

import com.its.op.dto.its.scrs.TbScSgnlCtlrDto;
import com.its.op.dto.its.scrs.TbScSgnlCtlrPhaseDto;
import com.its.op.dto.its.scrs.TbScSgnlIxrSttsDto;
import com.its.op.global.CodeManager;
import com.its.utils.ItsUtils;
import com.its.utils.SysUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;

import javax.persistence.*;
import java.io.Serializable;

/**
 * 신호 제어기 Entity Class
 */
@Getter
@NoArgsConstructor//(access = AccessLevel.PROTECTED)
@Builder
@AllArgsConstructor
@ApiModel("신호 제어기")
@Entity
@Table(name = "TB_SC_SGNL_CTLR")
public class TbScSgnlCtlr implements Serializable {
    private static final long serialVersionUID = 1L;

    @ApiModelProperty("신호 교차로 번호")  // N NUMBER(4)
    @Id
    @Column(name = "SGNL_IXR_NMBR", nullable = false, columnDefinition = "NUMBER", length = 4)
    private Integer sgnlIxrNmbr;

    @ApiModelProperty("교차로 명")  // Y VARCHAR2(50)
    @Column(name = "IXR_NM", length = 50)
    private String ixrNm;

    @ApiModelProperty("X 좌표")  // Y NUMBER(10)
    @Column(name = "X_CRDN", columnDefinition = "NUMBER", length = 10)
    private Long xCrdn;

    @ApiModelProperty("Y 좌표")  // Y NUMBER(10)
    @Column(name = "Y_CRDN", columnDefinition = "NUMBER", length = 10)
    private Long yCrdn;

    @ApiModelProperty("A링 1현시 코드")  // Y NUMBER(7)
    @Column(name = "ARING_1PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer aring1phasCd;

    @ApiModelProperty("A링 2현시 코드")  // Y NUMBER(7)
    @Column(name = "ARING_2PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer aring2phasCd;

    @ApiModelProperty("A링 3현시 코드")  // Y NUMBER(7)
    @Column(name = "ARING_3PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer aring3phasCd;

    @ApiModelProperty("A링 4현시 코드")  // Y NUMBER(7)
    @Column(name = "ARING_4PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer aring4phasCd;

    @ApiModelProperty("A링 5현시 코드")  // Y NUMBER(7)
    @Column(name = "ARING_5PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer aring5phasCd;

    @ApiModelProperty("A링 6현시 코드")  // Y NUMBER(7)
    @Column(name = "ARING_6PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer aring6phasCd;

    @ApiModelProperty("A링 7현시 코드")  // Y NUMBER(7)
    @Column(name = "ARING_7PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer aring7phasCd;

    @ApiModelProperty("A링 8현시 코드")  // Y NUMBER(7)
    @Column(name = "ARING_8PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer aring8phasCd;

    @ApiModelProperty("B링 1현시 코드")  // Y NUMBER(7)
    @Column(name = "BRING_1PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer bring1phasCd;

    @ApiModelProperty("B링 2현시 코드")  // Y NUMBER(7)
    @Column(name = "BRING_2PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer bring2phasCd;

    @ApiModelProperty("B링 3현시 코드")  // Y NUMBER(7)
    @Column(name = "BRING_3PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer bring3phasCd;

    @ApiModelProperty("B링 4현시 코드")  // Y NUMBER(7)
    @Column(name = "BRING_4PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer bring4phasCd;

    @ApiModelProperty("B링 5현시 코드")  // Y NUMBER(7)
    @Column(name = "BRING_5PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer bring5phasCd;

    @ApiModelProperty("B링 6현시 코드")  // Y NUMBER(7)
    @Column(name = "BRING_6PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer bring6phasCd;

    @ApiModelProperty("B링 7현시 코드")  // Y NUMBER(7)
    @Column(name = "BRING_7PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer bring7phasCd;

    @ApiModelProperty("B링 8현시 코드")  // Y NUMBER(7)
    @Column(name = "BRING_8PHAS_CD", columnDefinition = "NUMBER", length = 7)
    private Integer bring8phasCd;

    @OneToOne
    @JoinColumn(insertable=false, updatable=false, name="SGNL_IXR_NMBR", referencedColumnName = "SGNL_IXR_NMBR")
    @NotFound(action = NotFoundAction.IGNORE)
    private TbScSgnlIxrStts stts;

    public Double getXPos() {
        String xCrdn = String.format("%09d", this.xCrdn);
        Double x_crdn = (Integer.parseInt(xCrdn) / 1000000.);
        return x_crdn;
    }
    public Double getYPos() {
        String yCrdn = String.format("%09d", this.yCrdn);
        Double y_crdn = (Integer.parseInt(yCrdn) / 1000000.);
        return y_crdn;
    }
    public TbScSgnlCtlrDto toDto() {
//        String xCrdn = String.format("%09d", this.xCrdn);
//        String yCrdn = String.format("%09d", this.yCrdn);
//        Double x_crdn = (Integer.parseInt(xCrdn) / 1000000.);
//        Double y_crdn = (Integer.parseInt(yCrdn) / 1000000.);
        return TbScSgnlCtlrDto.builder()
                .sgnlIxrNmbr(this.sgnlIxrNmbr)
                .xCrdn(getXPos())
                .yCrdn(getYPos())
                .aring1phasCd(this.aring1phasCd)
                .aring2phasCd(this.aring2phasCd)
                .aring3phasCd(this.aring3phasCd)
                .aring4phasCd(this.aring4phasCd)
                .aring5phasCd(this.aring5phasCd)
                .aring6phasCd(this.aring6phasCd)
                .aring7phasCd(this.aring7phasCd)
                .aring8phasCd(this.aring8phasCd)
                .bring1phasCd(this.bring1phasCd)
                .bring2phasCd(this.bring2phasCd)
                .bring3phasCd(this.bring3phasCd)
                .bring4phasCd(this.bring4phasCd)
                .bring5phasCd(this.bring5phasCd)
                .bring6phasCd(this.bring6phasCd)
                .bring7phasCd(this.bring7phasCd)
                .bring8phasCd(this.bring8phasCd)
                .build();
    }

    public TbScSgnlCtlr(Integer sgnlIxrNmbr) {
        this.sgnlIxrNmbr = sgnlIxrNmbr;
    }

    public void updateInfo(TbScSgnlCtlrDto.TbScSgnlCtlrUpdReq req) {
        this.xCrdn = (long)(req.getXCrdn() * 1000000L);
        this.yCrdn = (long)(req.getYCrdn() * 1000000L);

        this.aring1phasCd = req.getAring1phasCd();
        this.aring2phasCd = req.getAring2phasCd();
        this.aring3phasCd = req.getAring3phasCd();
        this.aring4phasCd = req.getAring4phasCd();
        this.aring5phasCd = req.getAring5phasCd();
        this.aring6phasCd = req.getAring6phasCd();
        this.aring7phasCd = req.getAring7phasCd();
        this.aring8phasCd = req.getAring8phasCd();

        this.bring1phasCd = req.getBring1phasCd();
        this.bring2phasCd = req.getBring2phasCd();
        this.bring3phasCd = req.getBring3phasCd();
        this.bring4phasCd = req.getBring4phasCd();
        this.bring5phasCd = req.getBring5phasCd();
        this.bring6phasCd = req.getBring6phasCd();
        this.bring7phasCd = req.getBring7phasCd();
        this.bring8phasCd = req.getBring8phasCd();
    }

    public TbScSgnlCtlrPhaseDto toPhaseDto() {
        TbScSgnlCtlrPhaseDto dto = TbScSgnlCtlrPhaseDto.builder()
                .sgnlIxrNmbr(this.sgnlIxrNmbr)
                .dirA(0)
                .degAI(0)
                .degAO(0)
                .dirB(0)
                .degBI(0)
                .degBO(0)
                .build();

        if (this.stts == null) {
            dto.setCntlStts(3); // 통신장애
            return dto;
        }

        // Dir, 1: 직진, 2: 좌회전, 5: 보행자
        dto.setCntlMode(this.stts.getCntlMode());   // 제어모드(0: TRC, 1: TOD, 2: MAN)
        dto.setCntlStts(this.stts.getCntlStts());   // 제어상태(0: 온라인, 1: 오프라인, 2: 트랜스, 3: 통신장애)
        dto.setSpclCntl(this.stts.getSpclCntl());   // 특수제어(0: 없음, 1: 점멸, 2: 소등, 3: 수동, 4: 감응)

        int aRingPhase = -1;
        int bRingPhase = -1;
        switch(this.stts.getPrstAringPhas()) {
            case 1: aRingPhase = this.aring1phasCd; break;
            case 2: aRingPhase = this.aring2phasCd; break;
            case 3: aRingPhase = this.aring3phasCd; break;
            case 4: aRingPhase = this.aring4phasCd; break;
            case 5: aRingPhase = this.aring5phasCd; break;
            case 6: aRingPhase = this.aring6phasCd; break;
            case 7: aRingPhase = this.aring7phasCd; break;
            case 8: aRingPhase = this.aring8phasCd; break;
        }
        switch(this.stts.getPrstBringPhas()) {
            case 1: bRingPhase = this.bring1phasCd; break;
            case 2: bRingPhase = this.bring2phasCd; break;
            case 3: bRingPhase = this.bring3phasCd; break;
            case 4: bRingPhase = this.bring4phasCd; break;
            case 5: bRingPhase = this.bring5phasCd; break;
            case 6: bRingPhase = this.bring6phasCd; break;
            case 7: bRingPhase = this.bring7phasCd; break;
            case 8: bRingPhase = this.bring8phasCd; break;
        }
        if (aRingPhase >= 1000000) {
            String aPhase = String.format("%07d", aRingPhase);
            dto.setDirA(Integer.parseInt(aPhase.substring(0, 1)));
            dto.setDegAI(Integer.parseInt(aPhase.substring(1, 4)));
            dto.setDegAO(Integer.parseInt(aPhase.substring(4, 7)));
            if (dto.getDegAI() > 360) {
                dto.setDegAI(dto.getDegAI() - 360);
            }
            if (dto.getDegAO() > 360) {
                dto.setDegAO(dto.getDegAO() - 360);
            }
            if (5 == dto.getDirA()) {
                dto.setDegAI(dto.getDegAI() + 90);
                dto.setDegAO(dto.getDegAI() + 180);
                if (dto.getDegAI() > 360) {
                    dto.setDegAI(dto.getDegAI() - 360);
                }
                if (dto.getDegAO() > 360) {
                    dto.setDegAO(dto.getDegAO() - 360);
                }
            }
        }
        if (bRingPhase >= 1000000) {
            String bPhase = String.format("%07d", bRingPhase);
            dto.setDirB(Integer.parseInt(bPhase.substring(0, 1)));
            dto.setDegBI(Integer.parseInt(bPhase.substring(1, 4)));
            dto.setDegBO(Integer.parseInt(bPhase.substring(4, 7)));
            if (dto.getDegBI() > 360) {
                dto.setDegBI(dto.getDegBI() - 360);
            }
            if (dto.getDegBO() > 360) {
                dto.setDegBO(dto.getDegBO() - 360);
            }
            if (5 == dto.getDirB()) {
                dto.setDegBI(dto.getDegBI() + 90);
                dto.setDegBO(dto.getDegBI() + 180);
                if (dto.getDegBI() > 360) {
                    dto.setDegBI(dto.getDegBI() - 360);
                }
                if (dto.getDegBO() > 360) {
                    dto.setDegBO(dto.getDegBO() - 360);
                }
            }
        }
        return dto;
    }

    public TbScSgnlIxrSttsDto toSttsDto() {
        TbScSgnlIxrSttsDto dto = TbScSgnlIxrSttsDto.builder()
                .sgnlIxrNmbr(this.sgnlIxrNmbr)
                .ixrNm(this.ixrNm)
                .updtDt(CodeManager.CMNC_STTS_ERROR_DT)
                .cmncSttsCd(CodeManager.CMNC_STTS_ERROR)
                .build();

        if (this.stts != null) {
            dto.setUpdtDt(SysUtils.getSysTime());

            dto.setLcCnt(this.stts.getLcCnt());
            dto.setCntlMode(this.stts.getCntlMode());
            dto.setCntlStts(this.stts.getCntlStts());
            if (this.stts.getCntlStts() != 3) {
                dto.setCmncSttsCd("CMS0");
            }
            dto.setSpclCntl(this.stts.getSpclCntl());
            dto.setCycl(this.stts.getCycl());
            dto.setOfst(this.stts.getOfst());

            dto.setAring1phas(this.stts.getAring1phas());
            dto.setAring2phas(this.stts.getAring2phas());
            dto.setAring3phas(this.stts.getAring3phas());
            dto.setAring4phas(this.stts.getAring4phas());
            dto.setAring5phas(this.stts.getAring5phas());
            dto.setAring6phas(this.stts.getAring6phas());
            dto.setAring7phas(this.stts.getAring7phas());
            dto.setAring8phas(this.stts.getAring8phas());

            dto.setBring1phas(this.stts.getBring1phas());
            dto.setBring2phas(this.stts.getBring2phas());
            dto.setBring3phas(this.stts.getBring3phas());
            dto.setBring4phas(this.stts.getBring4phas());
            dto.setBring5phas(this.stts.getBring5phas());
            dto.setBring6phas(this.stts.getBring6phas());
            dto.setBring7phas(this.stts.getBring7phas());
            dto.setBring8phas(this.stts.getBring8phas());

            dto.setPrstAringPhas(this.stts.getPrstAringPhas());
            dto.setPrstBringPhas(this.stts.getPrstBringPhas());

            dto.setCboxStts(this.stts.getCboxStts());
        }

        dto.setMissSttsYn(ItsUtils.getMissSttsYn(dto.getUpdtDt()));
        if (("Y").equals(dto.getMissSttsYn())) {
            // 기준시각 보다 크기 때문에 상태정보를 통신두절로 설정
            dto.setCmncSttsCd(CodeManager.CMNC_STTS_ERROR);
        }
        dto.setCmncSttsDesc(CodeManager.getCodeDescShort(CodeManager.CMNC_STTS_CD, dto.getCmncSttsCd()));

        return dto;
    }
}
