import { useEffect, useRef, useState } from 'preact/hooks'
import { Button } from '../atoms/button.js'
import { Popup } from '../atoms/popup.js'
import { Scroller } from '../atoms/scroller.js'
import { Asset } from '../molecules/asset.js'
import h from '../shared/h.js'
import { NAVIGATION_CLOSE } from '../shared/icons.js'
import t from '../shared/t.js'

// -----------------------------------------------------------------------------
// Main component
// -----------------------------------------------------------------------------

export function ImageGallery ({ _model, _color, children, ...props }) {
  const [state, setState] = useState({
    index: null,
    showList: false,
    title: _model.title,
    color: _color
  })

  return h('div', { ...props, className: undefined },
    h(GalleryOverview, { state, setState, children }),
    h(GalleryList, { state, setState, children }),
    h(GalleryDetails, { state, setState, children })
  )
}

// -----------------------------------------------------------------------------
// Helpers
// -----------------------------------------------------------------------------

function GalleryPopup ({ show, title, children, onHide, popupRef }) {
  return h(Popup, {
    ref: popupRef,
    _layout: 'full',
    'aria-label': title,
    _show: show,
    onKeyDown (event) {
      if (event.key === 'Escape') {
        event.preventDefault()
        onHide()
      }
    },
    children: h('div', { className: 'flex flex-col gap-5 h-full' },
      h('div', {
        className: 'flex justify-end',
        children: h(Button, {
          onClick: onHide,
          _textless: true,
          _model: {
            name: t('Close'), icon: NAVIGATION_CLOSE
          }
        })
      }),
      h('div', { className: 'grow' }, children)
    )
  })
}

function ThumbnailContainer ({ onClick, className, children }) {
  return h('div', {
    className: `cursor-pointer clickable transition rounded-2xl overflow-hidden relative animate-fade ${className ?? ''}`,
    _style: id => `${id}:hover { transform: scale(1.02); }`,
    role: 'button',
    tabindex: 0,
    onClick,
    onKeyDown (event) {
      if (event.key === 'Enter') {
        event.preventDefault()
        onClick()
      }
    },
    children
  })
}

// -----------------------------------------------------------------------------
// Views
// -----------------------------------------------------------------------------

function GalleryOverview ({ state, setState, children }) {
  const maxSlides = 5
  const lastSlide = maxSlides - 1
  const tiles = { sm: 1, md: 2, lg: 4 }

  // Discard all children that have no image source.
  const validChildren = children?.filter(child => child?.props?._model?.image?.src)

  return validChildren.length > 0 && h('div', { role: 'list', className: 'grid gap-5 grid-cols-4 grid-rows-2' },
    ...validChildren.slice(0, maxSlides).map((child, index) => {
      const hasMore = index === lastSlide && validChildren.length > maxSlides
      const span = index === 0 ? tiles.md : tiles.sm
      const smallSpan = index === 0 ? tiles.lg : tiles.sm

      const onClick = hasMore
        ? () => setState({ ...state, showList: true, index: null })
        : () => setState({ ...state, index })

      return h('div', {
        'data-index': index,
        role: 'listitem',
        className: `lg:row-span-${span} lg:col-span-${span} md:row-span-${span} md:col-span-${span} sm:col-span-${smallSpan} cursor-pointer aspect-square`,
        children: h(ThumbnailContainer, { onClick, className: 'aspect-square' },
          h(Asset, { ...child.props, _tall: true }),
          hasMore && h('div', {
            className: 'absolute top-0 start-0 end-0 bottom-0 flex items-center justify-center pal-transparent text-txa',
            children: h('div', { className: 'font-custom text-3xl' }, `+${validChildren.length - maxSlides}`)
          })
        )
      })
    })
  )
}

function GalleryList ({ state, setState, children }) {
  const ref = useRef(null)

  // Bring back the focus when detail view closes.
  useEffect(() => {
    state.index === null && ref.current?.base?.focus?.()
  }, [state.index])

  return h(GalleryPopup, {
    popupRef: ref,
    show: state.showList,
    title: state.title,
    onHide: () => setState({ ...state, showList: false }),
    children: h('div', {
      className: 'lg:columns-4 md:columns-3 sm:columns-2 gap-x-5 space-y-5',
      children: children.map((child, index) => [
        h(ThumbnailContainer, {
          role: 'listitem',
          onClick: () => setState({ ...state, index }),
          children: h(Asset, { ...child.props })
        }),
        h('div', { className: 'hidden' }) // Hack for last item hover flicker.
      ])
    })
  })
}

function GalleryDetails ({ state, setState, children }) {
  return h(GalleryPopup, {
    show: state.index !== null,
    title: state.title,
    onHide: () => setState({ ...state, index: null }),
    children: h('div', { className: 'h-full' },
      h(Scroller, { _tall: true, _count: [1, 1, 1], _index: state.index }, children.map((child, index) =>
        h('figure', { className: 'flex flex-col gap-5 outline-none', tabindex: 0 },
          h('picture', { className: 'grow relative h-full' },
            h('span', { className: 'absolute start-0 end-0 top-0 bottom-0' },
              h(Asset, { _model: child.props._model, _tall: true, _fit: 'contain' })
            )
          ),
          h('figcaption', { className: 'shrink flex gap-x-5' },
            h('span', { className: 'font-bold whitespace-nowrap' }, `${index + 1} / ${children.length}`),
            h('span', { className: '' }, child.props._model.image?.caption)
          )
        )
      ))
    )
  })
}
