'use strict';

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

var vue = require('vue');
var mitt = require('mitt');
var util = require('../../utils/util.js');
var mergeDescriptors = require('../../utils/merge-descriptors.js');
var vm = require('../../utils/private/vm.js');
var cesiumProps = require('../../utils/cesium-props.js');
var config = require('../../utils/config.js');
var useLog = require('../private/use-log.js');
var index = require('../use-locale/index.js');
var index$1 = require('../use-events/index.js');
var lodashUnified = require('lodash-unified');
var useTimeout = require('../private/use-timeout.js');
var index$2 = require('../use-global-config/index.js');
var shared = require('@vue/shared');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var mitt__default = /*#__PURE__*/_interopDefaultLegacy(mitt);

const callbackCmpNames = ["Graphics", "VcEntity", "Datasource", "VcOverlayDynamic"];
function useCommon(props, { emit, attrs }, vcInstance) {
  const logger = useLog["default"](vcInstance);
  const { registerTimeout, removeTimeout } = useTimeout["default"]();
  vcInstance.alreadyListening = [];
  vcInstance.removeCallbacks = [];
  let unwatchFns = [];
  vcInstance.mounted = false;
  const vcMitt = mitt__default["default"]();
  vcInstance.vcMitt = vcMitt;
  const $services = vue.inject(config.vcKey);
  const { t } = index.useLocale();
  if ($services === void 0) {
    console.error(`${vcInstance.cesiumClass} ${t("vc.loadError")}`);
    return;
  }
  const parentVcInstance = vm.getVcParentInstance(vcInstance);
  const eventsState = index$1["default"](props, vcInstance, logger);
  vcInstance.children = [];
  const entityGraphics = {
    billboard: true,
    box: true,
    corridor: true,
    cylinder: true,
    ellipse: true,
    ellipsoid: true,
    label: true,
    model: true,
    tileset: true,
    path: true,
    plane: true,
    point: true,
    polygon: true,
    polyline: true,
    polylineVolume: true,
    rectangle: true,
    wall: true
  };
  const globalConfig = index$2.useGlobalConfig();
  const beforeLoad = async () => {
    emit("beforeLoad", vcInstance);
    if (parentVcInstance.nowaiting) {
      return true;
    } else {
      await parentVcInstance.proxy.creatingPromise;
    }
  };
  const load = async () => {
    var _a;
    if (vcInstance.mounted) {
      return false;
    }
    logger.debug(`${vcInstance.cesiumClass}---loading`);
    await beforeLoad();
    const { Cesium: Cesium2, viewer } = $services;
    vcInstance.viewer = viewer;
    vcInstance.Cesium = Cesium2;
    if (!parentVcInstance.cesiumObject && !parentVcInstance.nowaiting) {
      return await ((_a = parentVcInstance.proxy) == null ? void 0 : _a.load());
    }
    setPropsWatcher(true);
    return createCesiumObject().then(async (cesiumObject) => {
      vcInstance.cesiumObject = cesiumObject;
      return mount().then(() => {
        vcInstance.mounted = true;
        parentVcInstance.children.push(vcInstance);
        Object.assign(vcInstance.proxy, {
          cesiumObject: vcInstance.cesiumObject
        });
        const readyObj = { Cesium: Cesium2, viewer, cesiumObject, vm: vcInstance.proxy };
        emit("ready", readyObj);
        vcMitt.emit("ready", readyObj);
        logger.debug(`${vcInstance.cesiumClass}---loaded`);
        return readyObj;
      });
    });
  };
  const beforeUnload = async () => {
    await vcInstance.unloadingPromise;
  };
  const unload = async () => {
    await beforeUnload();
    for (let i = 0; i < vcInstance.children.length; i++) {
      const vcChildCmp = vcInstance.children[i].proxy;
      await vcChildCmp.unload();
    }
    vcInstance.children.length = 0;
    vcInstance.isUnmounted = false;
    return vcInstance.mounted ? unmount().then(async () => {
      setPropsWatcher(false);
      vcInstance.cesiumObject = void 0;
      vcInstance.mounted = false;
      vcInstance.removeCallbacks.forEach((removeCallback) => {
        removeCallback();
      });
      emit("destroyed", vcInstance);
      logger.debug(`${vcInstance.cesiumClass}---unmounted`);
      return vcInstance.renderByParent && !vcInstance.unloadingPromise ? parentVcInstance.proxy.unload() : true;
    }) : false;
  };
  const beforeReload = async () => {
    await vcInstance.reloadingPromise;
  };
  const reload = async () => {
    await beforeReload();
    return unload().then(() => {
      return load();
    });
  };
  const mount = async () => {
    var _a;
    eventsState.registerEvents(true);
    return ((_a = vcInstance.mount) == null ? void 0 : _a.call(vcInstance)) || true;
  };
  const unmount = async () => {
    var _a;
    eventsState.registerEvents(false);
    return ((_a = vcInstance.unmount) == null ? void 0 : _a.call(vcInstance)) || true;
  };
  const createCesiumObject = async () => {
    logger.debug("do createCesiumObject");
    if (shared.isFunction(vcInstance.createCesiumObject)) {
      return vcInstance.createCesiumObject();
    } else {
      const options = transformProps(props);
      return new Cesium[vcInstance.cesiumClass](options);
    }
  };
  const deepWatchHandler = (vueProp, watcherOptions) => {
    let deep = watcherOptions == null ? void 0 : watcherOptions.deep;
    const {
      SampledPositionProperty,
      Appearance,
      DebugAppearance,
      MaterialAppearance,
      PolylineColorAppearance,
      EllipsoidSurfaceAppearance,
      PerInstanceColorAppearance,
      PolylineMaterialAppearance
    } = Cesium;
    if (vueProp === "position") {
      deep = !(vcInstance.proxy[vueProp] instanceof SampledPositionProperty);
    } else if (vueProp === "appearance" || vueProp === "depthFailAppearance") {
      const value = vcInstance.proxy[vueProp];
      deep = !(value instanceof Appearance || value instanceof DebugAppearance || value instanceof MaterialAppearance || value instanceof PolylineColorAppearance || value instanceof EllipsoidSurfaceAppearance || value instanceof PerInstanceColorAppearance || value instanceof PolylineMaterialAppearance || util.getObjClassName(value).indexOf("Appearance") !== -1);
    }
    return deep;
  };
  const setPropsWatcher = (register) => {
    if (register) {
      if (!vcInstance.cesiumClass || !Cesium[vcInstance.cesiumClass]) {
        return;
      }
      props && Object.keys(props).forEach((vueProp) => {
        var _a, _b, _c, _d, _e;
        let cesiumProp = vueProp;
        if (vueProp === "labelStyle" || vueProp === "wmtsStyle") {
          cesiumProp = "style";
        } else if (vueProp === "bmKey") {
          cesiumProp = "key";
        }
        if (((_b = (_a = vcInstance.proxy) == null ? void 0 : _a.$options.watch) == null ? void 0 : _b[vueProp]) || vcInstance.alreadyListening.indexOf(vueProp) !== -1) {
          return;
        }
        const watcherOptions = (_d = (_c = vcInstance.proxy) == null ? void 0 : _c.$options.props[vueProp]) == null ? void 0 : _d.watcherOptions;
        const unwatch = (_e = vcInstance.proxy) == null ? void 0 : _e.$watch(vueProp, async (val, oldVal) => {
          await vcInstance.proxy.creatingPromise;
          const { cesiumObject } = vcInstance;
          const pd = cesiumObject && Object.getOwnPropertyDescriptor(cesiumObject, cesiumProp);
          const pdProto = cesiumObject && Object.getOwnPropertyDescriptor(Object.getPrototypeOf(cesiumObject), cesiumProp);
          const hasSetter = pd && (pd.writable || pd.set) || pdProto && (pdProto.writable || pdProto.set);
          if (hasSetter) {
            if (watcherOptions && watcherOptions.cesiumObjectBuilder) {
              const newVal = watcherOptions.cesiumObjectBuilder.call(vcInstance, val, vcInstance.viewer.scene.globe.ellipsoid);
              if (!(Cesium.defined(cesiumObject[cesiumProp]) && Cesium.defined(cesiumObject[cesiumProp]._callback))) {
                cesiumObject[cesiumProp] = newVal;
              }
            } else {
              cesiumObject[cesiumProp] = transformProp(cesiumProp, val);
            }
            return true;
          } else {
            if (!lodashUnified.isEqual(val, oldVal) || Array.isArray(val)) {
              if (attrs["reload-mode"] === "once" || attrs["reloadMode"] === "once" || globalConfig.value.reloadMode === "once") {
                removeTimeout();
                registerTimeout(() => {
                  ;
                  vcInstance.proxy.reload();
                }, 0);
              } else {
                vcInstance.reloadingPromise = new Promise((resolve, reject) => {
                  ;
                  vcInstance.proxy.reload().then(() => {
                    resolve(true);
                  }).catch((e) => {
                    reject(e);
                  });
                });
              }
            }
          }
        }, {
          deep: deepWatchHandler(vueProp, watcherOptions)
        });
        unwatchFns.push(unwatch);
      });
    } else {
      unwatchFns.forEach((item) => item());
      unwatchFns = [];
    }
  };
  const transformProps = (props2, childProps) => {
    const options = {};
    props2 && Object.keys(props2).forEach((vueProp) => {
      let cesiumProp = vueProp;
      if (vueProp === "labelStyle" || vueProp === "wmtsStyle") {
        cesiumProp = "style";
      } else if (vueProp === "bmKey") {
        cesiumProp = "key";
      }
      if (props2[vueProp] === void 0 || props2[vueProp] === null) {
        return;
      }
      const className = util.getObjClassName(props2[vueProp]);
      if (className && entityGraphics[cesiumProp] && (vcInstance.cesiumClass === "Entity" || vcInstance.cesiumClass.indexOf("DataSource") > 0 || vcInstance.cesiumClass === "VcOverlayDynamic")) {
        options[cesiumProp] = transformProps(props2[vueProp], childProps);
      } else {
        options[cesiumProp] = transformProp(vueProp, props2[vueProp], childProps);
      }
    });
    return options;
  };
  const transformProp = (prop, value, childProps) => {
    var _a, _b;
    const className = util.getObjClassName(value);
    if (className && entityGraphics[prop] && (vcInstance.cesiumClass === "Entity" || vcInstance.cesiumClass.indexOf("DataSource") > 0 || vcInstance.cesiumClass === "VcOverlayDynamic")) {
      return transformProps(value, childProps);
    } else {
      const cmpName = (_a = vcInstance.proxy) == null ? void 0 : _a.$options.name;
      let supportCallbackProperty = false;
      if (shared.isFunction(value) && cmpName) {
        callbackCmpNames.forEach((v) => {
          if (cmpName.indexOf(v) !== -1) {
            supportCallbackProperty = true;
          }
        });
      }
      const propOption = ((_b = vcInstance.proxy) == null ? void 0 : _b.$options.props[prop]) || (childProps == null ? void 0 : childProps[prop]) || cesiumProps[prop] && cesiumProps[prop][prop];
      return (propOption == null ? void 0 : propOption.watcherOptions) && !util.isEmptyObj(value) ? propOption.watcherOptions.cesiumObjectBuilder.call(vcInstance, value, vcInstance.viewer.scene.globe.ellipsoid) : supportCallbackProperty ? new Cesium.CallbackProperty(value, false) : value;
    }
  };
  const getServices = () => {
    return mergeDescriptors.mergeDescriptors({}, $services || {});
  };
  const creatingPromise = new Promise((resolve, reject) => {
    try {
      let isLoading = false;
      if ($services.viewer) {
        isLoading = true;
        load().then((e) => {
          resolve(e);
          isLoading = false;
        }).catch((e) => {
          emit("unready", e);
          reject(e);
        });
      }
      parentVcInstance.vcMitt.on("ready", () => {
        if (!isLoading && !vcInstance.isUnmounted) {
          load().then((e) => {
            resolve(e);
          }).catch((e) => {
            emit("unready", e);
            reject(e);
          });
        }
      });
    } catch (e) {
      emit("unready", e);
      reject(e);
    }
  });
  logger.debug(`${vcInstance.cesiumClass}---onCreated`);
  vue.onUnmounted(() => {
    logger.debug(`${vcInstance.cesiumClass}---onUnmounted`);
    vcInstance.unloadingPromise = new Promise((resolve, reject) => {
      unload().then(() => {
        logger.debug(`${vcInstance.cesiumClass}---unloaded`);
        resolve(true);
        vcInstance.isUnmounted = true;
        vcInstance.unloadingPromise = void 0;
        vcMitt.all.clear();
      });
    });
    vcInstance.alreadyListening = [];
  });
  Object.assign(vcInstance.proxy, {
    creatingPromise,
    load,
    unload,
    reload,
    getCreatingPromise: () => creatingPromise,
    getCesiumObject: () => vcInstance.cesiumObject
  });
  return {
    $services,
    load,
    unload,
    reload,
    creatingPromise,
    transformProp,
    transformProps,
    unwatchFns,
    setPropsWatcher,
    logger,
    getServices
  };
}

exports["default"] = useCommon;
//# sourceMappingURL=index.js.map
