// @flow
import React, { type ComponentType, forwardRef } from 'react';
import styled, { css } from 'styled-components';
import { Box } from '../../../primitives/box';
import { Span } from '../../typography/span';
import type {
  TextButtonWithIconProps,
  IconType,
} from './text-button-with-icon.proptypes';
import { SmallArrowRight } from '../../icon/small-arrow-right';
import { Add } from '../../icon/add';
import {
  FOCUS_VISIBLE_SELECTOR,
  getBaseFocusState,
  focusedBoxShadow,
  focusedBorderShadow,
  focusedBorderColor,
  focusedBorderRadius,
} from '../../../mixins/focus';
import { getForegroundColor } from '../../../mixins/branding';
import { UnstyledButton } from '../../behaviors/unstyled-button';

const sharedStyles = css`
  display: inline-block;
  text-decoration: none;
  cursor: pointer;
  color: inherit;

  &:hover {
    text-decoration: underline;
  }
`;

const StyledSpan = styled(Span)`
  svg {
    vertical-align: middle;
    > g {
      fill: ${getForegroundColor};
    }
  }
`;

const ActualLink = styled.a`
  && {
    ${sharedStyles}
    ${getBaseFocusState({ hoverTransition: false, activeTransition: false })}
  }
  ${FOCUS_VISIBLE_SELECTOR} {
    & > div {
      box-shadow: ${focusedBorderShadow({ inset: false })} ${focusedBorderColor},
        ${focusedBoxShadow};
      border-radius: ${focusedBorderRadius};
    }
  }
`;

const ActualButton = styled(UnstyledButton)`
  ${sharedStyles}
`;

const getIcon = (icon: IconType) => {
  switch (icon) {
    case 'add':
      return <Add />;
    case 'small-arrow-right':
      return <SmallArrowRight />;
    default:
      return null;
  }
};

const LeftBox = styled(Box)`
  margin-right: 5px;
`;
const RightBox = styled(Box)`
  margin-left: 5px;
`;

const Display = ({ position, icon, children }: TextButtonWithIconProps) => (
  <Box stacked="row" align="center">
    {position === 'left' && (
      <LeftBox stacked="row" align="center">
        {getIcon(icon)}
      </LeftBox>
    )}
    <Box>{children}</Box>
    {position === 'right' && (
      <RightBox stacked="row" align="center">
        {getIcon(icon)}
      </RightBox>
    )}
  </Box>
);

/**
 * Important: Due to our dependence on Icomoon, we cannot have an element
 * whose class name contains `icon-` in the middle.
 * We need the `Icon` part to be at the end instead of at the start or middle
 * because React auto-generates class names based on the component's displayName.
 */
export const TextButtonWithIcon: ComponentType<TextButtonWithIconProps> = forwardRef(
  (
    {
      onClick,
      href,
      target,
      spacing,
      position,
      icon,
      children,
      colorName = 'brand-primary-fg',
      className,
      'data-cy': dataCy,
      'data-qa': dataQa,
      ...props
    }: TextButtonWithIconProps,
    ref,
  ) => (
    <StyledSpan
      bold
      colorName={colorName}
      spacing={spacing}
      ref={ref}
      {...props}
    >
      {onClick == null || href != null ? (
        <ActualLink
          href={href}
          target={target}
          onClick={onClick}
          data-cy={dataCy}
          data-qa={dataQa}
          className={className}
        >
          <Display position={position} icon={icon}>
            {children}
          </Display>
        </ActualLink>
      ) : (
        <ActualButton
          onClick={onClick}
          data-cy={dataCy}
          data-qa={dataQa}
          className={className}
        >
          <Display position={position} icon={icon}>
            {children}
          </Display>
        </ActualButton>
      )}
    </StyledSpan>
  ),
);

TextButtonWithIcon.displayName = 'TextButtonWithIcon';
