package com.its.api.its.global;

import com.its.api.config.AppUtils;
import com.its.api.its.model.dto.code.TbCmmnCdDto;
import com.its.api.its.model.entity.code.TbSectGradClsf;
import com.its.api.its.repository.code.TbSectGradClsfRepository;
import com.its.api.its.service.code.TbCmmnCdService;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@RequiredArgsConstructor
@Getter
@Component
public class CodeManager {

    private final TbCmmnCdService cmmnCdService;
    private final TbSectGradClsfRepository sectGradClsfRepository;

    // 소통정보 결측 소통등급 코드
    public static final String MISS_SPED_GRAD = "LTC0";

    // 돌발상황 출처 유형
    public static final String INCD_ORGN_IST1 = "IST1";    //운영자
    public static final String INCD_ORGN_IST2 = "IST2";    //제보
    public static final String INCD_ORGN_IST3 = "IST3";    //연계기관
    public static final String INCD_ORGN_IST4 = "IST4";    //OBE
    public static final String INCD_ORGN_IST5 = "IST5";    //도로교통공단
    public static final String INCD_ORGN_IST6 = "IST6";    //자동돌발검지
    public static final String INCD_ORGN_IST7 = "IST7";    //기타

    // 돌발상황 진행 단계 유형
    public static final String INCD_PRGR_STEP_ISS1 = "ISS1";    //접수/미확인
    public static final String INCD_PRGR_STEP_ISS2 = "ISS2";    //진행
    public static final String INCD_PRGR_STEP_ISS3 = "ISS3";    //종료
    public static final String INCD_PRGR_STEP_ISS4 = "ISS4";    //오보

    // 돌발상황관리 코드
    public static final String INCD_CODE_IST  = "IST";  //돌발상황 원본 코드 : IST
    public static final String INCD_CODE_LTCU = "LTCU"; //소통 등급 코드 : LTCU
    public static final String INCD_CODE_ICM  = "ICM";  //돌발상황 확인 방법 코드 : ICM
    public static final String INCD_CODE_IDTU = "IDTU"; //돌발상황 유형 분류 코드 : IDTU

    public static final String INCD_CODE_ACTU = "ACTU"; //돌발상황 유형 코드 : ACTU, CRTU, EVTU, WETU 중 하나	// 사고
    public static final String INCD_CODE_CRTU = "CRTU"; //돌발상황 유형 코드 : ACTU, CRTU, EVTU, WETU 중 하나	// 공사
    public static final String INCD_CODE_EVTU = "EVTU"; //돌발상황 유형 코드 : ACTU, CRTU, EVTU, WETU 중 하나	// 행사
    public static final String INCD_CODE_WETU = "WETU"; //돌발상황 유형 코드 : ACTU, CRTU, EVTU, WETU 중 하나	// 기상

    public static final String INCD_CODE_SRLU = "SRLU"; //돌발상황 심각도 코드 : SRLU
    public static final String INCD_CODE_PRTU = "PRTU"; //통행 제한 유형 코드 : PRTU
    public static final String INCD_CODE_RSL  = "RSL";  //대응 수준 코드 : RSL
    public static final String INCD_CODE_ISS  = "ISS";  //돌발상황 진행 단계 코드 : ISS
    public static final String INCD_CODE_DFW  = "DFW";  //기상 코드 : DFW

    public static final String INCD_CODE_VIT  = "VIT";  //VMS 돌발 유형 코드 : VIT
    public static final String INCD_CODE_IDT  = "IDT";  //VMS 돌발 유형 세부 코드 : IDT
    public static final String INCD_CODE_EDT  = "EDT";  //VMS 돌발 유형 세부 코드 : EDT
    public static final String INCD_CODE_VRT  = "VRT";  //VMS 돌발 통제 코드 : VRT

    // 코드
    private static final String defUnknownCode = "X";
    private static final String defUnknownDesc = "UNKNOWN";

    public static final String EDTN_CD              = "EDI";    // 편집모드
    public static final String DAY_TYPE_CD          = "DTW";    // 요일유형
    public static final String SYST_STTS_CD         = "SPS";    // 프로세스 상태
    public static final String CMTR_GRAD_CD         = "LTC";    // 소통등급
    public static final String PRCN_SORC            = "CST";    // 가공소스
    public static final String ADJS_SORC            = "MCS";    // 보정소스
    public static final String NODE_TYPE            = "NDT";    // 노드유형
    public static final String ROAD_USE             = "RDU";    // 도로사용여부
    public static final String ROAD_RANK            = "RDR";    // 도로등급
    public static final String ROAD_TYPE            = "RDT";    // 도로유형
    public static final String MULTI_LINK           = "MLT";    // 중용구간
    public static final String LINK_CONNECT         = "CTR";    // 연결로
    public static final String REST_VEH             = "PLV";    // 통행제한차량
    public static final String SECT_GRAD_CD         = "SRT";    // 구간 등급 코드
    public static final String DRCT_CD              = "IFD";    // 방향 코드
    public static final String HLDY_DAY_CD          = "LHT";    // 휴일유형코드
    public static final String CNCT_INTN_TYPE_CD    = "COT";    // 연계기관유형코드

    public static final String STTS_UNKNOWN         = "-";
    public static final String CMNC_STTS_NORMAL     = "CMS0";
    public static final String CMNC_STTS_ERROR      = "CMS1";
    public static final String CMNC_STTS_ERROR_DT   = "19700101000000";
    public static final String CMNC_STTS_CD         = "CMS";    // 통신상태코드
    public static final String MODL_STTS_CD         = "MOS";    // 모듈상태
    public static final String PWER_STTS_CD         = "PWS";    // 전원상태
    public static final String DOOR_STTS_CD         = "CDS";    // 도어상태
    public static final String FAN_STTS_CD          = "PAS";    // 팬상태
    public static final String HETR_STTS_CD         = "HTS";    // 히터상태

    //public static final String DTCT_TYPE_CD         = "DTT";    // 검지기유형
    public static final String DTCT_TYPE_CD = "ACD";    // 검지기방향

    public static final String VMS_USAG_TYPE_CD     = "VUT";    // VMS 용도 유형 코드
    public static final String VMS_TYPE_CD          = "VMP";    // VMS 유형 코드

    public static final String REPT_CNGS_CD         = "RCS";    // 반복정체 원본 코드

    public static final String FCLT_TYPE_CD         = "FTC";    // 시설물 유형 코드

    public static final String FCLT_FAIL_TYPE_CD    = "FFA";    // 시설물 장애 유형 코드

    private static final ConcurrentHashMap<String, HashMap<String, Code>> codes = new ConcurrentHashMap<>();

    @PostConstruct
    void init() {
        load();
    }

    public void load() {
        loadAllCode();
        log.info("=== {}", codes);
    }

    private void loadSectGradStup() {
        HashMap<String, Code> codeMap = new HashMap<>();
        List<TbSectGradClsf> codeList = sectGradClsfRepository.findAll();
        for (TbSectGradClsf cd : codeList) {
            codeMap.put(cd.getSectGradCd(), new Code(cd.getSectGradCd(), cd.getSectGradNm(), cd.getSectGradNm()));
        }
        codes.put(SECT_GRAD_CD, codeMap);
    }

    public static void loadCode(String CMMN_CLSF_CD) {
        TbCmmnCdService cmmnCdService = (TbCmmnCdService) AppUtils.getBean(TbCmmnCdService.class);
        HashMap<String, Code> codeMap = new HashMap<>();
        List<TbCmmnCdDto> codeList = cmmnCdService.findAllByCmmnClsfCd(CMMN_CLSF_CD);
        if (codeList != null) {
            for (TbCmmnCdDto cd : codeList) {
                codeMap.put(cd.getCmmnCd(), new Code(cd.getCmmnCd(), cd.getCmmnCdKorNm(), cd.getCmmnDescEnglNm()));
            }
        }
        codes.put(CMMN_CLSF_CD, codeMap);
    }

    public void loadAllCode() {
        List<TbCmmnCdDto> codeList = this.cmmnCdService.findAll();
        for (TbCmmnCdDto cd : codeList) {
            HashMap<String, Code> codeMap = codes.get(cd.getCmmnClsfCd());
            if (codeMap == null) {
                codeMap = new HashMap<>();
                codeMap.put(cd.getCmmnCd(), new Code(cd.getCmmnCd(), cd.getCmmnCdKorNm(), cd.getCmmnDescEnglNm()));
                codes.put(cd.getCmmnClsfCd(), codeMap);
            }
            else {
                codeMap.put(cd.getCmmnCd(), new Code(cd.getCmmnCd(), cd.getCmmnCdKorNm(), cd.getCmmnDescEnglNm()));
            }
        }
    }

    public static String getCodeDesc(String CMMN_CLSF_CD, String CMMN_CD) {
        HashMap<String, Code> codeMap = codes.get(CMMN_CLSF_CD);
        if (codeMap != null) {
            Code code = codeMap.get(CMMN_CD);
            if (code != null) {
                return "[" + CMMN_CD + "] " + code.getDesc();
            }
        }
        return "[" + CMMN_CD + "] " + defUnknownDesc;
    }
    public static String getCodeDescShort(String CMMN_CLSF_CD, String CMMN_CD) {
        HashMap<String, Code> codeMap = codes.get(CMMN_CLSF_CD);
        if (codeMap != null) {
            Code code = codeMap.get(CMMN_CD);
            if (code != null) {
                return code.getDesc();
            }
        }
        return defUnknownDesc;
    }
}
