import { TMapMngr, TFclt } from "/js/vworld/map-mngr.js";
import { LayerType, LayerIndex, EditLinkColor, EditLinkLineSize} from "/js/vworld/map-const.js";
"use-strict"
let _strtDt;
let _strtTm;
let _endDt;
let _endTm;
let _tfvlList;
let _odList;
let _searchBtn;
let _closeBtn;
let _mapManager;
const crdnMap = new Map();
let _timeArr;
let _trfvData;
let _selectedVector;
let _selectedNmbr;
let _max;
let _dotLyre;
let _drawInfoMap = new Map();
const _lyrIdx       = LayerIndex.Dsrc;
let _mapToggleChek  = null;
const _apiUri = "/api/tb_rse_od_stat_hh/tfvl";
//20221214090000' AND '20221214235959'
const strtTmVal = new Date().setHours(new Date().getHours()-2);
const endTmVal = new Date().setHours(new Date().getHours()-1);
const _pageName = 'DSRC OD 교통량 통계';
$(()=>{
    _strtDt = new dxDate($('.strt-date'), 'yyyy-MM-dd', '검색 시작일', 130, 30, 'date', null, null, null);
    _strtTm = new dxDate($('.strt-time'), 'HH', '검색 시작 시각', 80, 30, 'time', 60, null, null);
    _endDt  = new dxDate($('.end-date'), 'yyyy-MM-dd', '검색 종료일', 130, 30, 'date', null, null, null);
    _endTm  = new dxDate($('.end-time'), 'HH', '검색 종료 시각', 80, 30, 'time', 60, null, null);
    _strtDt.setValue(new Date().setDate(new Date().getDate()-1));
    _endDt.setValue(new Date().setDate(new Date().getDate()-1));
    _strtTm.setValue(strtTmVal);
    _endTm.setValue(endTmVal);
    
    _timeArr = [ 
        _strtDt,
        _strtTm,
        _endDt,
        _endTm,
    ];

    _closeBtn = new dxBtn($('.close-btn'), '닫기', 'close', 'outlined', null, null, false, true);
    _closeBtn.onClick(()=>window.close());
    _searchBtn = new dxBtn($('.search-btn'), '조회', 'refresh', 'outlined', null, 32, false, true);
    _searchBtn.onClick(fetchBaseData);
    _tfvlList = $('.tfvl-list').width('100%').height('100%').dxDataGrid({
        dataSource : [],
        allowColumnReordering   : true,
        showColumnLines         : true,
        showBorders             : true,
        allowColumnResizing     : true,
        rowAlternationEnabled   : true,
        columnAutoWidth         : true,
        focusedRowEnabled       : true,
        idDataText              : '표출할 정보가 없습니다.',
        selection  : {
            mode :'single'
        },
        keyExpr : 'rse_ctlr_nmbr',
        paging: {
            enabled: false,
            pageSize: 1000,
        },
        scrolling: {
            mode: 'standard',
        },
        columns:  [
            {
                caption   : 'DSRC 명',
                dataField : "rse_nm",
                alignment : 'center',
                cellTemplate(c, e) {
                    alignTemplate(c, e, 'left');
                }
            },
            {
                dataField : "depart_tfvl",
                caption   : "출발",
                alignment : "center",
                format    : "#,##0"
            },
            {
                dataField : "arrival_tfvl",
                caption   : "도착",
                alignment : "center",
                format    : "#,##0"
            },
        ],
        onRowDblClick(e) {
            trfvListDblClick(e);
        }
    }).dxDataGrid("instance");
    let data = [];
    getData('/api/rse/tb_rse_ctlr', data);
    if (data[0] && data[0].length > 0) {
        data[0].map((item)=>{
            crdnMap.set(item.rse_ctlr_nmbr, [item.x_crdn, item.y_crdn]); 
        })
    }
    doMap();
    fetchBaseData();
})
function trfvListDblClick(e){
    if (e.data) {
        _mapManager.map.getView().setCenter(crdnMap.get(e.data.rse_ctlr_nmbr));
    }
}
/**
 * 맵정보 및 맵 툴바 생성
 */
function doMap() {
    _mapManager = new TMapMngr("map", "tooltip");
    _mapManager.setZoom(15);
    _mapManager.setEditMode(_lyrIdx, true);
    _mapManager.showLayer(_lyrIdx, true);
    _mapManager.map.getView().setCenter([127.09399, 36.99351]);
    let lineLayer  = makeIfscLayer();
    _mapToggleChek = fetchMapIconBar2($('.map-bar'), _mapManager, lineLayer, _pageName, EditLinkLineSize);
    _mapToggleChek.on("valueChanged", (e)=> toggleChanged(e, lineLayer));
    _mapManager.map.on("pointermove", function(e){
        const f = _mapManager.map.forEachFeatureAtPixel(e.pixel, function (feature) {
            return feature;
        });
        if (f) {
            const obj = f.get("obj");
            const nm  = f.get('name');
            let name;
            if (obj) {
                name = obj.NAME;
                let iwContent = '<div id="edit-tooltip">' + name + "</div>";
                _mapManager.tooltip.style.display = "";
                _mapManager.tooltipOverlay.setPosition(e.coordinate);
                _mapManager.tooltip.innerHTML = iwContent;
            }
            else if (nm){
                name = nm;
                let iwContent = '<div id="edit-tooltip">' + name + "</div>";
                _mapManager.tooltip.style.display = "";
                _mapManager.tooltipOverlay.setPosition(e.coordinate);
                _mapManager.tooltip.innerHTML = iwContent;
            }
           
        }
    });
};

/**
 * 
 * @param {*} e 
 * @param {*} lineLyer 
 */
function toggleChanged (e, lineLyer) {
    _mapManager.toggleBaseMap(e.value);
    if (lineLyer) {

        let lineWidth = EditLinkLineSize[_mapManager.map.getView().getZoom()];
        lineLyer.setStyle([
            new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: e.value ? '#FFFFFF' : '#000',
                    width: lineWidth + 2,
                    //lineCap: "square",
                //lineJoin: "round",
            }),
            ZIndex: 2,
        }),
        new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: '#15B337',
                width: lineWidth,
                //lineCap: "square",
            }),
                ZIndex: 1,
            }),
        ]);
    }
    if (_dotLyre) {
        _dotLyre.setStyle(
            new ol.style.Style({
                stroke: new ol.style.Stroke({
                    width: 3,
                    color: e.value ? '#eee':'black',
                    lineDash: [.1, 5] //or other combinations
                }),
            }),
        )
    }
}

/**
 * DSRC Icon Layer 생성
 * @param {*} data DSRC 데이터
 */
function drawDsrcIcon(data){
     // 기존 객체를 모두 삭제한다.
     _mapManager.removeLayerObject(_lyrIdx);
     if (data.length > 0) {
         // 시설물 객체를 지도에 그린다.
         const objs = new Array();
         data.forEach((obj) => {
             const item = new TFclt(obj.rse_ctlr_nmbr, obj.rse_nm, crdnMap.get(obj.rse_ctlr_nmbr)[0], crdnMap.get(obj.rse_ctlr_nmbr)[1]);
             objs.push(item);
         });
 
         _mapManager.initFcltObject(_lyrIdx, objs);
     }
}

/**
 * 정보제공 구간 layer 만들기
 * @returns ifsc 구간 vector
 */
function makeIfscLayer() {
    let vrtx;
    if(_trafficMap) {
        vrtx = _trafficMap.get('ifsc1');
    }
    const lineFeatures = [];
    if (vrtx && vrtx.length > 0) {
        vrtx.map((item)=>{
            const arrX = item.x_crdn_arr.split(",");
            const arrY = item.y_crdn_arr.split(",");
            let lineCoordinates = [];
            for (let ii = 0; ii < arrX.length; ii++) {
                let lineArr = [];
                lineArr.push(Number(arrX[ii]), Number(arrY[ii]));
                lineCoordinates.push(lineArr);
            }
            lineFeatures.push(
                new ol.Feature({
                    geometry: new ol.geom.LineString(lineCoordinates),
                }));
            })
            
            let lineWidth = EditLinkLineSize[_mapManager.map.getView().getZoom()];
            let lineVector = new ol.layer.Vector({
                title  : 'stroke',
                source : new ol.source.Vector({features : lineFeatures}),
                style : [
                    new ol.style.Style({
                        stroke: new ol.style.Stroke({
                            color: '#000', //'#000', '#FFFFFF'
                            width: lineWidth + 2,
                            //lineCap: "square",
                            //lineJoin: "round",
                        }),
                        ZIndex: 2,
                    }),
                    new ol.style.Style({
                        stroke: new ol.style.Stroke({
                            color: '#15B337',
                            width: lineWidth,
                            //lineCap: "square",
                        }),
                        ZIndex: 1,
                    }),
                ],
            })
            _mapManager.map.addLayer(lineVector);
            return lineVector;
        }
}

/**
 * 조회 데이터 수신
 * @returns 유효한 데이터만 요청
 */
function fetchBaseData(){
    for (let time of _timeArr) {
        if (time.isValidation()) {
            return alertWarning( time.label + '을 형식에 맞게 입력해주세요.', null, time);
        }
        else if (time.isNull()) {
            return alertWarning( time.label+ '을 입력해주세요.', null, time);
        }
    }
    let strtDt = _strtDt.getSendDateValue().substring(0,8);
    let endDt  = _endDt.getSendDateValue().substring(0,8);
    let strtTm = _strtTm.getSendTimeValue().substring(0,2) + '0000';
    let endTm  = _endTm.getSendTimeValue().substring(0,2) + '0000';
    let strt   = strtDt + strtTm;
    let end    = endDt + endTm;
    _selectedNmbr = null;
    if (strt > end) {
        return alertWarning( '검색 시작 시간이 종료 시각보다 큽니다.', null, _endDt);
    }
    else if (Number(strt) + 100000000 <= Number(end)) {
        return alertWarning( '검색 기간을 1개월 이내로 입력해주세요.', null, _endDt);
    }
    $('.date-text').text('조회기간 : ' + dateTextFormat(strt) + ' ~ ' + dateTextFormat(end));
    getDataAsync(_apiUri + '/od', recvTrfvListData, _tfvlList, {FROM_DT : strt, TO_DT : end})
    getDataAsync(_apiUri + '/od-list-data', recvOdListData, null, {FROM_DT : strt, TO_DT : end});
    //getDataAsync(_apiUri + '/od', recvTrfvListData, _tfvlList, {FROM_DT : '20221214090000', TO_DT : '20221214235959'});
    //getDataAsync(_apiUri + '/od-list-data', recvOdListData, null, {FROM_DT : '20221214090000', TO_DT : '20221214235959'});
}

/**
 * 조회 시작, 종료값 텍스트 변환
 * @param {*} date 시작, 종료 텍스트
 * @returns 날짜 포맷 텍스트
 */
function dateTextFormat(date){
    return date.substring(0,4) + '년 ' + date.substring(4,6) + '월 ' + date.substring(6,8) + '일 ' + date.substring(8,10) + '시';
}

/**
 * 좌측 교통량 목록 데이터 수신 및 맵 차트 생성
 * @param {*} jsonData 수신 데이터
 * @param {*} table 리스트 테이블
 */
function recvTrfvListData(jsonData, table) {
    _trfvData = jsonData;
    _tfvlList.clearSelection();
    _tfvlList.option('focusedRowIndex', -1);
    if (jsonData.length > 0) {
        let array = [];
        jsonData.map((item)=>{
            array.push(item.arrival_tfvl + item.depart_tfvl);
        });
        _max = Math.max(...array);
    }
    drawSeachCircle();
    table.option('dataSource', jsonData);
}

/**
 * 하단 OD 분석 데이터 수신 및 리스트 목록 생성
 * @param {*} jsonData 수신 데이터
 */
function recvOdListData(jsonData) {
    let columns =[
        {
            caption   : 'DSRC ID',
            dataField : "rse_nm",
            alignment : 'center',
            cellTemplate(c, e) {
                alignTemplate(c, e, 'left');
            }
        },
    ]
    if (jsonData.length > 0) {
        dataSorting(jsonData, 'rse_ctlr_nmbr');
        jsonData.map((item)=>{
            columns.push(
                {
                    caption   : item.rse_nm,
                    dataField : 'tfvl_' + item.rse_ctlr_nmbr,
                    alignment : 'center',
                }
            )
            item.lists.map((list)=>{
                item['tfvl_' + list.rse_ctlr_nmbr] = list.tfvl;
            })
        })
        _odList = $('.od-list').width('100%').height('100%').dxDataGrid({
            dataSource : jsonData,
            allowColumnReordering   : true,
            showColumnLines         : true,
            showBorders             : true,
            allowColumnResizing     : true,
            rowAlternationEnabled   : true,
            columnAutoWidth         : true,
            focusedRowEnabled       : true,
            idDataText              : '표출할 정보가 없습니다.',
            selection  : {
                mode :'single'
            },
            keyExpr : 'rse_ctlr_nmbr',
            paging: {
                enabled: false,
                pageSize: 1000,
            },
            scrolling: {
                mode: 'standard',
            },
            columns: columns,
            onRowDblClick(e){
                drawCircle(e.data);
            }
        }).dxDataGrid("instance");
        _odList.clearSelection();
        _odList.option('focusedRowIndex', -1);
    }
}

/**
 * 조회 버튼 클릭 시 맵 차트 생성
 */
function drawSeachCircle(){
    const map = _mapManager.map;
    if (_selectedVector && _selectedVector.length > 0) {
        _selectedVector.map((item)=>{
            map.removeLayer(item);
        })
    }
    let features = [];
    let data = [];
    _trfvData.map((item)=>{
        let {arrival_tfvl, depart_tfvl, rse_ctlr_nmbr, rse_nm} = item;
        const center = crdnMap.get(rse_ctlr_nmbr);
        if (arrival_tfvl || depart_tfvl) {
            features.push( 
                new ol.Feature({
                geometry: new ol.geom.Point(center),
                data: [arrival_tfvl, depart_tfvl],
                sum: arrival_tfvl + depart_tfvl,
                text : [arrival_tfvl, depart_tfvl],
                name : rse_nm,
            }));
        }
        else {
            data.push(item);
        }
    })
    
    drawDsrcIcon(data);

    let vector = new ol.layer.Vector(
        {
            name: 'Vecteur',
            source: new ol.source.Vector({ features: features }),
            renderOrder: ol.ordering.yOrdering(),
            style: function(f) { return getFeatureStyle(f, true); },
            zIndex: 3,
        }
    )
    _selectedVector = [vector];
    map.addLayer(vector);
  
}

/**
 * 맵 원형 차트 그리기
 * @param {*} odData 교통량 데이터
 * @returns 같은 값 클릭 시 실행 안함
 */
function drawCircle(odData){
    if (odData.rse_ctlr_nmbr === _selectedNmbr) {
        return;
    }
    _selectedNmbr = odData.rse_ctlr_nmbr;
    const map = _mapManager.map;
    if (_selectedVector) {
        _selectedVector.map((item)=>{
            map.removeLayer(item);
        })
    }

    let idx = _trfvData.findIndex(item => odData.rse_ctlr_nmbr === item.rse_ctlr_nmbr);
    let {arrival_tfvl, depart_tfvl, rse_ctlr_nmbr} = _trfvData[idx];
    let center = crdnMap.get(rse_ctlr_nmbr);
    let features = [];
    let sum = arrival_tfvl + depart_tfvl;
    if (sum) {
        features.push( 
            new ol.Feature({
                geometry: new ol.geom.Point(center),
                data: [arrival_tfvl, depart_tfvl],
                sum: sum,
                text : [arrival_tfvl, depart_tfvl],
            }));
        _max = sum;
    }
    let odFeatures = [];
    let lineFeatures = [];
    let data =[];

    odData.lists.map((item)=>{
        if (item.tfvl) {
            const currentPos = crdnMap.get(item.rse_ctlr_nmbr);
            odFeatures.push(
                new ol.Feature({
                    geometry: new ol.geom.Point(currentPos),
                    data : [item.tfvl],
                    sum  : item.tfvl,
                    text : item.tfvl,
                    name : item.name,
                })
            )
            lineFeatures.push(
                new ol.Feature({
                    geometry : new ol.geom.LineString([center, currentPos]),
                })
            )
        }
        else {
            if (sum > 0) {
                if (rse_ctlr_nmbr !== item.rse_ctlr_nmbr) {
                    data.push(item);
                }
            }
            else {
                data.push(item);
            }
        }
    })

    drawDsrcIcon(data);
    let vector = new ol.layer.Vector(
        {
            name: 'Vecteur',
            source: new ol.source.Vector({ features: features }),
            renderOrder: ol.ordering.yOrdering(),
            style: function(f) { return getFeatureStyle(f, true); },
            zIndex: 3,
        }
    )
    let odVector = new ol.layer.Vector(
        {
            name: 'Vecteur',
            source: new ol.source.Vector({ features: odFeatures }),
            renderOrder: ol.ordering.yOrdering(),
            style: function(f) { return getOdFeatureStyle(f, true); },
            zIndex: 3,
        }
    )
    let checkVal = getValue(_mapToggleChek);
    let lineVector = new ol.layer.Vector({
        title  : 'stroke',
        source : new ol.source.Vector({features : lineFeatures}),
        style : new ol.style.Style({
            stroke: new ol.style.Stroke({
                width: 3,
                color: checkVal ? '#eee' : 'black',
                lineDash: [.1, 5] //or other combinations
            }),
        }),
        zIndex: 3,
    })
    _dotLyre = lineVector;
    map.addLayer(lineVector);
    map.addLayer(vector);
    map.addLayer(odVector);
    _selectedVector = [vector, odVector, lineVector];
    map.getView().setCenter(center);
}

/**
 * 교통량 서클 사이즈 및 텍스트 위치
 * @param {*} feature 해당 서클 정보
 * @returns style 정보
 */
function getOdFeatureStyle(feature) {
    //var radius = 15;
    // area proportional to data size: s=PI*r^2
    let radius = 2* Math.sqrt (feature.get("sum") / Math.PI);
    const data = feature.get("data");
    // Create chart style
    let style = [
        new ol.style.Style({
            image: new ol.style.Circle({
                radius: radius < 15 ? 15 : radius,
                stroke: new ol.style.Stroke({ color: '#fff', width: 1 }),
                fill: new ol.style.Fill({ color: '#FFAA00' })
            })
        }),
        new ol.style.Style({
            text: new ol.style.Text({
            text: data[0].toString(),
            offsetX: 0,
            offsetY: 1,
            textAlign: "center",
            textBaseline: "middle",
            stroke: new ol.style.Stroke({ color:"gray", width: 1 }),
            fill: new ol.style.Fill({color:"black"}),
            style  : "bold",
            font:  '14px sans-serif',
            }),
            zIndex: 3,
        })
    ];

    return style;
}

/**
 * 값 별 서클 사이즈 정보
 */
class TDrawInfo {
    constructor(ARadius, AFont, AOffset) {
        this.radius = ARadius;
        this.font = AFont;
        this.offset = AOffset;
    }
}
_drawInfoMap.set(0, new TDrawInfo(18, 8, 3));
_drawInfoMap.set(1, new TDrawInfo(20, 9, 3));
_drawInfoMap.set(2, new TDrawInfo(25, 10, 0));
_drawInfoMap.set(3, new TDrawInfo(30, 10, -5));
_drawInfoMap.set(4, new TDrawInfo(35, 11, -5));
_drawInfoMap.set(5, new TDrawInfo(40, 11, -10));
_drawInfoMap.set(6, new TDrawInfo(45, 12, -10));
_drawInfoMap.set(7, new TDrawInfo(50, 13, -10));
_drawInfoMap.set(8, new TDrawInfo(55, 14, -15));
_drawInfoMap.set(9, new TDrawInfo(60, 14, -15));
_drawInfoMap.set(10, new TDrawInfo(60, 14, -15));

/**
 * 분할 서클 스타일(출발/도착)
 * @param {*} feature 
 * @returns 
 */
function getFeatureStyle(feature) {
    // area proportional to data size: s=PI*r^2
    const sumTraf = Number(feature.get("sum"));
    const stepVal = sumTraf / Number(_max) * 100.;
    const drawInfo = _drawInfoMap.get(Math.trunc(Number(stepVal)/10., 0));
    let radius = drawInfo.radius;
    let font = drawInfo.font;
    let val = drawInfo.offset;

    //radius = Math.sqrt(feature.get("sum") / Math.PI);
    let data = feature.get("data");
    //radius *= (sel?1.2:1);
    // Create chart style
    let style = [ new ol.style.Style({
      image: new ol.style.Chart({
        type: "pie", 
        radius: radius, 
        data: data, 
        colors : 'pastel',
        rotateWithView: true,
        stroke: new ol.style.Stroke({
          color: "#fff",
          width: 1
        }),
        zIndex: 3,
      })
    })];
    
    // Show values on select
    const sum = feature.get("sum");
    let s = 0;
    for (let ii = 0; ii < data.length; ii++) {
        let d = data[ii];
        let a = (2*s+d)/sum*Math.PI-Math.PI/2;
        let text = feature.get("text")[ii].toString();
        style.push(
            new ol.style.Style({
                text : new ol.style.Text({
                    text         : text, /* d.toString() */
                    offsetX      : Math.cos(a)*(radius + val),
                    offsetY      : Math.cos(a),
                    //offsetX      : Math.cos(a)*(radius + val),
                    //offsetY      : Math.cos(a)*(radius + val),
                    textAlign    : (a < Math.PI/2 ? "right":"left"),
                    textBaseline : "middle",
                    stroke       : new ol.style.Stroke({ color:"gray", width: 1 }),
                    fill         : new ol.style.Fill({color:"black"}),
                    style        : "bold",
                    font         : font + 'px sans-serif',
                })
            })
        );
        s += d;
    }
  return style;
}
