import { MDControlBase } from "./md-control-base";
import { AppMapService } from '../ctrl-service';
import { init } from 'echarts';
import { Util } from '@ibizstudio/runtime';
/**
 * 地图部件基类
 *
 * @export
 * @class MapControlBase
 * @extends {MDControlBase}
 */
export class MapControlBase extends MDControlBase {
    constructor() {
        super(...arguments);
        /**
         * 地图信息缓存
         *
         * @memberof MapControlBase
         */
        this.addressCache = new Map();
        /**
          * 地图数据
          *
          * @type {*}
          * @memberof MapControlBase
          */
        this.items = [];
        /**
         * 地图数据项模型
         *
         * @type {}
         * @memberof MapControlBase
         */
        this.mapItems = {};
        /**
         * 显示图例
         *
         * @type {*}
         * @memberof MapControlBase
         */
        this.showLegends = [];
        /**
         * 显示的最大值
         *
         * @type {number}
         * @memberof MapControlBase
         */
        this.valueMax = 0;
        /**
         * 省份区域数据
         *
         * @memberof MapControlBase
         */
        this.areaData = [];
        /**
         * 区域样式图数据
         *
         * @memberof MapControlBase
         */
        this.regionData = [];
        /**
         * 初始化配置
         *
         * @type {}
         * @memberof MapControlBase
         */
        this.initOptions = {
            title: {
                text: '',
                left: 'center',
                top: 20,
            },
            tooltip: {
                trigger: 'item',
            },
            legend: {
                orient: 'vertical',
                x: 'left',
                y: 'center',
                data: [],
            },
            geo: {
                map: 'china',
                zoom: 1.2,
                label: {
                    show: true,
                },
                itemStyle: {
                    areaColor: '#e0ffff',
                },
                emphasis: {
                    itemStyle: {
                        areaColor: '#F3B329',
                    },
                },
            },
            visualMap: [
                {
                    min: 0,
                    max: 1000,
                    left: 'left',
                    seriesIndex: 0,
                    top: 'bottom',
                    text: ['高', '低'],
                    inRange: {
                        color: ['#e0ffff', '#006edd'],
                    },
                    show: true,
                },
            ],
            series: [
                {
                    name: '信息量',
                    type: 'map',
                    geoIndex: 0,
                    data: [],
                    tooltip: {
                        formatter: "<span style='margin-right: 20px'>{b}</span><b>{c}</b>",
                    },
                }
            ]
        };
        /**
         * 默认排序方向
         *
         * @readonly
         * @memberof MapControlBase
         */
        this.minorSortDir = '';
        /**
         * 默认排序应用实体属性
         *
         * @readonly
         * @memberof MapControlBase
         */
        this.minorSortPSDEF = '';
    }
    /**
     * 获取选中数据
     *
     * @returns {any[]}
     * @memberof GridControlBase
     */
    getSelection() {
        return this.selections;
    }
    /**
     * 省份区域值集合
     *
     * @memberof MapControlBase
     */
    getAreaValueList() {
        return [
            { name: '南海诸岛', value: this.calculateAreaValue('南海') },
            { name: '北京', value: this.calculateAreaValue('北京') },
            { name: '天津', value: this.calculateAreaValue('天津') },
            { name: '上海', value: this.calculateAreaValue('上海') },
            { name: '重庆', value: this.calculateAreaValue('重庆') },
            { name: '河北', value: this.calculateAreaValue('河北') },
            { name: '河南', value: this.calculateAreaValue('河南') },
            { name: '云南', value: this.calculateAreaValue('云南') },
            { name: '辽宁', value: this.calculateAreaValue('辽宁') },
            { name: '黑龙江', value: this.calculateAreaValue('黑龙江') },
            { name: '湖南', value: this.calculateAreaValue('湖南') },
            { name: '安徽', value: this.calculateAreaValue('安徽') },
            { name: '山东', value: this.calculateAreaValue('山东') },
            { name: '新疆', value: this.calculateAreaValue('新疆') },
            { name: '江苏', value: this.calculateAreaValue('江苏') },
            { name: '浙江', value: this.calculateAreaValue('浙江') },
            { name: '江西', value: this.calculateAreaValue('江西') },
            { name: '湖北', value: this.calculateAreaValue('湖北') },
            { name: '广西', value: this.calculateAreaValue('广西') },
            { name: '甘肃', value: this.calculateAreaValue('甘肃') },
            { name: '山西', value: this.calculateAreaValue('山西') },
            { name: '内蒙古', value: this.calculateAreaValue('内蒙古') },
            { name: '陕西', value: this.calculateAreaValue('陕西') },
            { name: '吉林', value: this.calculateAreaValue('吉林') },
            { name: '福建', value: this.calculateAreaValue('福建') },
            { name: '贵州', value: this.calculateAreaValue('贵州') },
            { name: '广东', value: this.calculateAreaValue('广东') },
            { name: '青海', value: this.calculateAreaValue('青海') },
            { name: '西藏', value: this.calculateAreaValue('西藏') },
            { name: '四川', value: this.calculateAreaValue('四川') },
            { name: '宁夏', value: this.calculateAreaValue('宁夏') },
            { name: '海南', value: this.calculateAreaValue('海南') },
            { name: '台湾', value: this.calculateAreaValue('台湾') },
            { name: '香港', value: this.calculateAreaValue('香港') },
            { name: '澳门', value: this.calculateAreaValue('澳门') },
        ];
    }
    ;
    /**
     * 监听静态参数变化
     *
     * @param {*} newVal
     * @param {*} oldVal
     * @memberof MapControlBase
     */
    onStaticPropsChange(newVal, oldVal) {
        this.isSelectFirstDefault = newVal.isSelectFirstDefault ? true : false;
        super.onStaticPropsChange(newVal, oldVal);
    }
    /**
      * 部件模型数据初始化实例
      *
      * @memberof MapControlBase
      */
    async ctrlModelInit(args) {
        await super.ctrlModelInit();
        if (!(this.Environment && this.Environment.isPreviewMode)) {
            this.service = new AppMapService(this.controlInstance, this.context);
            await this.service.loaded(this.controlInstance);
            this.initMapModel();
        }
    }
    /**
     * 初始化
     *
     * @memberof MapControlBase
     */
    ctrlInit(args) {
        super.ctrlInit();
        // 绑定this
        this.transformData = this.transformData.bind(this);
        this.refresh = this.refresh.bind(this);
        this.win = window;
    }
    viewStateAction(tag, action, data) {
        if (!Object.is(tag, this.name)) {
            return;
        }
        super.viewStateAction(tag, action, data);
        if (Object.is(action, 'load')) {
            this.load(data);
        }
    }
    /**
     * 部件挂载完毕
     *
     * @protected
     * @memberof MapControlBase
     */
    ctrlMounted() {
        super.ctrlMounted();
        let _this = this;
        let map = this.$refs.map;
        if (map) {
            this.map = init(map);
        }
        if (this.map) {
            this.map.setOption(this.initOptions);
            // 如果是导航视图默认选中第一项
            this.map.on('selectchanged', 'series', function (params) {
                var _a;
                if ((_a = params.fromActionPayload) === null || _a === void 0 ? void 0 : _a.custom) {
                    const select = [params.fromActionPayload.custom];
                    _this.onClick(select);
                }
            });
            // 监听地图触发的点击事件
            this.map.on('click', 'series', function (params) {
                var _a, _b;
                if (Object.is(params.seriesType, 'scatter') && ((_a = params.data) === null || _a === void 0 ? void 0 : _a.value)) {
                    const select = [params.data.value[3]];
                    _this.onClick(select);
                }
                else if ((Object.is(params.seriesType, 'custom') || Object.is(params.seriesType, 'lines')) && ((_b = params.data) === null || _b === void 0 ? void 0 : _b.coords)) {
                    const selects = [];
                    params.data.coords.forEach((coord) => {
                        selects.push(coord[3]);
                    });
                    _this.onClick(selects);
                }
            });
            // 图例改变过滤地图数据
            this.map.on('legendselectchanged', function (params) {
                if (params.name) {
                    _this.showLegends.forEach((showLegend) => {
                        if (Object.is(showLegend.name, params.name)) {
                            showLegend.show = !showLegend.show;
                        }
                    });
                    // 重新设置地图数据
                    _this.valueMax = 0;
                    const data = _this.getAreaValueList();
                    _this.map.setOption({
                        visualMap: {
                            max: _this.valueMax > 0 ? _this.valueMax : 1000,
                        },
                        series: {
                            data: data,
                        }
                    });
                }
            });
        }
        let amap = this.win.AMap;
        amap.plugin(["AMap.Geocoder"], () => {
            this.geocoder = new amap.Geocoder({
                extensions: "all",
            });
        });
    }
    /**
     * 刷新
     *
     * @param {*} [args] 额外参数
     * @memberof MapControlBase
     */
    refresh(args) {
        this.load(args);
    }
    /**
     * 更新大小
     *
     * @memberof MapControlBase
     */
    updateSize() {
        if (this.map) {
            this.map.resize();
        }
    }
    /**
     * 地图数据加载
     *
     * @param {*} [data={}] 额外参数
     * @returns {void}
     * @memberof MapControlBase
     */
    load(data = {}) {
        if (!this.fetchAction) {
            this.$throw(this.$t('app.map.notconfig.fetchaction'), 'load');
            return;
        }
        this.items = [];
        const parentData = {};
        this.ctrlEvent({ controlname: this.name, action: "beforeload", data: parentData });
        Object.assign(data, parentData);
        let tempViewParams = parentData.viewparams ? parentData.viewparams : {};
        if (this.viewparams) {
            Object.assign(tempViewParams, Util.deepCopy(this.viewparams));
        }
        for (let item in this.mapItems) {
            let sort = '';
            if (this.mapItems[item].sort) {
                sort += this.mapItems[item].sort + ',';
            }
            if (sort) {
                sort = sort + 'desc';
                Object.assign(tempViewParams, { sort: sort });
            }
        }
        Object.assign(data, { viewparams: tempViewParams });
        let tempContext = Util.deepCopy(this.context);
        this.onControlRequset('load', tempContext, data);
        this.service.search(this.fetchAction, this.context, data).then((response) => {
            if (!response || response.status !== 200) {
                this.$throw(response, 'load');
            }
            this.items = response.data;
            this.ctrlEvent({
                controlname: this.name,
                action: 'load',
                data: this.items,
            });
            this.calculateAreaData().then(() => {
                this.setAreaData();
                this.handleMapOptions();
                this.setOptions();
                // 处理地图所有数据需要一定时间，所以将关闭遮罩放置在地图绘制完成之后
                this.onControlResponse('load', response);
            });
        }, (response) => {
            this.onControlResponse('load', response);
            this.$throw(response, 'load');
        });
    }
    /**
     * 设置配置
     *
     * @memberof MapControlBase
     */
    setOptions() {
        var _a;
        if (!this.map) {
            return;
        }
        const options = Util.deepCopy(this.initOptions);
        this.map.setOption(options);
        // 如果是导航视图默认选中第一项
        if (this.isSelectFirstDefault) {
            const select = this.items.find((item) => { var _a; return Object.is(item.itemType, (_a = this.showLegends[0]) === null || _a === void 0 ? void 0 : _a.itemType); });
            this.map.dispatchAction({
                type: 'select',
                seriesId: (_a = this.showLegends[0]) === null || _a === void 0 ? void 0 : _a.itemType,
                dataIndex: 0,
                custom: select,
            });
        }
        ;
        this.updateSize();
    }
    /**
     * 配置整合
     *
     * @return {*}
     * @memberof MapControlBase
     */
    handleMapOptions() {
        let series = this.initOptions.series;
        if (!series || series.length == 0) {
            return;
        }
        series.forEach((serie) => {
            const seriesData = [];
            this.items.forEach((item) => {
                if (Object.is(item.itemType, serie.itemType)) {
                    seriesData.push(item);
                }
            });
            this.handleSeriesOptions(seriesData, serie);
        });
        Object.assign(this.initOptions.series, series);
    }
    /**
     * 整合序列数据
     *
     * @param {*} seriesData 序列数据
     * @param {*} serie 序列
     * @memberof MapControlBase
     */
    handleSeriesOptions(seriesData, serie) {
        serie.id = serie.itemType;
        if (Object.is(serie.type, 'scatter')) {
            // 点样式数据处理
            seriesData.forEach((data) => {
                const tempItem = [
                    parseFloat(data.longitude), parseFloat(data.latitude), data.content, data
                ];
                const _data = {
                    name: data.title,
                    value: tempItem,
                };
                serie.data.push(_data);
            });
        }
        else if (Object.is(serie.type, 'lines') || Object.is(serie.type, 'custom')) {
            const groupDatas = [];
            // 获取对应分组的数据集合
            const getGroupItems = (groupName) => {
                const items = [];
                if (groupName) {
                    seriesData.forEach((data) => {
                        if (Object.is(data.group, groupName)) {
                            items.push(data);
                        }
                    });
                }
                ;
                return items;
            };
            // 分组
            if (this.mapItems[serie.itemType].group) {
                seriesData.forEach((data) => {
                    if (data.group) {
                        const group = groupDatas.find((groupData) => Object.is(groupData.group, data.group));
                        if (!group) {
                            groupDatas.push({
                                group: data.group,
                                items: getGroupItems(data.group),
                            });
                        }
                        ;
                    }
                    ;
                });
            }
            else {
                groupDatas.push({
                    group: serie.name,
                    items: seriesData,
                });
            }
            if (Object.is(serie.type, 'custom')) {
                // 区域图数据处理
                this.regionData = [];
            }
            groupDatas.forEach((groupData) => {
                if (this.mapItems[serie.itemType].sort) {
                    groupData.items.sort((a, b) => {
                        const x = a.sort;
                        const y = b.sort;
                        return x > y ? -1 : x < y ? 1 : 0;
                    });
                }
                ;
                const coords = [];
                groupData.items.forEach((item) => {
                    const coord = [
                        parseFloat(item.longitude), parseFloat(item.latitude), item.content, item
                    ];
                    coords.push(coord);
                });
                serie.data.push({
                    name: groupData.group,
                    coords: coords,
                });
            });
            if (Object.is(serie.type, 'custom')) {
                // 区域图数据处理
                this.regionData = [...serie.data];
            }
        }
    }
    /**
     * 初始化地图参数
     *
     * @memberof MapControlBase
     */
    initMapModel() {
        const mapItems = this.controlInstance.getPSSysMapItems();
        this.showLegends = [];
        if (mapItems) {
            mapItems.forEach((item, index) => {
                var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
                this.showLegends.push({
                    name: item.name,
                    itemType: (_a = item.itemType) === null || _a === void 0 ? void 0 : _a.toLowerCase(),
                    show: true,
                });
                Object.assign(this.mapItems, {
                    [(_b = item.itemType) === null || _b === void 0 ? void 0 : _b.toLowerCase()]: {
                        bkcolor: item.bKColor,
                        color: item.color,
                        content: (_c = item.getContentPSAppDEField()) === null || _c === void 0 ? void 0 : _c.codeName.toLowerCase(),
                        latitude: (_d = item.getLatitudePSAppDEField()) === null || _d === void 0 ? void 0 : _d.codeName.toLowerCase(),
                        longitude: (_e = item.getLongitudePSAppDEField()) === null || _e === void 0 ? void 0 : _e.codeName.toLowerCase(),
                        text: (_f = item.getTextPSAppDEField()) === null || _f === void 0 ? void 0 : _f.codeName.toLowerCase(),
                        tips: (_g = item.getTipsPSAppDEField()) === null || _g === void 0 ? void 0 : _g.codeName.toLowerCase(),
                        group: (_h = item.getGroupPSAppDEField()) === null || _h === void 0 ? void 0 : _h.codeName.toLowerCase(),
                        sort: (_j = item.getOrderValuePSAppDEField()) === null || _j === void 0 ? void 0 : _j.codeName.toLowerCase(),
                        code: index
                    }
                });
                this.initOptions.legend.data.push(item.name);
                this.initOptions.visualMap.push({
                    type: 'piecewise',
                    left: 'left',
                    top: 'bottom',
                    splitNumber: 1,
                    seriesIndex: index + 1,
                    pieces: [{
                            label: item.name,
                            min: index * 10,
                            max: (index + 1) * 10,
                            color: item.color,
                            backgroundColor: item.bKColor,
                            borderColor: item.borderColor,
                            borderWidth: item.borderWidth
                        }],
                    show: false
                });
                if (Object.is('POINT', item.itemStyle)) {
                    this.initOptions.series.push({
                        name: item.name,
                        type: 'scatter',
                        coordinateSystem: 'geo',
                        itemType: (_k = item.itemType) === null || _k === void 0 ? void 0 : _k.toLowerCase(),
                        color: item.color,
                        selectedMode: 'single',
                        select: {
                            itemStyle: {
                                borderColor: item.color,
                                opacity: 1,
                                borderWidth: 6,
                            },
                        },
                        itemStyle: {
                            opacity: 0.7,
                        },
                        geoIndex: 0,
                        symbolSize: 16,
                        label: {
                            show: true,
                            position: 'right',
                            formatter: '{b}',
                        },
                        emphasis: {},
                        encode: {
                            value: 2,
                        },
                        tooltip: {},
                        data: [],
                    });
                }
                else if (Object.is('LINE', item.itemStyle)) {
                    this.initOptions.series.push({
                        name: item.name,
                        type: 'lines',
                        geoIndex: 0,
                        itemType: (_l = item.itemType) === null || _l === void 0 ? void 0 : _l.toLowerCase(),
                        coordinateSystem: 'geo',
                        polyline: true,
                        tooltip: {
                            show: true,
                            formatter: (arg) => this.renderTooltip(arg),
                        },
                        lineStyle: {
                            color: item.color,
                            opacity: 1,
                            width: 3,
                        },
                        data: [],
                    });
                }
                else if (Object.is('REGION', item.itemStyle)) {
                    this.initOptions.series.push({
                        name: item.name,
                        type: 'custom',
                        geoIndex: 0,
                        itemType: (_m = item.itemType) === null || _m === void 0 ? void 0 : _m.toLowerCase(),
                        coordinateSystem: 'geo',
                        renderItem: (params, api) => this.renderRegion(params, api),
                        selectedMode: 'single',
                        itemStyle: {
                            color: item.color,
                            opacity: 0.5,
                        },
                        tooltip: {
                            formatter: (arg) => this.renderTooltip(arg),
                        },
                        data: [],
                    });
                }
            });
        }
    }
    /**
     * 绘制悬浮提示
     *
     * @param arg
     */
    renderTooltip(arg) {
        const curData = arg.data;
        const items = curData.coords;
        let content = '';
        if (Object.is("lines", arg.seriesType)) {
            content = items[0][2] + '-' + items[items.length - 1][2];
        }
        else {
            let total = 0;
            items.forEach((item) => {
                total += item[2];
            });
            content = total;
        }
        const interval = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
        const tooltip = arg.name + '<br />' + arg.marker + curData.name + interval + content;
        return tooltip;
    }
    /**
     * 绘制区域图
     *
     * @param params 参数
     * @param api 方法集合
     * @returns
     */
    renderRegion(params, api) {
        const children = [];
        const color = api.visual('color');
        this.regionData.forEach((data) => {
            let points = [];
            data.coords.forEach((value) => {
                points.push(api.coord(value));
            });
            const child = {
                type: 'polygon',
                shape: {
                    points: points,
                },
                style: api.style({
                    fill: color,
                }),
                select: {
                    style: {
                        opacity: 1,
                        fill: color,
                    },
                },
            };
            children.push(child);
        });
        return {
            type: 'group',
            children: children,
        };
    }
    /**
     * 调用服务，根据经纬度获取地址信息
     *
     * @param {*} lng 经度
     * @param {*} lat 纬度
     * @memberof MapControlBase
     */
    async getAddress(lng, lat) {
        return new Promise((resolve, reject) => {
            let address = null;
            if (this.addressCache.get(lng + '-' + lat)) {
                address = this.addressCache.get(lng + '-' + lat);
                resolve(address);
            }
            this.geocoder.getAddress([lng, lat], (status, result) => {
                if (status === 'complete' && result.info === 'OK') {
                    if (result && result.regeocode) {
                        address = result.regeocode.addressComponent;
                        this.addressCache.set(lng + '-' + lat, address);
                    }
                }
                resolve(address);
            });
        });
    }
    /**
     * 计算省份区域数据
     *
     * @memberof MapControlBase
     */
    async calculateAreaData() {
        this.areaData = [];
        if (this.items.length > 0) {
            for (let item of this.items) {
                const address = await this.getAddress(item.longitude, item.latitude);
                if (address) {
                    const provinceName = address.province;
                    this.areaData.push({
                        name: provinceName,
                        itemType: item.itemType,
                        data: item,
                    });
                }
            }
        }
    }
    /**
     * 计算省份区域数据值(项类容属性)
     *
     * @param name 省份区域名
     * @returns 省份区域值
     * @memberof MapControlBase
     */
    calculateAreaValue(name) {
        const areaData = [];
        this.areaData.forEach((item) => {
            const showLegend = this.showLegends.find((_showLegend) => Object.is(_showLegend.itemType, item.itemType));
            if (item.name.indexOf(name) > -1 && (showLegend === null || showLegend === void 0 ? void 0 : showLegend.show)) {
                areaData.push(item.data);
            }
        });
        let value = 0;
        areaData.forEach((item) => {
            if (Number.isFinite(Number(item.content))) {
                value += item.content;
            }
            else {
                value += 1;
            }
        });
        this.valueMax = value > this.valueMax ? value : this.valueMax;
        return value;
    }
    /**
     * 设置地图数据(初始化)
     *
     * @memberof MapControlBase
     */
    setAreaData() {
        var _a;
        let series = this.initOptions.series;
        if (!series || series.length == 0) {
            return;
        }
        this.valueMax = 0;
        this.initOptions.title.text = (_a = this.controlInstance) === null || _a === void 0 ? void 0 : _a.logicName;
        this.initOptions.series[0].data = this.getAreaValueList();
        this.initOptions.visualMap[0].max = this.valueMax > 0 ? this.valueMax : 1000;
    }
    /**
     * 地图点击事件
     *
     * @param $event 选中数据
     * @memberof MapControlBase
     */
    onClick($event) {
        this.selections = $event;
        if ($event && (Object.keys($event).length > 0)) {
            this.$emit("ctrl-event", { controlname: this.controlInstance.name, action: "selectionchange", data: this.selections });
        }
    }
}
