import { defineComponent, ref, watch, nextTick, onMounted, onUnmounted, openBlock, createElementBlock, createCommentVNode, withDirectives, createElementVNode, renderSlot, vShow, shallowRef, Fragment, renderList, toDisplayString, createVNode } from 'vue';
import * as echarts from 'echarts';
import axios from 'axios';

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

var freeGlobal$1 = freeGlobal;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal$1 || freeSelf || Function('return this')();

var root$1 = root;

/** Built-in value references. */
var Symbol = root$1.Symbol;

var Symbol$1 = Symbol;

/** Used for built-in method references. */
var objectProto$1 = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto$1.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString$1 = objectProto$1.toString;

/** Built-in value references. */
var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined;

/**
 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the raw `toStringTag`.
 */
function getRawTag(value) {
  var isOwn = hasOwnProperty.call(value, symToStringTag$1),
      tag = value[symToStringTag$1];

  try {
    value[symToStringTag$1] = undefined;
    var unmasked = true;
  } catch (e) {}

  var result = nativeObjectToString$1.call(value);
  if (unmasked) {
    if (isOwn) {
      value[symToStringTag$1] = tag;
    } else {
      delete value[symToStringTag$1];
    }
  }
  return result;
}

/** Used for built-in method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString = objectProto.toString;

/**
 * Converts `value` to a string using `Object.prototype.toString`.
 *
 * @private
 * @param {*} value The value to convert.
 * @returns {string} Returns the converted string.
 */
function objectToString(value) {
  return nativeObjectToString.call(value);
}

/** `Object#toString` result references. */
var nullTag = '[object Null]',
    undefinedTag = '[object Undefined]';

/** Built-in value references. */
var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : undefined;

/**
 * The base implementation of `getTag` without fallbacks for buggy environments.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
function baseGetTag(value) {
  if (value == null) {
    return value === undefined ? undefinedTag : nullTag;
  }
  return (symToStringTag && symToStringTag in Object(value))
    ? getRawTag(value)
    : objectToString(value);
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return value != null && typeof value == 'object';
}

/** `Object#toString` result references. */
var symbolTag = '[object Symbol]';

/**
 * Checks if `value` is classified as a `Symbol` primitive or object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
 * @example
 *
 * _.isSymbol(Symbol.iterator);
 * // => true
 *
 * _.isSymbol('abc');
 * // => false
 */
function isSymbol(value) {
  return typeof value == 'symbol' ||
    (isObjectLike(value) && baseGetTag(value) == symbolTag);
}

/** Used to match a single whitespace character. */
var reWhitespace = /\s/;

/**
 * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
 * character of `string`.
 *
 * @private
 * @param {string} string The string to inspect.
 * @returns {number} Returns the index of the last non-whitespace character.
 */
function trimmedEndIndex(string) {
  var index = string.length;

  while (index-- && reWhitespace.test(string.charAt(index))) {}
  return index;
}

/** Used to match leading whitespace. */
var reTrimStart = /^\s+/;

/**
 * The base implementation of `_.trim`.
 *
 * @private
 * @param {string} string The string to trim.
 * @returns {string} Returns the trimmed string.
 */
function baseTrim(string) {
  return string
    ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
    : string;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return value != null && (type == 'object' || type == 'function');
}

/** Used as references for various `Number` constants. */
var NAN = 0 / 0;

/** Used to detect bad signed hexadecimal string values. */
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;

/** Used to detect binary string values. */
var reIsBinary = /^0b[01]+$/i;

/** Used to detect octal string values. */
var reIsOctal = /^0o[0-7]+$/i;

/** Built-in method references without a dependency on `root`. */
var freeParseInt = parseInt;

/**
 * Converts `value` to a number.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to process.
 * @returns {number} Returns the number.
 * @example
 *
 * _.toNumber(3.2);
 * // => 3.2
 *
 * _.toNumber(Number.MIN_VALUE);
 * // => 5e-324
 *
 * _.toNumber(Infinity);
 * // => Infinity
 *
 * _.toNumber('3.2');
 * // => 3.2
 */
function toNumber(value) {
  if (typeof value == 'number') {
    return value;
  }
  if (isSymbol(value)) {
    return NAN;
  }
  if (isObject(value)) {
    var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
    value = isObject(other) ? (other + '') : other;
  }
  if (typeof value != 'string') {
    return value === 0 ? value : +value;
  }
  value = baseTrim(value);
  var isBinary = reIsBinary.test(value);
  return (isBinary || reIsOctal.test(value))
    ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
    : (reIsBadHex.test(value) ? NAN : +value);
}

/**
 * Gets the timestamp of the number of milliseconds that have elapsed since
 * the Unix epoch (1 January 1970 00:00:00 UTC).
 *
 * @static
 * @memberOf _
 * @since 2.4.0
 * @category Date
 * @returns {number} Returns the timestamp.
 * @example
 *
 * _.defer(function(stamp) {
 *   console.log(_.now() - stamp);
 * }, _.now());
 * // => Logs the number of milliseconds it took for the deferred invocation.
 */
var now = function() {
  return root$1.Date.now();
};

var now$1 = now;

/** Error message constants. */
var FUNC_ERROR_TEXT = 'Expected a function';

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max,
    nativeMin = Math.min;

/**
 * Creates a debounced function that delays invoking `func` until after `wait`
 * milliseconds have elapsed since the last time the debounced function was
 * invoked. The debounced function comes with a `cancel` method to cancel
 * delayed `func` invocations and a `flush` method to immediately invoke them.
 * Provide `options` to indicate whether `func` should be invoked on the
 * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
 * with the last arguments provided to the debounced function. Subsequent
 * calls to the debounced function return the result of the last `func`
 * invocation.
 *
 * **Note:** If `leading` and `trailing` options are `true`, `func` is
 * invoked on the trailing edge of the timeout only if the debounced function
 * is invoked more than once during the `wait` timeout.
 *
 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
 *
 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
 * for details over the differences between `_.debounce` and `_.throttle`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Function
 * @param {Function} func The function to debounce.
 * @param {number} [wait=0] The number of milliseconds to delay.
 * @param {Object} [options={}] The options object.
 * @param {boolean} [options.leading=false]
 *  Specify invoking on the leading edge of the timeout.
 * @param {number} [options.maxWait]
 *  The maximum time `func` is allowed to be delayed before it's invoked.
 * @param {boolean} [options.trailing=true]
 *  Specify invoking on the trailing edge of the timeout.
 * @returns {Function} Returns the new debounced function.
 * @example
 *
 * // Avoid costly calculations while the window size is in flux.
 * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
 *
 * // Invoke `sendMail` when clicked, debouncing subsequent calls.
 * jQuery(element).on('click', _.debounce(sendMail, 300, {
 *   'leading': true,
 *   'trailing': false
 * }));
 *
 * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
 * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
 * var source = new EventSource('/stream');
 * jQuery(source).on('message', debounced);
 *
 * // Cancel the trailing debounced invocation.
 * jQuery(window).on('popstate', debounced.cancel);
 */
function debounce(func, wait, options) {
  var lastArgs,
      lastThis,
      maxWait,
      result,
      timerId,
      lastCallTime,
      lastInvokeTime = 0,
      leading = false,
      maxing = false,
      trailing = true;

  if (typeof func != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  wait = toNumber(wait) || 0;
  if (isObject(options)) {
    leading = !!options.leading;
    maxing = 'maxWait' in options;
    maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
    trailing = 'trailing' in options ? !!options.trailing : trailing;
  }

  function invokeFunc(time) {
    var args = lastArgs,
        thisArg = lastThis;

    lastArgs = lastThis = undefined;
    lastInvokeTime = time;
    result = func.apply(thisArg, args);
    return result;
  }

  function leadingEdge(time) {
    // Reset any `maxWait` timer.
    lastInvokeTime = time;
    // Start the timer for the trailing edge.
    timerId = setTimeout(timerExpired, wait);
    // Invoke the leading edge.
    return leading ? invokeFunc(time) : result;
  }

  function remainingWait(time) {
    var timeSinceLastCall = time - lastCallTime,
        timeSinceLastInvoke = time - lastInvokeTime,
        timeWaiting = wait - timeSinceLastCall;

    return maxing
      ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
      : timeWaiting;
  }

  function shouldInvoke(time) {
    var timeSinceLastCall = time - lastCallTime,
        timeSinceLastInvoke = time - lastInvokeTime;

    // Either this is the first call, activity has stopped and we're at the
    // trailing edge, the system time has gone backwards and we're treating
    // it as the trailing edge, or we've hit the `maxWait` limit.
    return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
      (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
  }

  function timerExpired() {
    var time = now$1();
    if (shouldInvoke(time)) {
      return trailingEdge(time);
    }
    // Restart the timer.
    timerId = setTimeout(timerExpired, remainingWait(time));
  }

  function trailingEdge(time) {
    timerId = undefined;

    // Only invoke if we have `lastArgs` which means `func` has been
    // debounced at least once.
    if (trailing && lastArgs) {
      return invokeFunc(time);
    }
    lastArgs = lastThis = undefined;
    return result;
  }

  function cancel() {
    if (timerId !== undefined) {
      clearTimeout(timerId);
    }
    lastInvokeTime = 0;
    lastArgs = lastCallTime = lastThis = timerId = undefined;
  }

  function flush() {
    return timerId === undefined ? result : trailingEdge(now$1());
  }

  function debounced() {
    var time = now$1(),
        isInvoking = shouldInvoke(time);

    lastArgs = arguments;
    lastThis = this;
    lastCallTime = time;

    if (isInvoking) {
      if (timerId === undefined) {
        return leadingEdge(lastCallTime);
      }
      if (maxing) {
        // Handle invocations in a tight loop.
        clearTimeout(timerId);
        timerId = setTimeout(timerExpired, wait);
        return invokeFunc(lastCallTime);
      }
    }
    if (timerId === undefined) {
      timerId = setTimeout(timerExpired, wait);
    }
    return result;
  }
  debounced.cancel = cancel;
  debounced.flush = flush;
  return debounced;
}

const _hoisted_1$1 = { class: "echarts-box flex-center" };
const _hoisted_2$1 = /*#__PURE__*/ createElementVNode("div", { class: "echarts-empty" }, "暂无数据", -1 /* HOISTED */);
var script$1 = /*#__PURE__*/ defineComponent({
    __name: 'index',
    props: {
        option: {
            type: Object,
            default: null,
        },
        clickFn: {
            type: Function,
            default: undefined,
        },
        // 是否需要清空option
        isResetOption: {
            type: Boolean,
            default: false,
        },
        adapterDebounceTime: {
            type: Number,
            default: 500,
        },
    },
    emits: ['initFinish'],
    setup(__props, { emit: emits }) {
        const props = __props;
        const echartDom = ref();
        function initChart() {
            if (!echartDom.value) {
                return console.error('dom is not exist');
            }
            const instance = echarts.init(echartDom.value);
            if (!instance) {
                console.error('echarts is instance not exist');
                return console.error('echart init fail');
            }
            instance.setOption(props.option);
            if (props.clickFn) {
                instance.on('click', props.clickFn);
            }
            emits('initFinish', instance);
            screenAdapter();
        }
        function screenAdapter() {
            if (!props.option) {
                return;
            }
            nextTick(() => {
                if (echartDom.value) {
                    const instance = echarts.getInstanceByDom(echartDom.value);
                    instance && instance.resize();
                }
            });
        }
        watch(() => props.option, val => {
            if (val) {
                nextTick(() => {
                    if (echartDom.value) {
                        const instance = echarts.getInstanceByDom(echartDom.value);
                        if (instance) {
                            instance.setOption(val, props.isResetOption);
                        }
                        else {
                            initChart();
                        }
                    }
                });
            }
        }, { immediate: true, deep: true });
        const debounceScreenAdapter = debounce(screenAdapter, props.adapterDebounceTime, { leading: false });
        const resizeObserver = new ResizeObserver(debounceScreenAdapter);
        // const visibleObserver = new IntersectionObserver((params): void => {
        //   if (params[0].isIntersecting) {
        //     debounceScreenAdapter();
        //   }
        // });
        onMounted(() => {
            // window.addEventListener('resize', debounce(screenAdapter, 1000));
            echartDom.value && resizeObserver.observe(echartDom.value);
            // visibleObserver.observe(echartDom.value);
        });
        onUnmounted(() => {
            // window.removeEventListener('resize', screenAdapter);
            resizeObserver.disconnect();
            // visibleObserver.disconnect();
        });
        return (_ctx, _cache) => {
            return (openBlock(), createElementBlock("div", _hoisted_1$1, [
                (__props.option)
                    ? (openBlock(), createElementBlock("div", {
                        key: 0,
                        ref_key: "echartDom",
                        ref: echartDom,
                        class: "echarts-box-content"
                    }, null, 512 /* NEED_PATCH */))
                    : createCommentVNode("v-if", true),
                withDirectives(createElementVNode("div", null, [
                    renderSlot(_ctx.$slots, "empty flex-center", {}, () => [
                        _hoisted_2$1
                    ])
                ], 512 /* NEED_PATCH */), [
                    [vShow, !__props.option]
                ])
            ]));
        };
    }
});

script$1.__file = "packages/echarts-box/index.vue";

const _hoisted_1 = { class: "map-box" };
const _hoisted_2 = { class: "header" };
const _hoisted_3 = ["onClick"];
const _hoisted_4 = {
    key: 0,
    class: "map-breadcrumb-separator"
};
var script = /*#__PURE__*/ defineComponent({
    __name: 'index',
    props: {
        getData: {
            // eslint-disable-next-line no-unused-vars
            type: Function,
            default: undefined,
        },
        getJsonPath: {
            type: Function,
            default: undefined,
        },
        getMapOptions: {
            type: Function,
            default: undefined,
        },
        drillable: {
            type: [Boolean, Function],
            default: true,
        },
    },
    emits: ['initFinish'],
    setup(__props, { expose: __expose, emit: emits }) {
        const props = __props;
        // 地图配置
        const mapOptions = ref();
        // 下钻路径
        const pathArr = ref([]);
        // 记录区域信息（方便使用，不用传来传去)
        const currentRegionData = shallowRef();
        // 请求数据(queryData是查询条件)
        function getRequestData() {
            return new Promise((resolve, reject) => {
                if (!props.getData) {
                    return reject('getData is not exist');
                }
                if (!currentRegionData.value) {
                    return reject('regionData is not exist');
                }
                props.getData(currentRegionData.value).then((result) => {
                    resolve(result);
                });
            });
        }
        // 获取地图json
        function getMapJson() {
            if (currentRegionData.value?.acode) {
                const { acode } = currentRegionData.value;
                let jsonPath = `../../geo-json/${acode}.json`;
                if (props.getJsonPath) {
                    const path = props.getJsonPath(acode);
                    if (path) {
                        jsonPath = path;
                    }
                }
                return axios.get(jsonPath).then(res => {
                    // 注册地图
                    echarts.registerMap(acode, res.data);
                });
            }
            return Promise.reject('acode is undefined');
        }
        // 单独请求数据（比如改变请求条件的时候用）
        function requestData() {
            getRequestData()
                .then(res => {
                drawMap(res);
            })
                .catch(err => {
                console.warn(err);
            });
        }
        // 清空当前地图数据
        function clearData() {
            drawMap(null);
        }
        // 构造地图
        function setMapData(regionData) {
            if (!regionData.acode || !regionData.name) {
                return;
            }
            currentRegionData.value = regionData;
            Promise.all([getRequestData(), getMapJson()])
                .then(res => {
                drawMap(res[0]);
            })
                .catch(err => {
                console.warn(err);
            });
        }
        // 绘制
        function drawMap(data) {
            if (!props.getMapOptions) {
                return console.warn('getMapOptions is not exist');
            }
            mapOptions.value = props.getMapOptions(currentRegionData.value?.acode, data);
        }
        // 路径上卷
        async function jumpRegion(item, index) {
            if (index === pathArr.value.length) {
                return;
            }
            await setMapData(item);
            pathArr.value = pathArr.value.slice(0, index + 1);
        }
        // 地图下钻
        async function toLower(params) {
            console.log('clickMap', params);
            if (params.data) {
                // 判断是否可下钻
                if (!props.drillable) {
                    return;
                }
                if (typeof props.drillable === 'function' && !props.drillable(params.data)) {
                    return;
                }
                try {
                    await setMapData(params.data);
                    // 更新下钻路径
                    currentRegionData.value && pathArr.value.push(currentRegionData.value);
                }
                catch (err) {
                    console.warn(err);
                }
            }
        }
        // 初始化地图
        async function initMap(regionData) {
            try {
                await setMapData(regionData);
                // 更新下钻路径
                currentRegionData.value && pathArr.value.push(currentRegionData.value);
            }
            catch (err) {
                console.warn(err);
            }
        }
        // 重置路径
        async function resetPath(newPath = []) {
            if (newPath.length) {
                try {
                    const lowestRegion = newPath[newPath.length - 1];
                    await setMapData(lowestRegion);
                    pathArr.value = newPath;
                }
                catch (err) {
                    console.warn(err);
                }
            }
        }
        __expose({ initMap, setMapData, requestData, clearData, resetPath });
        return (_ctx, _cache) => {
            return (openBlock(), createElementBlock("div", _hoisted_1, [
                createElementVNode("div", _hoisted_2, [
                    createElementVNode("div", null, [
                        renderSlot(_ctx.$slots, "breadcrumb", {
                            pathArr: pathArr.value
                        }, () => [
                            (openBlock(true), createElementBlock(Fragment, null, renderList(pathArr.value, (item, index) => {
                                return (openBlock(), createElementBlock(Fragment, {
                                    key: item.acode
                                }, [
                                    createElementVNode("span", {
                                        class: "map-breadcrumb-label",
                                        onClick: ($event) => (jumpRegion(item, index))
                                    }, toDisplayString(item.name), 9 /* TEXT, PROPS */, _hoisted_3),
                                    (index !== pathArr.value.length - 1)
                                        ? (openBlock(), createElementBlock("span", _hoisted_4, ">"))
                                        : createCommentVNode("v-if", true)
                                ], 64 /* STABLE_FRAGMENT */));
                            }), 128 /* KEYED_FRAGMENT */)),
                            renderSlot(_ctx.$slots, "breadcrumbExtra", {
                                pathArr: pathArr.value
                            })
                        ])
                    ]),
                    renderSlot(_ctx.$slots, "extra")
                ]),
                createCommentVNode(" 地图 "),
                createVNode(script$1, {
                    option: mapOptions.value,
                    "click-fn": toLower,
                    onInitFinish: _cache[0] || (_cache[0] =
                        (echartInstance) => {
                            emits('initFinish', echartInstance);
                        }),
                    style: { "height": "100%", "z-index": "1" }
                }, null, 8 /* PROPS */, ["option"])
            ]));
        };
    }
});

script.__file = "packages/echarts-maps/index.vue";

const install = (app) => {
    app.component('EchartsBox', script$1);
    app.component('EchartsMaps', script);
};
var index = { install };

export { script$1 as EchartsBox, script as EchartsMaps, index as default };
