'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var map = require('@ktmap/map');
var domAlign = require('dom-align');
var shared = require('@ktmap/shared');

// import './style';
/**
 * 信息窗体
 */
class InfoWindow extends map.InfoWindow {
    constructor(map, options) {
        var _a, _b, _c;
        super();
        Object.defineProperty(this, "map", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: map
        });
        Object.defineProperty(this, "options", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: options
        });
        Object.defineProperty(this, "id", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: ''
        });
        Object.defineProperty(this, "clsPrefix", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: 'ktmap-info-window'
        });
        Object.defineProperty(this, "$window", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "lastWorldPosition", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "cacheInnerHTML", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: ''
        });
        options.align = (_a = options.align) !== null && _a !== void 0 ? _a : { points: ['cl'], useCssTransform: true };
        options.align.points = (_b = options.align.points) !== null && _b !== void 0 ? _b : ['cl'];
        options.align.useCssTransform = (_c = options.align.useCssTransform) !== null && _c !== void 0 ? _c : true;
        this.__init();
    }
    __init() {
        console.log('InfoWindow init success');
        {
            shared.warn('开发环境警告，测试');
        }
        this.create();
        const { map, options, options: { align }, $window } = this;
        // ✨ 执行 updateSize，地图缩放时，要在进行世界坐标转屏幕坐标的行为，否则信息窗体不会跟随想要的元素走
        map.updateSizeMap.set(this, () => {
            // 将最后的世界坐标存储到缓存，用于计算屏幕坐标
            if (this.lastWorldPosition && $window.style.display === 'block') {
                const { $map, scene, camera } = map;
                const { x, y } = shared.getScreenPostion({
                    worldPosition: this.lastWorldPosition,
                    $map,
                    scene,
                    camera
                });
                domAlign.alignPoint($window, { clientX: x, clientY: y }, {
                    points: align.points,
                    offset: align.offset,
                    overflow: { adjustX: true, adjustY: true },
                    useCssTransform: align.useCssTransform
                });
            }
        });
        // const source = document.createElement('div');
        // source.id = 'source';
        // source.innerHTML = 'source';
        // const target = document.createElement('div');
        // target.id = 'target';
        // target.innerHTML = 'target';
        // map.$map.append(source, target);
        // // use domAlign
        // // sourceNode's initial style should be position:absolute;left:-9999px;top:-9999px;
        // const alignConfig = {
        //   points: ['tl', 'cr'], // align top left point of sourceNode with top right point of targetNode
        //   offset: [10, 10], // the offset sourceNode by 10px in x and 20px in y,
        //   // targetOffset: ['30%', '40%'], // the offset targetNode by 30% of targetNode width in x and 40% of targetNode height in y,
        //   // targetOffset: [-10, -10], // the offset targetNode by 30% of targetNode width in x and 40% of targetNode height in y,
        //   overflow: { adjustX: true, adjustY: true } // auto adjust position when sourceNode is overflowed
        // };
        // domAlign(source, target, alignConfig);
        if (options.trigger === 'hover') {
            const _find = (item) => {
                // 循环找到父级 name 为 car 的
                let _item = item.object;
                while (_item && _item.name !== options.targetName) {
                    _item = _item === null || _item === void 0 ? void 0 : _item.parent;
                }
                return _item;
            };
            // TODO:外部可传入条件约束，是否要展示信息提示框
            // TODO:鼠标没有移动，只是缩放地图，没有触发到 mousemove 事件会导致弹框一直存在
            map.on('mousemove', ev => {
                const { intersects, worldPosition, screenPosition } = ev;
                if (intersects && screenPosition) {
                    this.lastWorldPosition = worldPosition;
                    let target = null;
                    for (const item of intersects) {
                        target = _find(item);
                        if (target)
                            break;
                    }
                    // 判断是否悬浮到目标上
                    if (target) {
                        const { x, y } = screenPosition;
                        // $window.style.cssText = `display:block;left:${x + 10}px;top:${
                        //   y + 10
                        // }px`;
                        domAlign.alignPoint($window, { clientX: x, clientY: y }, {
                            points: align.points,
                            offset: align.offset,
                            overflow: { adjustX: true, adjustY: true },
                            useCssTransform: align.useCssTransform
                        });
                        $window.style.display = 'block';
                        map.domElement.style.cursor = 'pointer';
                        this.emitter.emit('hover', target);
                    }
                    else {
                        $window.style.display = 'none';
                        map.domElement.style.cursor = 'default';
                    }
                }
                // 超出地图元素，直接隐藏
                else {
                    $window.style.display = 'none';
                }
            });
        }
        else if (options.trigger === 'click') {
            const _find = (item) => {
                // 循环找到父级 name 为 car 的
                let _item = item.object;
                while (_item && _item.name !== options.targetName) {
                    _item = _item === null || _item === void 0 ? void 0 : _item.parent;
                }
                return _item;
            };
            // 悬浮时，切换鼠标样式，让用户感知这是一个点击区域
            map.on('mousemove', ev => {
                const { intersects, screenPosition } = ev;
                if (intersects && screenPosition) {
                    let target = null;
                    for (const item of intersects) {
                        target = _find(item);
                        if (target)
                            break;
                    }
                    // 判断是否悬浮到目标上
                    map.domElement.style.cursor = target ? 'pointer' : 'default';
                }
            });
            map.on('click', ev => {
                const { intersects, worldPosition, screenPosition } = ev;
                if (intersects && screenPosition) {
                    this.lastWorldPosition = worldPosition;
                    let target = null;
                    for (const item of intersects) {
                        target = _find(item);
                        if (target)
                            break;
                    }
                    // 判断是否悬浮到目标上
                    if (target) {
                        const { x, y } = screenPosition;
                        domAlign.alignPoint($window, { clientX: x, clientY: y }, {
                            points: align.points,
                            offset: align.offset,
                            overflow: { adjustX: true, adjustY: true },
                            useCssTransform: align.useCssTransform
                        });
                        $window.style.display = 'block';
                        this.emitter.emit('click', target);
                    }
                    else {
                        $window.style.display = 'none';
                    }
                }
                // 超出地图元素，直接隐藏
                else {
                    $window.style.display = 'none';
                }
            });
        }
    }
    /**
     * 设置内容
     */
    setContent(content) {
        const { clsPrefix, $window } = this;
        const $content = $window === null || $window === void 0 ? void 0 : $window.querySelector(`.${clsPrefix}__content`);
        if ($content) {
            let innerHTML = this.cacheInnerHTML;
            if (content instanceof HTMLElement) {
                innerHTML = content.outerHTML;
            }
            else {
                innerHTML = content;
            }
            if (this.cacheInnerHTML !== innerHTML)
                $content.innerHTML = innerHTML;
            this.cacheInnerHTML = innerHTML;
        }
    }
    /**
     * 打开窗口
     */
    create() {
        const { map, options, clsPrefix } = this;
        const html = `
      ${options.title
            ? `<div class="${clsPrefix}__title">${options.title}</div>`
            : ''}
      <div class="${clsPrefix}__content"></div>
      ${options.close
            ? `<div class="text-right">
              <button>我知道了</button>
            </div>`
            : ''}
    `;
        const wrapper = document.createElement('div');
        // 一个唯一id
        wrapper.id = this.id = `${clsPrefix}_${+new Date()}`;
        wrapper.className = `${clsPrefix} ${clsPrefix}--${options.type}`;
        wrapper.innerHTML = html;
        wrapper.style.display = 'none';
        wrapper.addEventListener('click', ev => {
            if (ev.target.tagName === 'BUTTON') {
                this.hide();
            }
        });
        map.$map.appendChild(wrapper);
        this.$window = wrapper;
        return wrapper;
    }
    /**
     * 打开窗体
     * 当 trigger 为 custom 时，会用到
     */
    show(worldPosition) {
        if (worldPosition) {
            const { map: { $map, scene, camera }, options: { align } } = this;
            this.lastWorldPosition = worldPosition;
            const { x, y } = shared.getScreenPostion({
                worldPosition,
                $map,
                scene,
                camera
            });
            domAlign.alignPoint(this.$window, { clientX: x, clientY: y }, {
                points: align.points,
                offset: align.offset,
                overflow: { adjustX: true, adjustY: true },
                useCssTransform: align.useCssTransform
            });
        }
        this.$window.style.display = 'block';
    }
    /**
     * 隐藏窗口
     */
    hide() {
        this.$window.style.display = 'none';
    }
    /**
     * 销毁
     */
    destroy() { }
}
Object.defineProperty(InfoWindow, "NAME", {
    enumerable: true,
    configurable: true,
    writable: true,
    value: 'InfoWindow'
});

exports.InfoWindow = InfoWindow;
