/*
 * 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 Node from './Node'
import {
  getDoc,
  getTaskCenter,
  linkParent,
  nextElement,
  previousElement,
  insertIndex,
  moveIndex,
  removeIndex
} from './operation'
import { uniqueId, isEmpty, checkLevel, debugLog } from '../shared/utils'
import { getWeexElement, setElement } from './WeexElement'

const DEFAULT_TAG_NAME = 'div'
const BUBBLE_EVENTS = [
  'click', 'longpress', 'touchstart', 'touchmove', 'touchend',
  'panstart', 'panmove', 'panend', 'horizontalpan', 'verticalpan', 'swipe'
]

function registerNode (docId, node) {
  const doc = getDoc(docId)
  doc.nodeMap[node.nodeId] = node
}

export default class Element extends Node {
  constructor (type = DEFAULT_TAG_NAME, props, isExtended) {
    super()

    const WeexElement = getWeexElement(type)
    if (WeexElement && !isExtended) {
      return new WeexElement(type, props, true)
    }

    props = props || {}
    this.nodeType = 1
    this.nodeId = uniqueId()
    this.ref = this.nodeId
    this.type = type
    this.attr = props.attr || {}
    this.style = props.style || {}
    this.classStyle = props.classStyle || {}
    this.event = {}
    this.children = []
    this.pureChildren = []
  }

  /**
   * Append a child node.
   * @param {object} node
   * @return {undefined | number} the signal sent by native
   */
  appendChild (node) {
    if (node.parentNode && node.parentNode !== this) {
      return
    }
    /* istanbul ignore else */
    if (!node.parentNode) {
      if (checkLevel('debug')) {
        debugLog(`[appendChild](${this.docId},${node.type},${node.ref}) `
          + `Append <${node.type}> to <${this.type}> (${this.ref}).`)
      }
      linkParent(node, this)
      insertIndex(node, this.children, this.children.length, true)
      if (this.docId) {
        registerNode(this.docId, node)
      }
      if (node.nodeType === 1) {
        insertIndex(node, this.pureChildren, this.pureChildren.length)
        const taskCenter = getTaskCenter(this.docId)
        if (taskCenter) {
          return taskCenter.send(
            'dom',
            { action: 'addElement' },
            [this.ref, node.toJSON(), -1]
          )
        }
      }
    }
    else {
      if (checkLevel('debug')) {
        debugLog(`[appendChild](${this.docId},${node.type},${node.ref}) `
          + `Move <${node.type}> to ${this.children.length} of <${this.type}> (${this.ref}).`)
      }
      moveIndex(node, this.children, this.children.length, true)
      if (node.nodeType === 1) {
        const index = moveIndex(node, this.pureChildren, this.pureChildren.length)
        const taskCenter = getTaskCenter(this.docId)
        if (taskCenter && index >= 0) {
          return taskCenter.send(
            'dom',
            { action: 'moveElement' },
            [node.ref, this.ref, index]
          )
        }
      }
    }
  }

  /**
   * Insert a node before specified node.
   * @param {object} node
   * @param {object} before
   * @return {undefined | number} the signal sent by native
   */
  insertBefore (node, before) {
    if (node.parentNode && node.parentNode !== this) {
      return
    }
    if (node === before || (node.nextSibling && node.nextSibling === before)) {
      return
    }
    if (!node.parentNode) {
      if (checkLevel('debug')) {
        debugLog(`[insertBefore](${this.docId},${node.type},${node.ref}) `
          + `Insert <${node.type}> to <${this.type}> (${this.ref}), before (${before.ref}).`)
      }
      linkParent(node, this)
      insertIndex(node, this.children, this.children.indexOf(before), true)
      if (this.docId) {
        registerNode(this.docId, node)
      }
      if (node.nodeType === 1) {
        const pureBefore = nextElement(before)
        const index = insertIndex(
          node,
          this.pureChildren,
          pureBefore
            ? this.pureChildren.indexOf(pureBefore)
            : this.pureChildren.length
        )
        const taskCenter = getTaskCenter(this.docId)
        if (taskCenter) {
          return taskCenter.send(
            'dom',
            { action: 'addElement' },
            [this.ref, node.toJSON(), index]
          )
        }
      }
    }
    else {
      moveIndex(node, this.children, this.children.indexOf(before), true)
      if (node.nodeType === 1) {
        const pureBefore = nextElement(before)
        /* istanbul ignore next */
        const index = moveIndex(
          node,
          this.pureChildren,
          pureBefore
            ? this.pureChildren.indexOf(pureBefore)
            : this.pureChildren.length
        )
        const taskCenter = getTaskCenter(this.docId)
        if (taskCenter && index >= 0) {
          return taskCenter.send(
            'dom',
            { action: 'moveElement' },
            [node.ref, this.ref, index]
          )
        }
      }
    }
  }

  /**
   * Insert a node after specified node.
   * @param {object} node
   * @param {object} after
   * @return {undefined | number} the signal sent by native
   */
  insertAfter (node, after) {
    if (node.parentNode && node.parentNode !== this) {
      return
    }
    if (node === after || (node.previousSibling && node.previousSibling === after)) {
      return
    }
    if (!node.parentNode) {
      if (checkLevel('debug')) {
        debugLog(`[insertAfter](${this.docId},${node.type},${node.ref}) `
          + `Insert <${node.type}> to <${this.type}> (${this.ref}), after (${after.ref}).`)
      }
      linkParent(node, this)
      insertIndex(node, this.children, this.children.indexOf(after) + 1, true)
      /* istanbul ignore else */
      if (this.docId) {
        registerNode(this.docId, node)
      }
      if (node.nodeType === 1) {
        const index = insertIndex(
          node,
          this.pureChildren,
          this.pureChildren.indexOf(previousElement(after)) + 1
        )
        const taskCenter = getTaskCenter(this.docId)
        /* istanbul ignore else */
        if (taskCenter) {
          return taskCenter.send(
            'dom',
            { action: 'addElement' },
            [this.ref, node.toJSON(), index]
          )
        }
      }
    }
    else {
      moveIndex(node, this.children, this.children.indexOf(after) + 1, true)
      if (node.nodeType === 1) {
        const index = moveIndex(
          node,
          this.pureChildren,
          this.pureChildren.indexOf(previousElement(after)) + 1
        )
        const taskCenter = getTaskCenter(this.docId)
        if (taskCenter && index >= 0) {
          return taskCenter.send(
            'dom',
            { action: 'moveElement' },
            [node.ref, this.ref, index]
          )
        }
      }
    }
  }

  /**
   * Remove a child node, and decide whether it should be destroyed.
   * @param {object} node
   * @param {boolean} preserved
   */
  removeChild (node, preserved) {
    if (node.parentNode) {
      removeIndex(node, this.children, true)
      if (node.nodeType === 1) {
        if (checkLevel('debug')) {
          debugLog(`[removeChild](${this.docId},${node.type},${node.ref}) `
            + `Remove <${node.type}> from <${this.type}> (${this.ref}).`)
        }
        removeIndex(node, this.pureChildren)
        const taskCenter = getTaskCenter(this.docId)
        if (taskCenter) {
          taskCenter.send(
            'dom',
            { action: 'removeElement' },
            [node.ref]
          )
        }
      }
    }
    if (!preserved) {
      node.destroy()
    }
  }

  /**
   * Clear all child nodes.
   */
  clear () {
    const taskCenter = getTaskCenter(this.docId)
    /* istanbul ignore else */
    if (taskCenter) {
      this.pureChildren.forEach(node => {
        taskCenter.send(
          'dom',
          { action: 'removeElement' },
          [node.ref]
        )
      })
    }
    this.children.forEach(node => {
      node.destroy()
    })
    this.children.length = 0
    this.pureChildren.length = 0
  }

  /**
   * Set an attribute, and decide whether the task should be send to native.
   * @param {string} key
   * @param {string | number} value
   * @param {boolean} silent
   */
  setAttr (key, value, silent) {
    if (this.attr[key] === value && silent !== false) {
      return
    }
    this.attr[key] = value
    const taskCenter = getTaskCenter(this.docId)
    if (!silent && taskCenter) {
      const result = {}
      result[key] = value
      taskCenter.send(
        'dom',
        { action: 'updateAttrs' },
        [this.ref, result]
      )
    }
  }

  /**
   * Set batched attributes.
   * @param {object} batchedAttrs
   * @param {boolean} silent
   */
  setAttrs (batchedAttrs, silent) {
    if (isEmpty(batchedAttrs)) return
    const mutations = {}
    for (const key in batchedAttrs) {
      if (this.attr[key] !== batchedAttrs[key]) {
        this.attr[key] = batchedAttrs[key]
        mutations[key] = batchedAttrs[key]
      }
    }
    if (!isEmpty(mutations)) {
      const taskCenter = getTaskCenter(this.docId)
      if (!silent && taskCenter) {
        taskCenter.send(
          'dom',
          { action: 'updateAttrs' },
          [this.ref, mutations]
        )
      }
    }
  }

  /**
   * Set a style property, and decide whether the task should be send to native.
   * @param {string} key
   * @param {string | number} value
   * @param {boolean} silent
   */
  setStyle (key, value, silent) {
    if (this.style[key] === value && silent !== false) {
      return
    }
    this.style[key] = value
    const taskCenter = getTaskCenter(this.docId)
    if (!silent && taskCenter) {
      const result = {}
      result[key] = value
      taskCenter.send(
        'dom',
        { action: 'updateStyle' },
        [this.ref, result]
      )
    }
  }

  /**
   * Set batched style properties.
   * @param {object} batchedStyles
   * @param {boolean} silent
   */
  setStyles (batchedStyles, silent) {
    if (isEmpty(batchedStyles)) return
    const mutations = {}
    for (const key in batchedStyles) {
      if (this.style[key] !== batchedStyles[key]) {
        this.style[key] = batchedStyles[key]
        mutations[key] = batchedStyles[key]
      }
    }
    if (!isEmpty(mutations)) {
      const taskCenter = getTaskCenter(this.docId)
      if (!silent && taskCenter) {
        taskCenter.send(
          'dom',
          { action: 'updateStyle' },
          [this.ref, mutations]
        )
      }
    }
  }

  /**
   * Set style properties from class.
   * @param {object} classStyle
   */
  setClassStyle (classStyle) {
    // reset previous class style to empty string
    for (const key in this.classStyle) {
      this.classStyle[key] = ''
    }

    Object.assign(this.classStyle, classStyle)
    const taskCenter = getTaskCenter(this.docId)
    if (taskCenter) {
      taskCenter.send(
        'dom',
        { action: 'updateStyle' },
        [this.ref, this.toStyle()]
      )
    }
  }

  /**
   * Add an event handler.
   * @param {string} event type
   * @param {function} event handler
   */
  addEvent (type, handler, params) {
    if (!this.event) {
      this.event = {}
    }
    if (!this.event[type]) {
      if (checkLevel('debug')) {
        debugLog(`[addEvent](${this.docId},${this.type},${this.ref}) `
          + `Add "${type}" event on <${this.type}> (${this.ref}).`)
      }
      this.event[type] = { handler, params }
      const taskCenter = getTaskCenter(this.docId)
      if (taskCenter) {
        taskCenter.send(
          'dom',
          { action: 'addEvent' },
          [this.ref, type]
        )
      }
    }
  }

  /**
   * Remove an event handler.
   * @param {string} event type
   */
  removeEvent (type) {
    if (this.event && this.event[type]) {
      if (checkLevel('debug')) {
        debugLog(`[removeEvent](${this.docId},${this.type},${this.ref}) `
          + `Remove "${type}" event on <${this.type}> (${this.ref}).`)
      }
      delete this.event[type]
      const taskCenter = getTaskCenter(this.docId)
      if (taskCenter) {
        taskCenter.send(
          'dom',
          { action: 'removeEvent' },
          [this.ref, type]
        )
      }
    }
  }

  /**
   * Fire an event manually.
   * @param {string} type type
   * @param {function} event handler
   * @param {boolean} isBubble whether or not event bubble
   * @param {boolean} options
   * @return {} anything returned by handler function
   */
  fireEvent (type, event, isBubble, options) {
    let result = null
    let isStopPropagation = false
    const eventDesc = this.event[type]
    if (eventDesc && event) {
      if (checkLevel('debug')) {
        debugLog(`[fireEvent](${this.docId},${this.type},${this.ref}) `
          + `Fire "${type}" event on <${this.type}> (${this.ref}).`)
      }
      const handler = eventDesc.handler
      event.stopPropagation = () => {
        isStopPropagation = true
      }
      try {
        if (options && options.params) {
          result = handler.call(this, ...options.params, event)
        }
        else {
          result = handler.call(this, event)
        }
      }
      catch (error) {
        console.error(`[JS Framework] Failed to invoke the event handler of "${type}" `
          + `on ${this.type} (${this.ref}):\n ${error.toString()}`)
        throw error
      }
    }

    if (!isStopPropagation
      && isBubble
      && (BUBBLE_EVENTS.indexOf(type) !== -1)
      && this.parentNode
      && this.parentNode.fireEvent) {
      event.currentTarget = this.parentNode
      this.parentNode.fireEvent(type, event, isBubble) // no options
    }

    return result
  }

  /**
   * Get all styles of current element.
   * @return {object} style
   */
  toStyle () {
    return Object.assign({}, this.classStyle, this.style)
  }

  /**
   * Convert current element to JSON like object.
   * @param {boolean} ignoreChildren whether to ignore child nodes, default false
   * @return {object} element
   */
  toJSON (ignoreChildren = false) {
    const result = {
      ref: this.ref.toString(),
      type: this.type,
      attr: this.attr,
      style: this.toStyle()
    }
    const event = []
    for (const type in this.event) {
      const { params } = this.event[type]
      if (!params) {
        event.push(type)
      }
      else {
        event.push({ type, params })
      }
    }
    if (event.length) {
      result.event = event
    }
    if (!ignoreChildren && this.pureChildren.length) {
      result.children = this.pureChildren.map((child) => child.toJSON())
    }
    return result
  }

  /**
   * Convert to HTML element tag string.
   * @return {stirng} html
   */
  toString () {
    return '<' + this.type +
    ' attr=' + JSON.stringify(this.attr) +
    ' style=' + JSON.stringify(this.toStyle()) + '>' +
    this.pureChildren.map((child) => child.toString()).join('') +
    '</' + this.type + '>'
  }
}

setElement(Element)
