text: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  
  import CallbackManager from './CallbackManager'
  import Element from '../vdom/Element'
  import { typof } from '../utils'
  import { normalizePrimitive } from './normalize'
  
  let fallback = function () {}
  
  // The API of TaskCenter would be re-design.
  export class TaskCenter {
    constructor (id, sendTasks) {
      Object.defineProperty(this, 'instanceId', {
        enumerable: true,
        value: String(id)
      })
      Object.defineProperty(this, 'callbackManager', {
        enumerable: true,
        value: new CallbackManager(id)
      })
      fallback = sendTasks || function () {}
    }
  
    callback (callbackId, data, ifKeepAlive) {
      return this.callbackManager.consume(callbackId, data, ifKeepAlive)
    }
  
    registerHook (...args) {
      return this.callbackManager.registerHook(...args)
    }
  
    triggerHook (...args) {
      return this.callbackManager.triggerHook(...args)
    }
  
    updateData (componentId, newData) {
      this.callModule('dom', 'updateComponentData', [newData])
    }
  
    destroyCallback () {
      return this.callbackManager.close()
    }
  
    /**
     * Normalize a value. Specially, if the value is a function, then generate a function id
     * and save it to `CallbackManager`, at last return the function id.
     * @param  {any}        v
     * @return {primitive}
     */
    normalize (v) {
      const type = typof(v)
      if (v && v instanceof Element) {
        return v.ref
      }
      if (v && v._isVue && v.$el instanceof Element) {
        return v.$el.ref
      }
      if (type === 'Function') {
        return this.callbackManager.add(v).toString()
      }
      return normalizePrimitive(v)
    }
  
    send (type, params, args, options) {
      const { action, component, ref, module, method } = params
  
      args = args.map(arg => this.normalize(arg))
  
      switch (type) {
        case 'dom':
          return this[action](this.instanceId, args)
        case 'component':
          return this.componentHandler(this.instanceId, ref, method, args, Object.assign({ component }, options))
        default:
          return this.moduleHandler(this.instanceId, module, method, args, options)
      }
    }
  
    callDOM (action, args) {
      return this[action](this.instanceId, args)
    }
  
    callComponent (ref, method, args, options) {
      return this.componentHandler(this.instanceId, ref, method, args, options)
    }
  
    callModule (module, method, args, options) {
      return this.moduleHandler(this.instanceId, module, method, args, options)
    }
  }
  
  export function init () {
    const DOM_METHODS = {
      createFinish: global.callCreateFinish,
      updateFinish: global.callUpdateFinish,
      refreshFinish: global.callRefreshFinish,
  
      createBody: global.callCreateBody,
  
      addElement: global.callAddElement,
      removeElement: global.callRemoveElement,
      moveElement: global.callMoveElement,
      updateAttrs: global.callUpdateAttrs,
      updateStyle: global.callUpdateStyle,
  
      addEvent: global.callAddEvent,
      removeEvent: global.callRemoveEvent
    }
    const proto = TaskCenter.prototype
  
    for (const name in DOM_METHODS) {
      const method = DOM_METHODS[name]
      proto[name] = method ?
        (id, args) => method(id, ...args) :
        (id, args) => fallback(id, [{ module: 'dom', method: name, args }], '-1')
    }
  
    proto.componentHandler = global.callNativeComponent ||
      ((id, ref, method, args, options) =>
        fallback(id, [{ component: options.component, ref, method, args }]))
  
    proto.moduleHandler = global.callNativeModule ||
      ((id, module, method, args) =>
        fallback(id, [{ module, method, args }]))
  }
  