// A lightweight Preact wrapper with a mithril-style hyperscript helper.
import { h as ph } from 'preact'
import getId from './get-id.js'
import { tw } from './twind.js'

const INNER_MODEL_PROPS = new Set([
  'name',
  'value',
  'icon',
  'type',
  'src',
  'alt',
  'caption',
  'autoplay'
])

function h (...args) {
  let [tag, props] = args

  // Ensure props are present.
  if (
    !props ||
    typeof props !== 'object' ||
    Object.hasOwn(props, '__k') || // Preact element
    Array.isArray(props)
  ) {
    props = {}
    args.splice(1, 0, props)
  }

  let customStyle
  if (typeof tag === 'string') {
    // When rendering HTML tag.
    handleColor(props)
    customStyle = handleCustomStyle(props)
    removePrivateProps(props)
    tw(props.className)
  } else {
    // When rendering Preact component.
    ensureModel(props)
  }

  return customStyle
    ? [customStyle, ph.apply(this, args)]
    : ph.apply(this, args)
}

// Remove private props (starting with underscore).
function removePrivateProps (props, ignoreList) {
  for (const key in props) {
    if (key.startsWith('_') && !ignoreList?.includes(key)) {
      delete props[key]
    }
  }
}

function handleCustomStyle (props) {
  if (props._style) {
    props.id ||= getId()
    return h('style', props._style(`#${props.id}`))
  }

  return null
}

function handleColor (props) {
  const { _color } = props
  if (_color) {
    props.className = `pal-${_color} ${props.className ?? ''}`
  }
}

function ensureModel (props) {
  const _model = props._model || {}
  if (Object.keys(_model).some(key => INNER_MODEL_PROPS.has(key))) {
    return
  }

  _model.image ||= {}
  _model.video ||= {}
  _model.links ||= []
  _model.tags ||= []
  _model.date = _model.date ? new Date(_model.date) : null
  _model.asset = _model.video.src ? _model.video : _model.image
  props._model = _model
}

export default h
