# src/layers/domOverlay.js

    import Overlayer from './overlay';
    import Util from '../util';

    const duration = 1200;

    /**
     * initDomOverlayer
     */
    export class DomOverlayer extends Overlayer {
        constructor(opts) {
            super(opts);
            this.domContainer = this._init();
            this.redraw = _redraw.bind(this);
            this.domOpts = opts.doms;  // store dom config
            if (opts && opts.map) {
                this.setMap(opts.map);
                // bind render doms to each move..performance to be promoted.
                opts.map.on("move", this.redraw);
            }
            this.doms = []; // store dom elements.
            this.lastData = [];
            this.redraw();
            console.log("Dom overlayer add to Map...");
        }

        _init() {
            let canvasContainer = this.map._canvasContainer,
                mapboxCanvas = this.map._canvas,
                domContainer = document.createElement("div");
            domContainer.style.position = "absolute";
            domContainer.className = "overlay-dom";
            domContainer.style.width = mapboxCanvas.style.width;
            domContainer.style.height = '0';
            canvasContainer.parentElement.appendChild(domContainer);
            return domContainer;
        }

        /**
         * updateDoms and redraw..
         */
        setDoms(Doms) {
            if (Array.isArray(Doms)) {
                this.domOpts = Doms;
                this.clearDoms();
                this.redraw();
            }
        }

        findDom(domId) {
            for(let i = 0;i<this.doms.length;i++) {
                try {
                    if (this.doms[i] === domId) {
                        return this.doms[i];
                    }
                } catch (error) {

                }
            }
        }

        clearDoms() {
            for(let i = 0;i<this.doms.length;i++) {
                this.domContainer.removeChild(this.doms[i]);
            }
            this.doms = [];
        }
    }

    const lineHeight = 60, dotRadius = 4, chartHeight = 60;
    /**
     * domOverlay register&render above default canvas..
     * keep in absolute geolocation..
     */
    function _redraw() {
        let doms = this.domOpts;
        if (doms && Array.isArray(doms)) {
            // append each of domPopups to domContainer.
            for (let i=0;i<doms.length;i++) {
                let domOpt = doms[i];
                if (typeof domOpt == undefined) continue;
                // let sanity = Util.checkSanity(this.lastDoms[i], domOpt);
                let x = domOpt['lon'], y = domOpt['lat'],
                    pix = this.lnglat2pix(x, y);
                if (pix == null) continue;
                let iconName = domOpt['icon'], resources = domOpt['resources'],
                    domStyle = domOpt['style']? domOpt['style'] + ' animated': 'bounceIn animated',
                    chartData = domOpt['data'], chartType = domOpt['type'];
                // data sanity should be checked, domOpts not changed then just update position!
                let dom = this.doms[i*3] || document.createElement("div"),
                    line = this.doms[i*3+1] ||document.createElement("div"),
                    dot =this.doms[i*3+2] || document.createElement("div");
                preStyleEles(line, dot, dom, pix, chartType||resources);

                let dataClone = Util.deepClone(chartData);
                // handle different typesof domOverlay.
                if (resources != undefined) {
                    dom.title = (domOpt['content'] || ``);
                    if (!dom.hasChildNodes() || dom.firstChild.src !== resources[0]) {
                        Util.setResource(dom, resources);
                    }
                } else if (iconName != undefined) {
                    dom.innerHTML = (domOpt['content'] || ``) + '</br>';
                    Util.setIconDiv(dom, iconName);
                } else if (chartData != undefined && chartType != undefined) {
                    if (Util.isChanged(this.lastData[i], chartData)) {
                        // setChart would contaminate input Data.
                        Util.setChart(dom, dataClone, chartType, chartHeight*2);
                        this.lastData[i] = chartData;
                    }
                } else {
                    dom.innerHTML = (domOpt['content']|| '') + '</br>';
                }
                if (chartType != undefined) styleChartContainer(dom)

                line.className = "dom-ele", dot.className = "dom-ele";
                line.style.left = pix[0] + "px";
                line.style.top = (pix[1] - (lineHeight - 10)) + "px";
                dot.style.left = pix[0] - dotRadius + "px";
                dot.style.top = pix[1] - dotRadius + "px";

                // add dom to container at init process.
                if (this.doms[i*3] == undefined) {
                    dom.className = `dom-popup ${domStyle}`;
                    line.className = dot.className = `dom-ele ${domStyle}`
                    console.warn(`add ${domStyle} css to dom.`)
                    this.domContainer.appendChild(dom);
                    this.domContainer.appendChild(line);
                    this.domContainer.appendChild(dot);
                    this.doms.push(...[dom, line, dot]);
                }
            }
        }
    }

    /**
     *  ___________
     * |chart/img  |   main popup. /// It is key topic to place popup align.
     *  -----------
     *       |         line/triangle.. (should implement by psuedoClass!)
     *       。         point..
     * chartWidth always 2*chartHeight if using Chart.js
     */
    function preStyleEles(line, dot, dom, pix, chartType) {
        const isImg = Array.isArray(chartType);
        line.style.height = lineHeight - 10 + 'px';
        line.style.width = '1px';
        line.style.position = "absolute";
        dot.style.borderRadius = '50%';
        dot.style.width = dot.style.height = dotRadius * 2 + 'px';
        dot.style.position = "absolute";
        dom.style.position = "absolute";
        if (!chartType) {
            dom.style.minWidth = "100px"; // consistant with chart/image dom width/height.
        }
        dom.style.background = "#fff";
        dom.style.textAlign = "center";
        dom.style.padding = '3px';
        // if has chartType, display chart above vertical line.
        dom.style.left = (pix[0] - (isImg? chartHeight/2: chartHeight)) + "px";
        dom.style.top = (pix[1] - lineHeight - (chartType? chartHeight : 20)) + "px";
    }

    function styleChartContainer(dom) {
        dom.style.borderWidth = '0';
        dom.style.zIndex = 9999;
        dom.style.backgroundColor = 'rgba(0,0,0,0.0)';
    }

    function animLine (line){
        line.className = "dom-line";
    }

    const htmlTemplate = {

    }