import styled, { keyframes, css } from 'styled-components';

const animationDuration = '0.25s';

const StyledWrapper = styled.div<{ themeLoading: boolean }>`
  display: flex;
  align-items: center;
  margin: 0;
  padding: 0;

  ${({ themeLoading }) => {
    switch (themeLoading) {
      case true:
        return css`
          pointer-events: none;
        `;
      case false:
        return css``;
    }
  }};
`;

const StyledInputWrapper = styled.label<{
  themeSize: 'small' | 'medium';
}>`
  position: relative;
  display: inline-block;
  margin: 0;
  padding: 0;

  ${({ themeSize, theme }) => {
    switch (themeSize) {
      case 'small':
        return css`
          width: ${theme.sizes.switch.smallWidth};
          height: ${theme.sizes.switch.smallHeight};
        `;
      case 'medium':
        return css`
          width: ${theme.sizes.switch.mediumWidth};
          height: ${theme.sizes.switch.mediumHeight};
        `;
    }
  }};
`;

const StyledSlider = styled.span<{
  themeDisabled: boolean;
  themeSize: 'small' | 'medium';
}>`
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 0;

  ${({ themeSize, theme }) => {
    switch (themeSize) {
      case 'small':
        return css`
          border-radius: ${theme.radii.switch.small};
        `;
      case 'medium':
        return css`
          border-radius: ${theme.radii.switch.medium};
        `;
    }
  }};

  ${({ themeDisabled, theme }) => {
    switch (themeDisabled) {
      case true:
        return css`
          cursor: not-allowed;
          background-color: ${theme.colors.switch.disabledBackground};
        `;
      case false:
        return css`
          cursor: pointer;
          background-color: ${theme.colors.switch.background};
        `;
    }
  }};

  &:before {
    position: absolute;
    content: '';
    background-color: ${({ theme }) =>
      theme.colors.switch.handleBackgroundColor};
    transition: ${animationDuration};
    border-radius: 50%;
    right: auto;

    ${({ themeSize, theme }) => {
      switch (themeSize) {
        case 'small':
          return css`
            width: ${theme.sizes.switch.sliderSmall};
            height: ${theme.sizes.switch.sliderSmall};
            top: ${theme.space.switch.sliderSmallTop};
            left: ${theme.space.switch.sliderSmallLeft};
          `;
        case 'medium':
          return css`
            width: ${theme.sizes.switch.sliderMedium};
            height: ${theme.sizes.switch.sliderMedium};
            top: ${theme.space.switch.sliderMediumTop};
            left: ${theme.space.switch.sliderMediumLeft};
          `;
      }
    }};
  }
`;

const getIconPositionStyle = (
  {
    themeChecked,
    themeDisabled,
  }: { themeChecked: boolean; themeDisabled: boolean },
  value: string
) =>
  themeDisabled === true && themeChecked === false
    ? css`
        right: ${value};
      `
    : css`
        left: ${value};
      `;

const DISABLED_ICON_SIZE_MAP = {
  small: 'disabledIconSmall',
  medium: 'disabledIconMedium',
} as const;

const StyledIconWrapper = styled.div<{
  themeChecked?: boolean;
  themeDisabled: boolean;
  themeSize: 'small' | 'medium';
}>`
  position: absolute;
  color: ${({ theme }) => theme.colors.switch.iconColor};
  margin: 0;
  padding: 0;

  ${({ themeSize, themeChecked = false, themeDisabled, theme }) => {
    switch (themeSize) {
      case 'small':
        return css`
          top: 0;
          ${getIconPositionStyle(
            { themeChecked, themeDisabled },
            theme.space.switch.iconSmallLeft
          )}
          line-height: ${theme.fontSizes.switch.iconSmall};
          margin-left: ${theme.space.switch.iconSmallMarginLeft};
          height: ${theme.sizes.switch.smallHeight};
          font-size: ${theme.fontSizes.switch.iconSmall};
        `;
      case 'medium':
        return css`
          top: 0;
          ${getIconPositionStyle(
            { themeChecked, themeDisabled },
            theme.space.switch.iconMediumLeft
          )}
          line-height: ${theme.fontSizes.switch.iconMedium};
          margin-left: ${theme.space.switch.iconMediumMarginLeft};
          height: ${theme.sizes.switch.mediumHeight};
          font-size: ${theme.fontSizes.switch.iconMedium};
        `;
    }
  }};

  ${({ themeDisabled, themeSize, theme }) => {
    switch (themeDisabled) {
      case true:
        return css`
          cursor: not-allowed;
          font-size: ${theme.fontSizes.switch[
            DISABLED_ICON_SIZE_MAP[themeSize]
          ]};
        `;
      case false:
        return css`
          cursor: pointer;
        `;
    }
  }};
`;

const StyledLoadingIconWrapper = styled.div<{
  themeDisabled: boolean;
  themeSize: 'small' | 'medium';
}>`
  position: absolute;
  transition: ${animationDuration};
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 0;

  ${({ themeDisabled, theme }) => {
    switch (themeDisabled) {
      case true:
        return css`
          color: ${theme.colors.switch.disabledLoadingIconColor};
          cursor: not-allowed;
        `;
      case false:
        return css`
          color: ${theme.colors.switch.loadingIconColor};
          cursor: pointer;
        `;
    }
  }};

  ${({ themeSize, theme }) => {
    switch (themeSize) {
      case 'small':
        return css`
          top: ${theme.space.switch.sliderSmallTop};
          font-size: ${theme.fontSizes.switch.loadingIconSmall};
          height: ${theme.sizes.switch.sliderSmall};
          width: ${theme.sizes.switch.sliderSmall};
        `;
      case 'medium':
        return css`
          top: ${theme.space.switch.sliderMediumTop};
          font-size: ${theme.fontSizes.switch.loadingIconMedium};
          height: ${theme.sizes.switch.sliderMedium};
          width: ${theme.sizes.switch.sliderMedium};
        `;
    }
  }};
`;

const fadeIn = keyframes`
  from {
    opacity: 0;
    transform: scale(0);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
`;

const StyledInput = styled.input<{
  themeDisabled: boolean;
  themeSize: 'small' | 'medium';
}>`
  opacity: 0;
  width: 0;
  height: 0;
  margin: 0;
  padding: 0;

  ${({ themeDisabled, theme }) => {
    switch (themeDisabled) {
      case true:
        return css`
          &:checked ~ ${StyledSlider} {
            background-color: ${theme.colors.switch.checkedDisabledBackground};
          }

          &:checked ~ ${StyledLoadingIconWrapper} {
            color: ${theme.colors.switch.checkedDisabledLoadingIconColor};
          }
        `;
      case false:
        return css`
          &:checked ~ ${StyledSlider} {
            background-color: ${theme.colors.switch.checkedBackground};
          }

          &:checked ~ ${StyledLoadingIconWrapper} {
            color: ${theme.colors.switch.checkedLoadingIconColor};
          }
        `;
    }
  }};

  ${({ themeSize, theme }) => {
    switch (themeSize) {
      case 'small':
        return css`
          &:checked ~ ${StyledSlider}:before {
            left: ${theme.space.switch.sliderSmallCheckedLeft};
          }
          ~ ${StyledLoadingIconWrapper} {
            left: ${theme.space.switch.loadingIconSmallLeft};
          }
          &:checked ~ ${StyledLoadingIconWrapper} {
            left: ${theme.space.switch.sliderSmallCheckedLeft};
          }
        `;
      case 'medium':
        return css`
          &:checked ~ ${StyledSlider}:before {
            left: ${theme.space.switch.sliderMediumCheckedLeft};
          }

          ~ ${StyledLoadingIconWrapper} {
            left: ${theme.space.switch.loadingIconMediumLeft};
          }

          &:checked ~ ${StyledLoadingIconWrapper} {
            left: ${theme.space.switch.sliderMediumCheckedLeft};
          }
        `;
    }
  }};

  ~ ${StyledIconWrapper} {
    display: none;
  }

  &:checked ~ ${StyledIconWrapper}, &:disabled ~ ${StyledIconWrapper} {
    display: flex;
    align-items: center;
    animation-name: ${fadeIn};
    animation-duration: ${animationDuration};
  }
`;

export {
  StyledWrapper,
  StyledInputWrapper,
  StyledInput,
  StyledSlider,
  StyledIconWrapper,
  StyledLoadingIconWrapper,
};
