import React from 'react'
import PropTypes from 'prop-types'
import { viewports } from '@telus-uds/system-constants'
import {
  selectSystemProps,
  StackView,
  useThemeTokens,
  useViewport,
  getTokensPropType
} from '@telus-uds/components-base'
import styled, { css } from 'styled-components'
import { VideoPropType } from './videoPropType'
import VideoPickerThumbnail from './VideoPickerThumbnail'
import VideoPickerPlayer from './VideoPickerPlayer'
import VideoSlider from './VideoSlider'
import { htmlAttrs } from '../utils'

const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])

const framedContainerStyles = ({
  framedContainerBackgroundColor,
  framedContainerBorderWidth,
  framedContainerBorderColor,
  framedContainerBorderRadius,
  framedMaxHeight
}) => css`
  background-color: ${framedContainerBackgroundColor};
  border: ${framedContainerBorderWidth}px solid ${framedContainerBorderColor};
  border-radius: ${framedContainerBorderRadius}px;

  & > div {
    max-height: ${framedMaxHeight}px;
  }
`

const VideoPickerContainer = styled.div`
  ${({ isFramed, ...tokens }) => isFramed && framedContainerStyles(tokens)}
`

const framedPlayerContainerStyles = ({ framedMaxHeight, framedContainerPadding }) => css`
  width: 66.67%;
  padding: ${framedContainerPadding}px;
  max-height: ${framedMaxHeight}px;
  flex-shrink: 0;
  box-sizing: border-box;
`

const VideoPlayerContainer = styled.div`
  ${({ isFramed, ...tokens }) => isFramed && framedPlayerContainerStyles(tokens)}
  overflow: auto;
`

const framedVideoListContainerStyle = css`
  max-height: ${({ framedMaxHeight }) => framedMaxHeight}px;
  overflow: auto;
  flex-direction: column;
`

const VideoListContainer = styled.div`
  display: flex;
  justify-content: flex-start;
  position: relative;
  flex-grow: 1;
  flex-direction: column;
  ${(props) => props.isFramed && framedVideoListContainerStyle}
`

const VideoPicker = React.forwardRef(
  (
    {
      videoList = [],
      selectedVideo = videoList[0]?.videoId,
      frame,
      onStartVideo = () => {},
      onSelectVideo = () => {},
      onPlay = () => {},
      onPause = () => {},
      onProgress = () => {},
      ...rest
    },
    ref
  ) => {
    const viewport = useViewport()
    const { stackViewDividerColor, ...themeTokens } = useThemeTokens('VideoPicker')
    const [currentVideoId, setCurrentVideoId] = React.useState(selectedVideo)
    const videoPlayerRef = React.useRef(null)

    const currentVideo = videoList.find((video) => video.videoId === currentVideoId)

    React.useEffect(() => {
      // Update current video if parent changes which video id it passes down
      setCurrentVideoId(selectedVideo)
    }, [selectedVideo])

    const addVideoEventHandlers = (video) => {
      if (!video) return {}
      return {
        ...video,
        onPlay: video.onPlay || onPlay,
        onPause: video.onPause || onPause,
        onProgress: video.onProgress || onProgress
      }
    }

    // `frame` variant should only work on larger screens
    const isFramed = frame && [viewports.lg, viewports.xl].includes(viewport)

    const hasSlider = !frame && [viewports.md, viewports.lg, viewports.xl].includes(viewport)

    const listElements = videoList.map((video, index) => (
      <VideoPickerThumbnail
        key={video.videoId}
        video={video}
        videoPlayerRef={videoPlayerRef}
        selectedVideoId={currentVideoId}
        onSelectVideo={(current) => {
          setCurrentVideoId(current.videoId)
          onSelectVideo(current)
        }}
        layout={!hasSlider ? 'horizontal' : 'vertical'}
        index={index}
        isFramed={isFramed}
      />
    ))

    return (
      <VideoPickerContainer ref={ref} isFramed={isFramed} {...selectProps(rest)} {...themeTokens}>
        <StackView
          divider={
            isFramed
              ? { tokens: { color: stackViewDividerColor } }
              : { variant: { decorative: true } }
          }
          space={isFramed ? 0 : 4} // everything has internal padding in `frame` variant
          direction={isFramed ? 'row' : 'column'}
        >
          <VideoPlayerContainer {...themeTokens} isFramed={isFramed}>
            <VideoPickerPlayer
              video={addVideoEventHandlers(currentVideo)}
              videoPlayerRef={videoPlayerRef}
              onStartVideo={onStartVideo}
            />
          </VideoPlayerContainer>
          {hasSlider ? (
            <VideoSlider>{listElements}</VideoSlider>
          ) : (
            <VideoListContainer
              viewport={viewport}
              data-testid="video-list-container"
              isFramed={isFramed}
            >
              {listElements}
            </VideoListContainer>
          )}
        </StackView>
      </VideoPickerContainer>
    )
  }
)

VideoPicker.displayName = 'VideoPicker'

VideoPicker.propTypes = {
  ...selectedSystemPropTypes,
  tokens: getTokensPropType('VideoPicker'),
  /**
   * Id of the currently selected video (defaults to the first video if not set).
   */
  selectedVideo: PropTypes.string,
  /**
   * An array of Video objects.
   */
  videoList: PropTypes.arrayOf(VideoPropType),
  /**
   * Use to display the picker in a container and the playlist as a sidebar (only available for breakpoints LG and larger)
   */
  frame: PropTypes.bool,
  /**
   * Callback function trigerred when the video player starts playing video.
   * @param {object} video - The video object that is playing.
   */
  onStartVideo: PropTypes.func,
  /**
   * Callback function trigerred when a video is selected from the thumbnail list.
   * @param {object} video - The video object that is selected.
   */
  onSelectVideo: PropTypes.func,

  /**
   * Callback function trigerred during progress milestones 10% 25% 50% 75% 100%.
   * @param {object} event - The event object.
   */
  onProgress: PropTypes.func,

  /**
   * Callback function trigerred when the video player starts playing video.
   * @param {object} event - The event object.
   */
  onPlay: PropTypes.func,

  /**
   * Callback function trigerred when the video gets paused.
   * @param {object} event - The event object.
   */
  onPause: PropTypes.func
}

export default VideoPicker
