/* eslint-disable no-useless-escape */
/* eslint-disable prettier/prettier */
import '@wisdom-utils/utils/lib/logger';
import _ from 'lodash';
import {
  addGlobalUncaughtErrorHandler,
  runAfterFirstMounted,
  registerMicroApps,
  setDefaultMountApp,
  loadMicroApp,
  prefetchApps,
  start,
} from 'qiankun';
import { event, store as microStore } from '@wisdom-utils/utils';
import { string } from '@wisdom-utils/utils/lib/helpers';
import micorConfig, { genActiveRule } from '../config/micor';
import { actionCreators } from './containers/App/store';
import loader from './render';
import store from './stores';
import actions from './actions';
const xss = require('xss');
// eslint-disable-next-line import/named
const { processComponentName } = string;
// eslint-disable-next-line no-undef
const Logger = logger('micro');
let micorManager = [];
let web4Load = false;
export const Configuration = {
  sandbox: {
    experimentalStyleIsolation: false,
    loose: true,
  },
  singular: false,
  scopedCSS: true,
  prefetch: true,
  getTemplate(tpl) {
    return tpl.replace(
      '<script language="javascript">setURL("18.10.10.253");supFlash(getVersion("td_cookie"));</script>',
      '',
    );
  },
  async fetch(url, ...args) {
    if (url.indexOf('cookie/flash.js') > -1) {
      return {
        async text() {
          return '';
        },
      };
    }
    return window.fetch(url, ...args);
  },
  // eslint-disable-next-line no-underscore-dangle
  excludeAssetFilter: url =>
    url.indexOf('framework/highcharts') !== -1 ||
    // url.indexOf('framework/amap/AMap.UI') !== -1 ||
    // url.indexOf('framework/4.9/init.js') !== -1 ||
    url.indexOf('DataPresentation.js') !== -1 ||
    url.indexOf('jquery-mousewheel-easyui-qrcode-cookie-resize-filesaver-fisheye-dateFormat-gridify.js') !== -1 ||
    url.indexOf('jquery') !== -1 ||
    url.indexOf('components/filetools/xlsx.core.min') !== -1 ||
    url.indexOf('managers/MapManager.js') !== -1 ||
    url.indexOf('jquery.mCustomScrollbar.js') !== -1 ||
    url.indexOf('QIAN_KUN_Platform.js') !== -1 ||
    url.indexOf('configuration/js') !== -1 ||
    url.indexOf('framework/three.js') !== -1 ||
    url.indexOf('threedimensional/frameworkthree') !== -1 ||
    url.indexOf('iframe/Civ3DLLab/js') !== -1 ||
    url.indexOf('framework/jquery/gridify-min.js') !== -1 ||
    url.indexOf('framework/jquery/gridify.qrcode.js') !== -1 ||
    url.indexOf('framework/application/Platform.js') !== -1 ||
    url.indexOf('webgisPanda/AMapTool') !== -1 ||
    url.indexOf('framework/underscore') !== -1 ||
    url.indexOf('echarts') !== -1 ||
    url.indexOf('lbs.amap.com') !== -1 ||
    url.indexOf('restapi.amap.com') !== -1 ||
    url.indexOf('webapi.amap.com') !== -1 ||
    url.indexOf('webapi.amap.com/count') !== -1 ||
    url.indexOf('webapi.amap.com/maps') !== -1 ||
    url.indexOf('restapi.amap.com/v3') !== -1 ||
    url.indexOf('api.map.baidu.com') !== -1 ||
    url.indexOf('map.baidu.com') !== -1 ||
    url.indexOf('pv.sohu.com') !== -1 ||
    url.indexOf('mt0.google.cn') !== -1 ||
    url.indexOf('mt1.google.cn') !== -1 ||
    url.indexOf('mt2.google.cn') !== -1 ||
    url.indexOf('mt3.google.cn') !== -1 ||
    url.indexOf('hm.baidu.com') !== -1 ||
    url.indexOf('framework/antv/antvL7.min.js') !== -1 ||
    url.indexOf('https://maponline0.bdimg.com') !== -1 ||
    url.indexOf('https://maponline1.bdimg.com') !== -1 ||
    url.indexOf('https://maponline2.bdimg.com') !== -1 ||
    url.indexOf('https://maponline3.bdimg.com') !== -1 ||
    url.indexOf('https://api.map.baidu.com/getscript') !== -1 ||
    url.indexOf('dlswbr.baidu.com') !== -1 ||
    url.indexOf('maponline0.bdimg.com') !== -1 ||
    url.indexOf('miao.baidu.com') !== -1 ||
    url.indexOf('build.loader.js') !== -1 ||
    url.indexOf('blob:') !== -1,
};

export const LifeCycle = {
  beforeLoad: [
    app => {
      store.dispatch(actionCreators.updateMicroMounted(true));
      Logger.info('[LifeCycle] before load %c%s', app);
    },
  ],
  beforeMount: [
    app => {
      microStore.off('event:globalConfig', () => {});
      Logger.info(`[LifeCycle] before mount %c%s ${app.name}`, app);
    },
  ],
  afterMount: [
    app => {
      store.dispatch(actionCreators.updateMicroMounted(false));
      Logger.info(`[LifeCycle] after mount %c%s ${app.name}`, app);
    },
  ],
  beforeUnmount: [
    app => {
      window.share.event.removeAllListeners('changeRoute');
      Logger.info(`[LifeCycle]  beforeUnmount %c%s ${app.name}`, app);
      // window.globalConfig = {}
      // createStoreage.remove(`__PANDA_STORE__${location.hostname}`)
    },
  ],
  afterUnmount: [
    app => {
      actions.offGlobalStateChange();
      Logger.info(`[LifeCycle] after unmount %c%s ${app.name}`, app);
    },
  ],
};

const microPackage = {
  civ_water:['react-file-viewer', 'ezuikit-js'],
  civ_webgis: ['react-file-viewer', 'xlsx'],
  civ_ai: ['react-file-viewer', 'ezuikit-js'],
  civ_monitor: ['react-file-viewer', 'ezuikit-js', 'xlsx'],
  civ_drainage: ['react-file-viewer', 'ezuikit-js', 'xlsx'],
  civ_workflow: ['react-file-viewer', 'xlsx'],
  civ_3d: ['react-file-viewer', 'ezuikit-js', 'xlsx'],
  civ_iot: ['xlsx'],
  civ_wisdomfactory: ['ezuikit-js'],
  civ_vms: ['ezuikit-js'],
  civ_customize: ['react-file-viewer', 'xlsx'],
  civ_assetmanage: [],
  civ_middleground: [],
  civ_energy: [],
  civ_hydrology: ['react-file-viewer', 'ezuikit-js', 'xlsx']
}

const extraPackage = {
  'react-file-viewer': { require: require.context('../node_modules/react-file-viewer/dist', true, /^.\/(dist\/)?[^\/]+\.js$/), entry: 'index.js' },
  'ezuikit-js': { require: require.context('../node_modules/ezuikit-js', true, /^.\/ezuikit\.js$/), entry: 'ezuikit.js' },
  'xlsx': { require: require.context('../node_modules/xlsx', true, /^.\/xlsx\.js$/), entry: 'xlsx.js' },
}

export const application = global => {
  const config = global || window.globalConfig || {};
  const applications = (config && config.products) || [];
  const products = [];
  applications &&
    Array.isArray(applications) &&
    applications.length > 0 &&
    applications.map(item => {
      if (item.PackageName === 'report') {
        products.push({
          name: item.PackageName,
          entry: item.RouteUrl,
          container: '#micro-container',
          activeRule: genActiveRule(`/civbase/${item.PackageName}`),
          props: {
            ...item.DefaultSetting,
            routerBase: item.PackageName,
            event,
            store: microStore,
          },
        });
      } else {
        products.push({
          name: item.PackageName,
          entry: `${window.location.protocol}//${window.location.host}/${item.PackageName}`,
          container: '#micro-container',
          activeRule: genActiveRule(`/civbase/${item.PackageName}`),
          props: {
            ...item.DefaultSetting,
            routerBase: item.PackageName,
            event,
            store: microStore,
          },
        });
      }
    });
  const workflow = products.filter(item => item.name === 'civ_workflow');
  if (workflow.length === 0) {
    products.push({
      name: 'civ_workflow',
      noPrefetch: true,
      entry: `${window.location.protocol}//${window.location.host}/civ_workflow`,
      container: '#micro-container',
      activeRule: genActiveRule('/civbase/civ_workflow'),
      props: {
        routerBase: 'civ_workflow',
        event,
        store: microStore,
      },
    });
  }
  const entrys = process.env.NODE_ENV !== 'production' ? micorConfig.dev : products;

  const apps = entrys.map(item => ({
    ...item,
    props: {
      emitter: window.share.event,
      baseRoot: item.name,
      event,
      store: microStore,
      // eslint-disable-next-line prettier/prettier
      globalConfig: /civweb4/.test(item.name) ? Object.assign({}, config, {homepage: config.homepage ? config.homepage.replace(/civweb\//, '') : config.homepage,}) : config,
      // createStoreage.get('globalConfig'),
      XMLHttpRequest: window.XMLHttpRequest,
      // offGlobalStateChange: actions.offGlobalStateChange
    },
    loader,
  }));

  return apps;
};

export const initSaveMicroApps = (pathName = '', global) => {
  /* eslint-disable */
  event.emit('loading', false);
  const microApps = application(global);
  microApps.map(app => {
    if(pathName.indexOf(app.name) > -1 && microPackage[app.name] && microPackage[app.name].map) {
      loadMicroPackage(app.name);
    }
  });
  setTimeout(() => {
    pathName.indexOf('civbase/civ_base') > -1 && event.emit('loading', false)
    const micro = microApps.filter(app => !/civweb4/.test(app.name)) ?? [];
    if(/civweb4/.test(pathName) && !web4Load) {
      event.emit("initweb", true);
      loadMicroApps(micro, pathName);
      web4Load = true;
    } else {
      const target = micorManager.slice(-1)[0] ?? null;
      if(!target || pathName.indexOf(target.name) == -1) {
        const microApp = microApps.filter(app => pathName.indexOf(app.name) > -1)[0] ?? null;
        if(microApp) micorManager.push({
          ...loadMicroApp(microApp, Configuration, LifeCycle), 
          name: microApp?.name, 
          store: microApp?.props?.store
        })
      }
    }
  })
};

export const loadMicroApps = (apps, pathName) => {
  const micro = apps.shift();
  const filter = micorManager.filter(mic => typeof(micro.name) === 'string' && micro.name.indexOf(mic.name) >= 0) ?? []
  if(filter.length === 0) {
    micorManager.push({
      ...loadMicroApp(micro, Configuration, LifeCycle).mountPromise.then(() => {
        if(apps.length > 0) {
          loadMicroApps(apps, pathName);
        } else {
          event.emit("finishInitWeb", pathName);
        }
      }).catch(error => {
        if(apps.length > 0) {
          loadMicroApps(apps, pathName);
        } else {
          event.emit("finishInitWeb", pathName);
        }
      }), 
      name: micro?.name, 
      store: micro?.props?.store
    })
  } else if(apps.length === 0) {
    event.emit("finishInitWeb", pathName);
  } else {
    loadMicroApps(apps, pathName);
  }
}

const loadMicroPackage = (name) => {
  require.ensure([], () => {
    microPackage[name].map((item) => {
      const microPkg = extraPackage[item];
      if(microPkg) {
        window.app.define(item, microPkg.require, microPkg.entry);
        delete extraPackage[item];
      }
    })
  })
}

export const initMicroApps = (url) => {
  if(!window.qiankunStarted) {
    // /* eslint-disable */
    const globalStore = store.getState().toJS();
    const globalConfig = window.globalConfig;
    microStore.set("event:globalConfig", {
      globalConfig: globalConfig,
      global: globalStore.globalf
    });
    const microApps = application();
    const micro = microApps.filter(app => {
      if(url.indexOf(app.name) > -1 && microPackage[app.name] && microPackage[app.name].map) {
        loadMicroPackage(app.name);
      }
      return !/civweb4/.test(app.name) && url.indexOf(app.name) < 0 && ['civ_water', 'civ_webgis', 'civ_monitor', 'civ_workflow', 'civ_customize'].indexOf(app.name) > -1 && !app.noPrefetch
    }) ?? [];
    if(window?.qiankunIsCache){
      microStore.on("event:dropCache", (() => {
        micorManager &&  micorManager.map((micro) => {
          micro.unmount && micro.unmount();
          micro = null;
        })
        micorManager = null;
      }));
      window.qiankunStarted = true;
      initSaveMicroApps(url);
      start(Configuration);
      const initAfterMounted = () => {
        window.parent && window.parent.postMessage({ type: 'runAfterFirstMounted' }, '*');
        event.emit('loading', false);
        Logger.info('[MainApp] first app mounted');
      }
      if(url.indexOf('civbase/civ_base') > -1) {
        initAfterMounted();
        prefetchApps(micro);
      } else {
        runAfterFirstMounted(() => {
          initAfterMounted();
          setTimeout(() => {
            prefetchApps(micro);
          }, 5000)
        });
      }
      addGlobalUncaughtErrorHandler(event => {
        console.log(event);
      });
    } else {
      window.qiankunStarted = true;
      registerMicroApps(microApps, LifeCycle);
      start(Configuration);
      const initAfterMounted = () => {
        micro.forEach((app) => {
          if(microPackage[app.name] && microPackage[app.name].map) {
            loadMicroPackage(app.name);
          }
        })
        window.parent && window.parent.postMessage({ type: 'runAfterFirstMounted' }, '*');
        event.emit('loading', false);
        Logger.info('[MainApp]first app mounted');
      }
      if(url.indexOf('civbase/civ_base') > -1) {
        setTimeout(() => {
          initAfterMounted();
        })
      } else {
        runAfterFirstMounted(() => {
          initAfterMounted();
        });
      }
      addGlobalUncaughtErrorHandler(event => {
        console.log(event);
      });
    }
  }
};

export const findMenuPath = widgets => {
  if (widgets && widgets.length > 0) {
    return widgets.map(item => {
      if (item.url && item.product) {
        return `${item.product}/${item.url}`;
      }
      return findMenuPath(item.widgets);
    })[0];
  }
  return '';
};

export const defaultApp = (setUrl) => {
    // eslint-disable-next-line no-undef
    const config = window.globalConfig;
    if (config && config.token) {
        let url = !config.home ?
        ((!config.homepage || _.isNull(config.homepage)) ? `/civbase/civweb4`: (`/civbase/${config.homepage.replace(/^\//, '')}`)) :  `/civbase/${config.homepage.replace(/^\//, '')}`;
        if(/civweb4/.test(setUrl || url)) {
          window.qiankunIsCache = false;
          console.log("请升级首页功能");
        }
        initMicroApps(setUrl || url);
        setDefaultMountApp(setUrl || url);
        micorManager = [];
        window.share.event.emit('visible', setUrl || url);
    }
};

/**
 * window.app主要功能:
   define 定义项目的公共库,主要用来解决JS公共库的管理问题
   require 引用自己的定义的基础库,配合define来使用
   routes 用于存放全局的路由,子项目路由添加到window.app.routes,用于完成路由的注册
   init 注册入口,为子项目添加上namesapce标识,注册上子项目管理数据流的reducers
 */

window.app = {

    modules: {},
    require: function (request, method) {

        if (request !== '.' && this.modules[request]) {
            return _.isFunction(this.modules[request]) ? this.modules[request]() : _.isFunction(this.modules[request][method]) && this.modules[request][method]();
        }
        if (request === '.') {
            return
        }
        /**
         * 特殊处理antd
         */
        if(request.indexOf('antd') > -1) {
            const modules = this.modules['antd']();
            const r = request.split('/');
            const pkg = r[2];
            if(r.length >3) {
                const m = request.split('/')
                const styles = this.modules[m.join('-')];
                if(styles) {
                    if(r[3] === 'style') {
                        return styles['index.js'] && styles['index.js']();
                    }
                    return styles[r[3]] && styles[r[3]]();
                }
                return
            }
            const componentName = processComponentName(pkg, {
                firstUpperCase: pkg === 'message' || pkg === 'notification' ? false: true
            });

            return modules[componentName];
        }

        if(request.indexOf(method) > -1) {
            request = request.replace(method, '').replace(/\//, '')
            return _.isFunction(this.modules[request]) && this.modules[request]();
        }
        return _.isFunction(this.modules[request]) && this.modules[request]();
    },
    define: function (name, context, index) {

        let keys = context.keys();
        for (let key of keys) {
            let parts = name.indexOf('@') > -1 || name == 'react/jsx-runtime' ? [name, ...(key.slice(1).split('/'))] : (name + key.slice(1)).split('/');
            parts = parts.filter(item => item !== "");
            let dir = this.modules;
            for (let i = 0; i < parts.length - 1; i++) {
                let part = parts[i];
                if (!dir.hasOwnProperty(part)) {
                    dir[part] = {};
                }
                dir = dir[part];
            }
            dir[parts[parts.length - 1]] = context.bind(context, key);
        }
        if (index && index !== null) {

            this.modules[name] = this.modules[name][index];
        }
    },
    init: function (namespace, reducers) {
        [namespace] = reducers;
    }
};

window.app.define('react', require.context('react', true, /^.\/index\.js$/), 'index.js');
window.app.define('react/jsx-runtime', require.context('../node_modules/react', true, /^.\/jsx-runtime\.js$/), 'jsx-runtime.js');
window.app.define('react-dom', require.context('react-dom', true, /^.\/index\.js$/), 'index.js');
window.app.define('react-router', require.context('react-router', true, /^.\/index\.js$/), 'index.js');
window.app.define('lodash', require.context('lodash', true, /^.\/index\.js$/), 'index.js');
window.app.define('connected-react-router', require.context('../node_modules/connected-react-router/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('react-helmet', require.context('../node_modules/react-helmet/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'Helmet.js');
window.app.define('qrcode.react', require.context('../node_modules/qrcode.react/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('qr.js', require.context('qr.js', true, /^.\/index\.js$/), 'index.js');
window.app.define('query-string', require.context('query-string', true, /^.\/index\.js$/), 'index.js');
window.app.define('react-helmet-async', require.context('../node_modules/react-helmet-async/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('immutable', require.context('../node_modules/immutable/dist', true, /^.\/(dist\/)?[^\/]+\.js$/), 'immutable.min.js');
window.app.define('redux-immutable', require.context('../node_modules/redux-immutable/dist', true, /^.\/(dist\/)?[^\/]+\.js$/), 'index.js');
window.app.define('redux-logger', require.context('../node_modules/redux-logger/dist', true, /^.\/(dist\/)?[^\/]+\.js$/), 'redux-logger.js');
window.app.define('react-router-dom', require.context('react-router-dom', true, /^.\/index\.js$/), 'index.js');
window.app.define('react-redux', require.context('../node_modules/react-redux/dist', true, /^.\/(dist\/)?[^\/]+\.js$/), 'react-redux.min.js');
window.app.define('redux', require.context('../node_modules/redux/dist', true, /^.\/(dist\/)?[^\/]+\.js$/), 'redux.min.js');
window.app.define('mqtt-client', require.context('../node_modules/mqtt-client/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('kit_logger', require.context('../node_modules/kit_logger/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('kit_utils', require.context('../node_modules/kit_utils/lib', true, /^.\/(lib\/)?[^\/]+\.js$/));
window.app.define('kit_global_config', require.context('../node_modules/kit_global_config/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('axios', require.context('../node_modules/axios/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'axios.js');
window.app.define('js-base64', require.context('../node_modules/js-base64', true, /[^\/]+\.js$/), 'base64.js');
window.app.define('@wisdom-utils/utils', require.context('../node_modules/@wisdom-utils/utils/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('@wisdom-utils/runtime', require.context('../node_modules/@wisdom-utils/runtime/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');

window.app.define('@wisdom-map/amap', require.context('../node_modules/@wisdom-map/amap/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('@wisdom-map/arcgismap', require.context('../node_modules/@wisdom-map/arcgismap/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('@wisdom-map/basemap', require.context('../node_modules/@wisdom-map/basemap/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');

window.app.define('@ant-design/pro-list', require.context('../node_modules/@ant-design/pro-list/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('classnames', require.context('classnames', true, /^.\/index\.js$/), 'index.js');
window.app.define('@ant-design/icons', require.context('../node_modules/@ant-design/icons/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('@ant-design/pro-utils', require.context('../node_modules/@ant-design/pro-utils/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('@ant-design/pro-layout', require.context('../node_modules/@ant-design/pro-layout/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('@ant-design/pro-table', require.context('../node_modules/@ant-design/pro-table/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('@ant-design/pro-form', require.context('../node_modules/@ant-design/pro-form/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('@ant-design/pro-provider', require.context('../node_modules/@ant-design/pro-provider/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('pinyin-match', require.context('../node_modules/pinyin-match/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'main.js');
window.app.define('react-intl', require.context('../node_modules/react-intl/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('echarts', require.context('../node_modules/echarts/dist', true, /^.\/echarts.min\.js$/), 'echarts.min.js');
window.app.define('moment', require.context('moment', true, /^.\/moment\.js$/), 'moment.js');

window.app.define('@wisdom-map/pd-map', require.context('../node_modules/@wisdom-map/pd-map/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');
window.app.define('@wisdom-map/gis-utils', require.context('../node_modules/@wisdom-map/gis-utils/lib', true, /^.\/(lib\/)?[^\/]+\.js$/), 'index.js');