import Vue from 'vue'
import { AssetType } from '@/constant'
import { WidgetType } from './constant'
import widgetCanvas from './config-json/canvas'
import widgetText from './config-json/text'
import widgetMarquee from './config-json/marquee'
import widgetMedia from './config-json/media'
import widgetImage from './config-json/image'
import widgetVideo from './config-json/video'
import widgetTime from './config-json/time'
import widgetWeather from './config-json/weather'
import widgetWeb from './config-json/web'
import widgetLive from './config-json/live'

export const widgets = Object.freeze([
  __STAGING__ ? widgetMedia : null,
  widgetText,
  widgetMarquee,
  widgetImage,
  widgetVideo,
  widgetTime,
  __STAGING__ ? widgetWeather : null,
  widgetWeb,
  widgetLive
].filter(val => val))

let scale = null
export function create (node) {
  const canvasDefaults = widgetCanvas.defaults()
  const canvas = {
    ...canvasDefaults,
    ...transform(compatibleProcessing(node), widgetCanvas.transform, { color: transformColorToWeb })
  }
  scale = {
    width: Math.max(1, canvas.width / canvasDefaults.width),
    height: Math.max(1, canvas.height / canvasDefaults.height)
  }
  canvas.widgets = canvas.widgets.map(widget => normalize(compatibleProcessing(widget)))
  return canvas
}

function compatibleProcessing (widget) {
  switch (widget.type) {
    case WidgetType.IMAGE:
      widget.sources?.forEach(source => {
        source.type = AssetType.IMAGE
        if (!source.duration) {
          Vue.set(source, 'duration', widget.interval)
        }
      })
      break
    case WidgetType.VIDEO:
      widget.sources?.forEach(source => {
        source.type = AssetType.VIDEO
      })
      break
    default:
      if (!widget.type) {
        widget.bgm?.forEach(source => {
          source.type = AssetType.AUDIO
        })
        widget.backgroundImage?.forEach(source => {
          source.type = AssetType.IMAGE
        })
      }
      break
  }
  return widget
}

export function toJSON (node) {
  const transformOptions = { color: transformColorToAndroid }
  const canvas = transform({ ...node }, widgetCanvas.transform, transformOptions)
  canvas.widgets = canvas.widgets.map(({ id, ...widget }) => transform(widget, getWidget(widget.type).transform, transformOptions))
  return canvas
}

export function copy ({ id, ...node }) {
  const widgetOptions = getWidget(node.type)
  const copyNode = widgetOptions.copy?.(node) || node
  copyNode.id = createID(copyNode.type)
  return copyNode
}

function getWidget (type) {
  return type && widgets.find(widget => widget.type === type) || {}
}

export function getIcon (type) {
  return getWidget(type).icon
}

export function getOptions (type) {
  return (type && getWidget(type) || widgetCanvas).options
}

function createID (type) {
  return `${type}${Math.random(16).toString().slice(2)}`
}

export function normalize (data) {
  const { type } = data
  const widgetOptions = getWidget(type)
  return {
    id: createID(type),
    ...widgetOptions.defaults(scale),
    ...transform(data, widgetOptions.transform, { color: transformColorToWeb })
  }
}

function transform10To16 (num) {
  return parseInt(num).toString(16).padStart(2, '0')
}

// 转换为#AARRGGBB或#RRGGBB
function transformColorToAndroid (color) {
  if (/^rgba\(/.test(color)) {
    const rgba = /^rgba\(([^,]+),([^,]+),([^,]+),([^)]+)\)$/i.exec(color)
    if (rgba) {
      color = `#${transform10To16(Math.round(Math.round((Number(rgba[4]) * 100)) / 100 * 255))}${transform10To16(rgba[1])}${transform10To16(rgba[2])}${transform10To16(rgba[3])}`
    }
  } else if (/^rgb\(/.test(color)) {
    const rgb = /^rgb\(([^,]+),([^,]+),([^)]+)\)$/i.exec(color)
    if (rgb) {
      color = `#${transform10To16(rgb[1])}${transform10To16(rgb[2])}${transform10To16(rgb[3])}`
    }
  }
  return color.toUpperCase()
}

function transfrom16To10 (num) {
  return parseInt(num, 16)
}

function getPercent (source) {
  return source === 0 ? 0 : source === 255 ? 1 : Math.round(source / 255 * 100) / 100
}

function transformColorToWeb (color) {
  if (/^#[0-9a-fA-F]{8}$/.test(color)) {
    const argb = /^#(.{2})(.{2})(.{2})(.{2})$/i.exec(color)
    if (argb) {
      return `rgba(${transfrom16To10(argb[2])}, ${transfrom16To10(argb[3])}, ${transfrom16To10(argb[4])}, ${getPercent(transfrom16To10(argb[1]))})`
    }
  }
  return color
}

function transform (data, transformOptions = {}, strat = {}) {
  Object.keys(transformOptions).forEach(key => {
    if (strat[key]) {
      transformOptions[key].forEach(attrKey => {
        if (data[attrKey]) {
          data[attrKey] = strat[key](data[attrKey])
        }
      })
    }
  })
  return data
}

export function fix (node) {
  const { bgm, widgets } = node

  if (bgm.length === 0) {
    const volumeWidgets = widgets.filter(({ type, sources }) => {
      switch (type) {
        case WidgetType.MEDIA:
          return sources.some(({ type }) => type === AssetType.VIDEO)
        case WidgetType.VIDEO:
        case WidgetType.LIVE:
          return true
        default:
          return false
      }
    })
    // 所有带视频组件均有效且无输出时
    // 仅有一个视频时，默认输出
    // 多个时，询问
    if (volumeWidgets.length && !volumeWidgets.some(widget => {
      if (widget.type === WidgetType.LIVE) {
        if (!widget.url) {
          return true
        }
      }
      if (!widget.sources.length) {
        return true
      }
      return widget.mute === 0
    })) {
      if (volumeWidgets.length === 1) {
        volumeWidgets[0].mute = 0
      } else {
        return '视频均未设置音频输出'
      }
    }
  }
  return null
}

export function getDuration (node) {
  return node.widgets.reduce((duration, widget) => {
    switch (widget.type) {
      case WidgetType.MEDIA:
      case WidgetType.IMAGE:
      case WidgetType.VIDEO:
        return Math.max(widget.sources.reduce((total, { duration }) => duration ? total + Number(duration) : total, 0), duration)
      case WidgetType.LIVE:
        return Math.max(60, duration)
      default:
        return duration
    }
  }, 0)
}

export function validate (node) {
  const { widgets } = node
  if (!widgets.length) {
    return '未配置组件，请先进行配置'
  }
  for (let i = 0; i < widgets.length; i++) {
    const widget = widgets[i]
    switch (widget.type) {
      case WidgetType.MEDIA:
        if (widget.sources.length === 0) {
          return '有媒资组件未配置数据，请先进行配置'
        }
        break
      case WidgetType.IMAGE:
        if (widget.sources.length === 0) {
          return '有图片组件未配置数据，请先进行配置'
        }
        break
      case WidgetType.VIDEO:
        if (widget.sources.length === 0) {
          return '有视频组件未配置数据，请先进行配置'
        }
        break
      case WidgetType.WEB:
        if (!widget.href) {
          return '有网页组件未配置链接地址，请先进行配置'
        }
        break
      case WidgetType.LIVE:
        if (!widget.url) {
          return '有直播组件未配置播放地址，请先进行配置'
        }
        break
      default:
        break
    }
  }
  return null
}

export function switchToNext (toggleType, arr, curr) {
  const length = arr.length
  if (length === 0) {
    return -1
  }

  if (length === 1 || curr === -1) {
    return 0
  }

  let index = curr
  switch (toggleType) {
    case 'cycle':
      index = (index + 1) % length
      break
    case 'random':
      index = Math.random() * length | 0
      if (arr[index]?.keyName === arr[curr].keyName) {
        if (index === 0) {
          index += 1
        } else {
          index -= 1
        }
      }
      break
    default:
      break
  }

  return index
}
