import React from 'react'
import PropTypes from 'prop-types'
import { Typography, useThemeTokens, applyShadowToken } from '@telus-uds/components-base'
import styled, { css } from 'styled-components'
import { useTableContext } from './Table'

const HEADER_TYPE = {
  HEADING: 'heading',
  SUBHEADING: 'subHeading',
  ROWHEADING: 'rowHeading'
}

const stickyStyles = ({ cellStickyShadow, stickyBackgroundColor, type }) => css`
  position: sticky;
  left: 0; // needed for sticky to work
  z-index: 2;
  clip-path: inset(0 -8px 0 0); // use clip path to cut off the shadow rendered below
  // Override default cell background with stickyBackgroundColor with an exception to subheading and heading
  ${type !== HEADER_TYPE.SUBHEADING && type !== HEADER_TYPE.HEADING
    ? `background-color: ${stickyBackgroundColor};`
    : undefined}
  &::before {
    // use a pseudo element for the sticky shadow, since we already use shadows for inner cells border
    content: '';
    box-shadow: ${cellStickyShadow};
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    pointer-events: none;
  }
`
const sharedStyles = css`
  ${({
    isSticky,
    align,
    cellPaddingTop,
    cellPaddingRight,
    cellPaddingBottom,
    cellPaddingLeft,
    cellBorderWidth,
    cellBorderColor,
    cellBorderTopWidth,
    cellMinWidth,
    cellBackground,
    cellStickyShadow,
    stickyBackgroundColor,
    cellBottomLeftBorderRadius,
    cellBottomRightBorderRadius,
    cellTopLeftBorderRadius,
    cellTopRightBorderRadius,
    type
  }) => css`
    text-align: ${align};
    min-width: ${cellMinWidth}px;
    padding: ${cellPaddingTop}px ${cellPaddingRight}px ${cellPaddingBottom}px ${cellPaddingLeft}px;
    background-color: ${cellBackground};
    ${isSticky && stickyStyles({ type, cellStickyShadow, stickyBackgroundColor })};
    border-style: ${cellBorderWidth || cellBorderTopWidth ? 'solid' : 'none'};
    border-color: ${cellBorderColor};
    border-width: ${cellBorderWidth}px;
    border-top-width: ${cellBorderTopWidth || cellBorderWidth}px;
    border-bottom-left-radius: ${cellBottomLeftBorderRadius}px;
    border-bottom-right-radius: ${cellBottomRightBorderRadius}px;
    border-top-left-radius: ${cellTopLeftBorderRadius}px;
    border-top-right-radius: ${cellTopRightBorderRadius}px;
  `}
`
const createStyledCell = (htmlElement) => styled[htmlElement]`
  ${sharedStyles};
  box-shadow: ${({ cellBoxShadowColor, type }) => {
    return type === HEADER_TYPE.HEADING
      ? `inset 0 1px 0 ${cellBoxShadowColor}, inset 0 -1px 0 ${cellBoxShadowColor}`
      : `inset 0 1px 0 ${cellBoxShadowColor}`
  }};
  ${({ display }) =>
    display &&
    `*:not(:empty) {
    display: ${display};
  }`}
`
const StyledHeaderCell = createStyledCell('th')
const StyledDataCell = createStyledCell('td')

const Cell = React.forwardRef(
  ({ children, isFirstInRow, align = 'left', tokens: cellTokens, type = 'default' }, ref) => {
    const {
      text,
      isScrollable: isTableScrollable,
      tokens: tableTokens,
      spacing,
      variant
    } = useTableContext()
    const themeTokens = { ...tableTokens, ...cellTokens }

    const {
      cellMinWidth,
      cellBoxShadowColor,
      cellBackground,
      cellStickyShadow,
      cellPaddingTop,
      cellPaddingRight,
      cellPaddingLeft,
      cellPaddingBottom,
      cellBorderWidth,
      cellBorderColor,
      cellBorderTopWidth,
      cellTopLeftBorderRadius,
      cellTopRightBorderRadius,
      cellBottomLeftBorderRadius,
      cellBottomRightBorderRadius,
      fontName,
      fontWeight,
      fontSize,
      lineHeight,
      stickyBackgroundColor,
      fontColor,
      display
    } = useThemeTokens('Table', themeTokens, { spacing, type, text, ...variant })

    const sharedProps = {
      align,
      isSticky: isTableScrollable && isFirstInRow,
      cellBackground,
      cellMinWidth,
      cellStickyShadow: applyShadowToken(cellStickyShadow).boxShadow,
      cellPaddingTop,
      cellPaddingRight,
      cellPaddingLeft,
      cellPaddingBottom,
      cellBorderWidth,
      cellBorderColor,
      cellBorderTopWidth,
      cellTopLeftBorderRadius,
      cellTopRightBorderRadius,
      cellBottomLeftBorderRadius,
      cellBottomRightBorderRadius,
      stickyBackgroundColor,
      cellBoxShadowColor,
      display,
      ref
    }

    const typographyTokens = {
      fontName,
      fontWeight,
      fontSize,
      lineHeight,
      color: fontColor
    }

    switch (type) {
      case HEADER_TYPE.HEADING:
        return (
          <StyledHeaderCell scope="col" {...sharedProps} type={type}>
            <Typography tokens={typographyTokens}>{children}</Typography>
          </StyledHeaderCell>
        )

      case HEADER_TYPE.SUBHEADING:
        return (
          <StyledHeaderCell scope="col" {...sharedProps} type={type}>
            <Typography tokens={typographyTokens}>{children}</Typography>
          </StyledHeaderCell>
        )

      case HEADER_TYPE.ROWHEADING:
        return (
          <StyledHeaderCell scope="row" {...sharedProps} type={type}>
            <Typography tokens={typographyTokens}>{children}</Typography>
          </StyledHeaderCell>
        )

      default:
        return (
          <StyledDataCell {...sharedProps}>
            <Typography tokens={typographyTokens}>{children}</Typography>
          </StyledDataCell>
        )
    }
  }
)

Cell.displayName = 'Cell'

Cell.propTypes = {
  type: PropTypes.oneOf(['default', 'heading', 'subHeading', 'rowHeading']),
  tokens: PropTypes.object,
  children: PropTypes.node,

  /**
   * @ignore
   * Used internally for making the first column sticky
   */
  isFirstInRow: PropTypes.bool,

  /**
   * Defines the text alignment within the cell
   */
  align: PropTypes.oneOf(['left', 'center', 'right'])
}

export default Cell
