import React from 'react'
import PropTypes from 'prop-types'
import {
  ChevronLink,
  selectSystemProps,
  useThemeTokens,
  Typography,
  withLinkRouter,
  Spacer,
  useViewport,
  getTokensPropType
} from '@telus-uds/components-base'
import styled, { css, keyframes } from 'styled-components'
import { htmlAttrs } from '../utils'

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

const transform = (property) => (from, to) =>
  keyframes`
  from {
    ${property}: ${from};
  }
  to {
    ${property}: ${to};
  }
`

const slideDown =
  (property) =>
  (from, to, end = to) =>
    keyframes`
  0% {
    ${property}: ${from};
  }
  99% {
    ${property}: ${to};
  }
  100% {
    ${property}: ${end};
  }
`

const animation = (props) => css`
  ${slideDown('height')(
    `${props.$animationHeightBefore}px`,
    `${props.$animationHeightAfter}px`,
    'auto'
  )} 1s ease-in-out 2s forwards,
    ${transform('padding-bottom')(
    `${props.$animationPaddingBottomBefore}px`,
    `${props.$animationPaddingBottomAfter}px`
  )} 1s ease-in-out 2s forwards,
    ${transform('padding-top')(
    `${props.$animationPaddingTopBefore}px`,
    `${props.$animationPaddingTopAfter}px`
  )} 1s ease-in-out 2s forwards,
    ${transform('background')(
    props.$animationBackgroundColorBefore,
    props.$animationBackgroundColorAfter
  )} 1s ease-in-out 3.2s forwards;
  & * {
    animation: ${transform('color')(props.$animationColorBefore, props.$animationColorAfter)} 1s
      ease-in-out 3s forwards;
  }
  & > a div {
    animation: ${transform('color')(props.$animationDivColorBefore, props.$animationDivColorAfter)}
      1s ease-in-out 3s forwards;
  }
  & > a svg {
    animation: ${transform('fill')(props.$animationFillColorBefore, props.$animationFillColorAfter)}
      1s ease-in-out 3s forwards;
  }
  & > a div {
    animation: ${transform('color')(
        props.$animationFillColorBefore,
        props.$animationFillColorAfter
      )}
      1s ease-in-out 3s forwards;
  }
`

const ToastContainer = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  padding-left: ${({ $padding }) => $padding}px;
  padding-right: ${({ $padding }) => $padding}px;
  background: ${({ $containerBackgroundColor }) => $containerBackgroundColor};
  gap: ${({ $containerGap }) => $containerGap};
  height: 0;
  overflow: hidden;
  animation: ${animation};
`

export const Toast = React.forwardRef(
  ({ toast, copy, headline, link, tokens, variant = {}, ...rest }, ref) => {
    // viewport hook added to work adjust the padding to different sizes
    const viewport = useViewport()

    const {
      containerBackgroundColor,
      containerGap,
      animationHeightBefore,
      animationHeightAfter,
      animationPaddingBottomBefore,
      animationPaddingBottomAfter,
      animationPaddingTopBefore,
      animationPaddingTopAfter,
      animationBackgroundColorBefore,
      animationBackgroundColorAfter,
      animationColorBefore,
      animationColorAfter,
      chevronlinkFontWeight,
      ...extraTokens
    } = useThemeTokens('Toast', tokens, variant, { viewport })

    // inherit ChevronLink tokens for animation colors
    const { color: chevronDefaultColor } = useThemeTokens('ChevronLink', {}, {})
    const { color: chevronInverseColor } = useThemeTokens('ChevronLink', {}, { style: 'inverse' })

    if (!toast) {
      return null
    }

    return (
      <ToastContainer
        $containerBackgroundColor={containerBackgroundColor}
        $containerGap={containerGap}
        $animationHeightBefore={animationHeightBefore}
        $animationHeightAfter={animationHeightAfter}
        $animationPaddingBottomBefore={animationPaddingBottomBefore}
        $animationPaddingBottomAfter={animationPaddingBottomAfter}
        $animationPaddingTopBefore={animationPaddingTopBefore}
        $animationPaddingTopAfter={animationPaddingTopAfter}
        $animationBackgroundColorBefore={animationBackgroundColorBefore}
        $animationBackgroundColorAfter={animationBackgroundColorAfter}
        $animationColorBefore={animationColorBefore}
        $animationColorAfter={animationColorAfter}
        $animationFillColorBefore={chevronInverseColor}
        $animationFillColorAfter={chevronDefaultColor}
        $padding={extraTokens.padding}
        ref={ref}
        {...selectProps(rest)}
      >
        {headline && <Typography variant={{ bold: true, inverse: true }}>{headline}</Typography>}
        <Spacer space={2} direction="row" />
        <Typography variant={{ inverse: true }}>{copy}</Typography>
        <Spacer space={2} direction="row" />
        {link && (
          <ChevronLink
            variant={{
              style: 'inverse'
            }}
            tokens={{ blockFontWeight: chevronlinkFontWeight }}
            href={link.href}
            LinkRouter={link.LinkRouter}
            linkRouterProps={link.linkRouterProps}
          >
            {link.text}
          </ChevronLink>
        )}
      </ToastContainer>
    )
  }
)

Toast.displayName = 'Toast'

Toast.propTypes = {
  ...selectedSystemPropTypes,
  tokens: getTokensPropType('Toast'),
  /**
   * If true, the toast will be displayed
   */
  toast: PropTypes.bool,
  /**
   * The copy to display in the toast
   */
  copy: PropTypes.string.isRequired,
  /**
   * The headline to display in the toast (before copy)
   */
  headline: PropTypes.string,
  /**
   * The link to display in the toast (after copy)
   */
  link: PropTypes.shape({
    href: PropTypes.string.isRequired,
    text: PropTypes.string.isRequired,
    LinkRouter: withLinkRouter.propTypes?.LinkRouter,
    linkRouterProps: withLinkRouter.propTypes?.linkRouterProps
  })
}
