/* eslint-disable react/button-has-type */
import { useStyledTheme } from '@pfb/hooks/useTheme';
import { Theme } from '@pfb/models/theme.model';
import {
  ButtonHTMLAttributes,
  PropsWithChildren,
  useCallback,
  MouseEvent,
  forwardRef,
  ReactNode,
} from 'react';
import { keyframes } from '@emotion/core';

export interface ButtonProps {
  primary?: boolean;
  error?: boolean;
  link?: boolean;
  transparent?: boolean;
  after?: ReactNode;
}

const getColorPair = (theme: Theme, props: ButtonProps) => {
  if (props.primary) {
    return theme.colors.primary;
  }
  if (props.error) {
    return theme.colors.error;
  }
  if (props.link) {
    return {
      backgroundColor: 'transparent',
      color: theme.elements.link.color,
      borderColor: 'transparent',
    };
  }
  if (props.transparent) {
    return {
      backgroundColor: 'transparent',
      color: theme.elements.link.color,
      borderColor: 'transparent',
    };
  }
  return theme.colors.default;
};

const rippleTransition = keyframes`
 to {
    transform: scale(4);
    opacity: 0;
  }`;

const styles = (props: {
  primary: boolean;
  error: boolean;
  link: boolean;
  transparent: boolean;
}) => (theme: Theme) => {
  const colorPairByProps = getColorPair(theme, props);
  return {
    button: {
      width: '100%',
      color: colorPairByProps.color,
      borderRadius: '4px',
      fontWeight: 'bold' as const,
      padding: `${theme.spacing(1)} ${theme.spacing(4)}`,
      border: '1px solid',
      borderColor: colorPairByProps.borderColor,
      backgroundColor: colorPairByProps.backgroundColor,
      position: 'relative' as const,
      overflow: 'hidden',
      transition: 'background 400ms',
      outline: '0',
      boxShadow:
        !props.link && !props.transparent && '0 0 0.5rem rgba(0, 0, 0, 0.3)',
      cursor: 'pointer',

      gridGap: theme.spacing(1),
      display: 'grid',
      gridAutoFlow: 'column',

      'span.ripple': {
        position: 'absolute' as const,
        borderRadius: '50%',
        transform: 'scale(0)',
        animation: `${rippleTransition} 600ms linear`,
        backgroundColor: 'rgba(255, 255, 255, 0.7)',
      },
      ':disabled': {
        backgroundColor: theme.palette.neutral,
        borderColor: theme.palette.darkerNeutral,
        color: theme.palette.darkerNeutral,
        cursor: 'not-allowed',
      },
    },
  };
};

export const Button = forwardRef<
  HTMLButtonElement,
  PropsWithChildren<ButtonProps & ButtonHTMLAttributes<unknown>>
>((props, ref) => {
  const {
    children,
    primary = false,
    error = false,
    link = false,
    transparent = false,
    after,
    onClick,
    ...otherProps
  } = props;
  const styled = useStyledTheme(styles({ primary, error, link, transparent }));
  console.log(styled.button.backgroundColor, 'transparent', transparent);

  const createRipple = useCallback(
    (event: MouseEvent<HTMLButtonElement>) => {
      if (!!onClick) {
        onClick(event);
      }

      const button = event.currentTarget;

      const circle = document.createElement('span');
      const diameter = Math.max(button.clientWidth, button.clientHeight);
      const radius = diameter / 2;

      circle.style.width = `${diameter}px`;
      circle.style.height = `${diameter}px`;
      circle.style.left = `${event.clientX - button.offsetLeft - radius}px`;
      circle.style.top = `${event.clientY - button.offsetTop - radius}px`;
      circle.classList.add('ripple');

      circle.addEventListener('animationend', () => button.removeChild(circle));

      button.appendChild(circle);
    },
    [onClick],
  );

  return (
    <button
      css={styled.button}
      {...otherProps}
      ref={ref}
      onClick={createRipple}
    >
      {styled.button.backgroundColor}
      {children}
      {!!after && after}
    </button>
  );
});
