package com.utic.center.utic.traf.server.service;

import com.utic.center.common.service.AbstractProcessService;
import com.utic.center.utic.traf.server.config.TraceConfig;
import com.utic.center.utic.traf.server.dto.LinkDto;
import com.utic.center.utic.traf.server.dto.LinkTrafMiss;
import com.utic.center.utic.traf.server.dto.LinkTrafPtrn;
import com.utic.center.utic.traf.server.dto.LinkTrafVal;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Getter
@RequiredArgsConstructor
@Service
public class LinkTrafPrcsDebugService implements AbstractProcessService {

    private final TraceConfig trace;
    private final LinkService linkService;
    private final LinkTrafFusionService fusionService;

//    @ProcessingElapsed(type="PRCS", name="교통정보 디버그 출력", starting = false)
    @Override
    public boolean processing() {

        debug();

        return true;
    }

    private void debug() {
        if (this.trace.getDebugLinks().isEmpty()) {
            return;
        }

        log.info("[INF] Debug Links: {} EA.", this.trace.getDebugLinks());
        for (String linkId : this.trace.getDebugLinks()) {
            LinkDto link = this.linkService.getLink(linkId);
            if (link == null) {
                log.warn("[INF] Debug Links: Link Not Found: {}", linkId);
                continue;
            }
            printLink("[INF] Link", link);
            printTraf(link);
            printCollect(link.getLinkId());

            String dnLinkId = link.getDnLinkId();
            String upLinkId = link.getUpLinkId();
            String link4Id = link.getLink4Id();
            link = this.linkService.getLink(dnLinkId);
            if (link != null) {
                printLink("    UpLink", link);
                printTraf(link);
                printCollect(link.getLinkId());
            }
            link = this.linkService.getLink(upLinkId);
            if (link != null) {
                printLink("    DnLink", link);
                printTraf(link);
                printCollect(link.getLinkId());
            }
            link = this.linkService.getLink(link4Id);
            if (link != null) {
                printLink("    Level4", link);
                printTraf(link);
                printCollect(link.getLinkId());
                for (String ll4Id : link.getLinkIds()) {
                    link = this.linkService.getLink(ll4Id);
                    if (link != null) {
                        log.info("    Level4: {}, LinkId: {}, Speed: {}, State: {}, Length: {}, MissValueYn: {}, PtrnSpeed: {}, PsdSpeed: {}",
                                link4Id, link.getLinkId(), link.getTrafFsn().getSpeed(), link.getTrafFsn().getState().isState(),
                                link.getLength(), link.getTrafFsn().getState().getMissValueYn(), link.getTrafPtrn().getSpeed(), link.getMissPsd().getSpeed());
                    }
                }
            }
        }
    }

    private void printLink(String logHead, LinkDto link) {
        if (link == null) {
            return;
        }
        log.info("{}: {}, Level: {}, Length: {}, RoadRank: {}, Lanes: {}, MinSpeed: {}, MaxSpeed: {}, upLinkId: {}, dnLinkId: {}, link4Id: {}",
                logHead,
                link.getLinkId(), link.getLinkLevel(), link.getLength(), link.getRoadRank()+101,
                link.getLanes(), link.getMinSpeed(), link.getMaxSpeed(),
                link.getUpLinkId(), link.getDnLinkId(), link.getLink4Id());
    }

    private void printTraf(LinkDto link) {
        LinkTrafVal fsn = link.getTrafFsn();        // 퓨전 소통정보
        LinkTrafPtrn ptrn = link.getTrafPtrn();     // 현재 주기 패턴값
        LinkTrafMiss psd = link.getMissPsd();       // PSD 알고리즘 수행 값

        log.info("    Fusion: Speed: {}, State: {}, CrtDataType: {}, MissValueYn: {}, DataResType: {}, CenterId: {}, TrafficGrade: {}, TravelTime: {}, PtrnSpeed: {}",
                fsn.getSpeed(),
                fsn.getState().isState(),
                fsn.getState().getCrtDataType(),
                fsn.getState().getMissValueYn(),
                fsn.getState().getDataResType(),
                fsn.getCenterId(),
                fsn.getState().getTrafficGrade(),
                fsn.getTravelTime(),
                ptrn.getSpeed());
        log.info("   Pattern: Speed: {}", ptrn.getSpeed());
        log.info("       Psd: Speed: {}, MissValueYn: {}", ptrn.getSpeed(), psd.getMissValueYn());
    }

    public void printCollect(String linkId) {
        this.fusionService.getCollectOPER().getLists().stream()
                .filter(c -> c.getLinkId().equals(linkId))
                .findFirst()
                .ifPresent(c -> log.info("      OPER: Speed: {}",
                        c.getSpeed()));

        this.fusionService.getCollectPRIO().getLists().stream()
                .filter(c -> c.getLinkId().equals(linkId))
                .findFirst()
                .ifPresent(c -> log.info("      PRIO: Speed: {}, Priority: {}, MissValueYn: {}, DataResType: {}, CenterId: {}",
                        c.getSpeed(), c.getCrtPriority(), c.getMissValueYn(), c.getDataResType(), c.getCenterId()));

        this.fusionService.getCollectPRIOETC().getLists().stream()
                .filter(c -> c.getLinkId().equals(linkId))
                .findFirst()
                .ifPresent(c -> log.info("   PRIOETC: Speed: {}, Priority: {}, MissValueYn: {}, DataResType: {}, CenterId: {}",
                        c.getSpeed(), c.getCrtPriority(), c.getMissValueYn(), c.getDataResType(), c.getCenterId()));

        this.fusionService.getCollectMOCT().getLists().stream()
                .filter(c -> c.getLinkId().equals(linkId))
                .findFirst()
                .ifPresent(c -> log.info("      MOCT: Speed: {}",
                        c.getSpeed()));
    }
}
