import { guid, makeError } from '../common'
import { constants as C } from '../constants'
import { locale as L } from '../lang/zh_TW.js'
import Collection from './ADCollection.js'
import Block from './ADBlock.js'
import Page from './ADPage.js'
import $ from 'jquery'

import './ADLayer.css'

const _properties = new WeakMap()

function Layer (property, target) {
  var _$this = (function (p) {
    for (var k = 0, l = p.length; k < l; k++) {
      if (p[k] instanceof $) return p[k]
      if (p[k] instanceof window.HTMLElement) return $(p[k])
    }
    return false
  })([target, property, property && property.target])

  if (_$this && _$this.length === 0) {
    return null
  }
  _properties.set(this || _$this[0].adllayer, {
    $this: _$this
  })
  const _ = _properties.get(this)
  if (_$this && _$this.length > 0) {
    if (_$this[0].adllayer && _$this[0].adllayer instanceof Layer) {
      return _$this[0].adllayer
    } else {
      if (!(this instanceof Layer)) {
        return new Layer(property, _$this)
      } else {
        if (_$this.prop('tagName') === 'DIV') {
          if (!_$this.hasClass('layer')) {
            _$this.addClass('layer')
          }
        } else {
          return null
        }
      }
    }
  } else if (!_$this) {
    if (!(this instanceof Layer)) {
      return new Layer(property)
    }
    _.$this = $('<div class="layer" id="layer' + guid() + '">')
  }

  _.$this[0].adllayer = this
  this.update(property)
}

const prototype = Layer.prototype
prototype.id = function id (newId) {
  const _ = _properties.get(this) || {}
  if (newId === undefined) {
    return _.$this.attr('id')
  } else {
    _.$this.attr('id', newId)
    return this
  }
}

prototype.name = function name (val) {
  const _ = _properties.get(this) || {}
  switch (arguments.length) {
    case 0:
      return _.$this.attr('name')
    default:
      _.$this.attr('name', val)
      return this
  }
}

prototype.type = function type (val) {
  const _ = _properties.get(this) || {}
  switch (arguments.length) {
    case 0:
      return _.$this.attr('data-type')
    default:
      _.$this.attr('data-type', val)
      return this
  }
}

prototype.update = function update (property) {
  const _ = _properties.get(this) || {}
  var _$this = _.$this
  if ($.isPlainObject(property)) {
    for (const attribute in property) {
      switch (attribute) {
        case 'id':
          _$this.attr('id', property.id)
          break
        case 'name':
          _$this.attr('name', property.name)
          break
        case 'type':
          switch (property.type) {
            case C`LAYER_BACKGROUND`:
            case C`LAYER_CONTENT`:
            case C`LAYER_FOREGROUND`:
              _$this.attr('data-type', property.type)
              break
            default:
              _$this.attr('data-type', C`LAYER_CONTENT`)
          }
      }
    }
  }
  if (this.name() === undefined) {
    _.$this.attr('name', L`_STR_UNTITLE`)
  }
  if (this.type() === undefined) {
    _$this.attr('data-type', C`LAYER_CONTENT`)
  }
}

prototype.editor = function editor () {
  const _ = _properties.get(this) || {}
  var _parent = _.parent
  if (_parent !== undefined) return _parent
  var layout = _.$this.closest('.AD_Layout')
  if (layout.length && layout[0].adl) {
    _.parent = layout[0].adl
    return layout[0].adl
  } else {
    return null
  }
}

prototype.append = function append (block) {
  const _ = _properties.get(this) || {}
  if (block instanceof Block) {
    block.appendTo(_.$this)
    return this
  } else {
    makeError('ERR_WORONG_TYPE', L`_STR_ERR_UNSUPPORT_TYPE`)
    return false
  }
}

prototype.appendTo = function appendTo (container) {
  const _ = _properties.get(this) || {}
  if (container instanceof $) {
    container.append(_.$this)
  } else if (container instanceof Page) {
    container.append(this)
  } else {
    makeError('ERR_WORONG_TYPE', L`_STR_ERR_UNSUPPORT_TYPE`)
    return false
  }
  return this
}

prototype.block = function block (id) {
  const _ = _properties.get(this) || {}
  switch (typeof id) {
    case 'number':
      return Block(_.$this.find('.block:nth(' + id + ')'))
    case 'string':
      return Block(_.$this.find('#' + 'block_' + this.index + '_' + id))
    case 'undefined':
      var blocks = new Collection(Block)
      _.$this.find('.block').each(function () {
        blocks.push(Block(this))
      })
      return blocks
  }
}

prototype.toJSON = function toJSON (stringify) {
  var obj = {}
  obj.id = this.id()
  obj.name = this.name()
  obj.type = this.type()
  obj.block = this.block().toJSON(false)
  return stringify === false ? obj : JSON.stringify(obj)
}

export default Layer
