import { observable } from 'mobx'
import { createMpApp } from '@cloudbase/weda-client';
import { createComputed, formatEnum, enumOptions } from '<%= subLevelPath %>../common/util'
import appGlobal from '<%= subLevelPath %>../app/app-global'
import { createDataset } from '<%= subLevelPath %>../datasources/index'

import lodashGet from 'lodash.get';
import config from '<%= subLevelPath %>../common/config';
import { generateDatasetQuery } from '../common/util';


<%= importor.state? `import state from '../lowcode/state'` : "const state = {}" %>
<%= importor.computed? `import computed from '../lowcode/computed'` : "const computed = {}" %>
<%= importor.common? `import common from './common'` : "const common = {}" %>

const mainAppKey = '__weappsMainApp'

<% function printBoundData(boundData={}) {
  /**
   * TODO: copy 过来的代码
   * 一些模板层面的工具应该如何复用？
   */
  const list = []
  Object.entries(boundData).map(([prop, bindMeta])=>{
    const str = `'${prop}': ($app, lists, forItems, event, $context, $w, params) => {${bindMeta.imports} return(
      ${bindMeta.expression === '' ? 'undefined': bindMeta.expression}
    )}`
    list.push(str)
  })
  return list.join(',')
}%>
<% function printEventHandler(eventHandlers) {
  /**
   * TODO: copy 过来的代码
   * 一些模板层面的工具应该如何复用？
   */
  Object.entries(eventHandlers).map(([handlerName, listeners])=>{
    print(`"${handlerName}": [
      ${listeners.map(l=>{
        return `{
          key: '${l.key||''}',
          sourceKey: '${ l.sourceKey||"" }',
          handler: ${l.generateHandler(subLevelPath) || 'undefined'},
          args: ${JSON.stringify(l.args||{}, undefined, 2)},
          argsBinds: {${printBoundData(l.argsBinds)}}
        }`
      }).join(',')}
    ],`)
  })
}%>

export const app = createGlboalApi()
export const $app = new Proxy({}, { get: function(obj, prop){ return app[prop] }});
export const $w = new Proxy(
  {},
  {
    get(_, prop) {
      return app.__internal__.$w?.[prop];
    },
  },
);

function createGlboalApi() {
  const mpApp = createMpApp({
    appConfig: {
      staticResourceDomain: config.domain,
      ...(<%= appConfig %>)
    },
  });
  const globalAPI = Object.assign(mpApp, {
    domain: config.domain,
    pages: {},
    session: {
      //configure: sdk.configure,
      //request: sdk.request,
      //getSessionId: sdk.getSessionId,
    },
    state: observable(state),
    computed: createComputed(computed),
    common,
    ...mpApp,
    invoke(params) {
      const $page = globalAPI.utils.getCurrentPage();
      return $page.invokeComponentMethod(params)
    },
    // ... other sdk apis & apis from mp
  }) // The global api exposed to lowcode

  globalAPI.__internal__.enumOptions = enumOptions
  globalAPI.utils.formatEnum = formatEnum
  /**
   * @deprecated utils._getConfig
   */
  globalAPI.utils._getConfig = () => {
    return globalAPI.__internal__.getConfig()
  }

  let dataset = createDataset('$global')
  dataset.query = generateDatasetQuery({<% Object.entries(appQuery).map(([id, item])=>{%>
    <%= id %>: { <% const { dataBinds, eventHandlers, handler, ...rest } = item %>
      ...(<%= JSON.stringify(rest, undefined, 2) %>),
      handler: <%= handler %>,
      dataBinds: {<%= printBoundData(dataBinds) %>},
      eventHandlers: {<% printEventHandler(eventHandlers) %>}
    },<%}) %>
  }, {
    $app: globalAPI,
    $w: globalAPI.__internal__.$w,
  })
  globalAPI.dataset = dataset
  globalAPI.state.dataset = dataset
  globalAPI.setState = (userSetState) => {
    Object.keys(userSetState).forEach((keyPath) => {
      globalAPI.utils.set(globalAPI.dataset.state, keyPath, userSetState[keyPath]);
    });
  };

  const subPackageName = '<%= subPackageName %>'
  if (subPackageName) {
    // is sub app
    globalAPI.mainApp = appGlobal[mainAppKey]
    const mpApp = getApp()
    mpApp && (mpApp.subApp = globalAPI)
  } else {
    // is mainApp
    appGlobal[mainAppKey] = globalAPI
  }

  // # expose some sdk modules
  /* const sdkModsIncluded = ['flow', 'getPageOptions', 'getLaunchOptions']
  sdkModsIncluded.forEach(key => {
    globalAPI[key] = sdk[key]
  }) */

  return globalAPI
}
