<script>
import JsBarcode from 'jsbarcode'
import placeholder from '../../../assets/imgs/thumb-placeholder.png'
import CalculatorParser from '../../../assets/js/calculator-parser'
import {
  formatDate, formatDateString, formatDateTime, toLocaleStringDecimal,
  toLocaleStringCurrency, toLocaleStringTel, formatDateTimeString
} from '../../../filters'

export default {
  props: {
    item: {
      type: Object,
      default: () => ({})
    },
    element: {
      type: Object,
      default: () => ({})
    }
  },
  data () {
    return {
      filters: [
        'digit', 'decimal', 'numberDisplayType', 'dateFormat',
        'dateDisplayType', 'timeDisplayType', 'telDisplayType'
      ],
      // filters: [
      //   { name: 'digit', render: '' }, // หลักตัวเลข เอาไว้ทำอิหยัง
      //   { name: 'taxDisplayType', render: '' } // ไม่มี
      // ],
      associates: {
        purchases: 'order'
      }
    }
  },
  methods: {
    renderFilter (value, fx = {}) {
      let newValue = value
      this.filters.forEach((name) => {
        const filter = fx[name]
        if (filter) {
          if (name === 'decimal') {
            newValue = toLocaleStringDecimal(newValue, filter.value)
          } else if (name === 'numberDisplayType') {
            if (filter.value === 'word') {
              newValue = toLocaleStringCurrency(newValue)
            }
          } else if (name === 'dateFormat') {
            if (filter.value === '%d/%m/%Y') {
              newValue = formatDate(newValue)
            } else {
              newValue = formatDateTime(newValue)
            }
          } else if (name === 'dateDisplayType') {
            if (filter.value === 'word') {
              newValue = formatDateString(value)
            }
          } else if (name === 'timeDisplayType') {
            if (filter.value === 'word') {
              newValue = formatDateTimeString(value)
            }
          } else if (name === 'telDisplayType') {
            if (filter.value === 'with_space') {
              newValue = toLocaleStringTel(newValue)
            }
          }
        }
      })
      return newValue
    },
    renderFx (value, el, data) {
      let newValue = value
      const points = []
      const associates = {}
      const fxItems = this.$_.map(el.fx, (val) => (val))
      fxItems.forEach((fx) => {
        if (['plus', 'minus', 'times', 'multiply', 'divide', 'divided_by'].includes(fx.name)) {
          let type = 'number'
          if (this.$_.isNaN(Number(fx.value))) {
            type = 'associate'
            associates[fx.value] = this.$_.result(data, fx.value)
          }
          points.push({ type: 'operator', value: fx.name })
          points.push({ type, value: fx.value })
        }
      })
      if (points.length) {
        if (this.$_.isFinite(Number(value))) {
          points.unshift({
            type: 'number',
            value: Number(value)
          })
        }
        const calculator = new CalculatorParser(points)
        newValue = calculator.toValue(associates)
      }
      if (this.$_.isObject(el.fx)) {
        newValue = this.renderFilter(newValue, el.fx)
      }
      return newValue
    },
    renderList (h, el, data) {
      return el.children.map((child) => this.renderElement(h, child, data))
    },
    renderBarcode (value) {
      const canvas = document.createElement('canvas')
      let format = 'CODE128'
      if (value) {
        if (value.length === 8) {
          format = 'EAN8'
        } else if (value.length === 13) {
          format = 'EAN13'
        }
      }
      JsBarcode(canvas, value, {
        displayValue: false,
        background: 'transparent',
        format,
        valid (valid) {
          return valid
        }
      })
      return canvas.toDataURL('image/png')
    },
    renderElement (h, el, data = this.item) {
      let associate = ''
      if (el.data && this.$_.isString(el.data)) {
        const splitValueString = (el.data.split('.') || []).map(this.$_.camelCase)
        associate = splitValueString.join('.')
      }
      if (el.properties.src && this.$_.isString(el.properties.src)) {
        const splitValueString = (el.properties.src.split('.') || []).map(this.$_.camelCase)
        associate = splitValueString.join('.')
      }

      if (!el.tag) return this._v(el.children || '')
      const model = this.associates[associate]
      if (model) {
        const values = this.$_.result(this.item[model], associate)
        const startIndex = el.cursor || 0
        const perPage = el.perPage || 1
        const endIndex = startIndex + perPage
        const nodes = this.$_.slice(values, startIndex, endIndex)
        const parents = nodes.map((value) => {
          let children = el.children
          if (this.$_.isArray(el.children) && el.children.length && el.children[0].tag) {
            const newModel = this.$_.singularize(associate)
            children = this.renderList(h, el, this.$_.defaults({
              ...value,
              [newModel]: value
            }, this.item))
          }
          return h(el.tag, { style: el.properties.style }, children)
        })
        return parents
      }

      let children
      let src
      const value = this.$_.result(data, associate)
      if (el.tag === 'img') {
        if (el.type === 'barcode') {
          src = this.renderBarcode(value)
        } else if (this.$_.isURL(el.properties.src)) {
          src = el.properties.src
        } else {
          src = placeholder || value || placeholder
        }
      } else if (this.$_.isArray(el.children) && el.children.length && el.children[0].tag) {
        children = this.renderList(h, el, data)
      } else if (this.$_.hasValue(value)) {
        children = this.renderFx(value, el, data)
      } else if (this.$_.isNumber(el.data)) {
        children = this.renderFx(el.data, el, data)
      } else {
        children = this.renderFx(el.children, el, data)
      }
      return h(el.tag, { style: el.properties.style, attrs: { src } }, children)
    }
  },
  render (h) {
    return this.renderElement(h, this.$_.cloneDeep(this.element))
  }
}
</script>
