// @flow
import React from 'react';
import type { AbstractComponent } from 'react';

import styled, { css } from 'styled-components';
import type { PatchworkComponent } from '../../../types';
import type { ButtonProps } from './button.proptypes';
import { getSpacingRules } from '../../../mixins/spacing';
import { getPaletteColor } from '../../../mixins/branding';
import {
  getFontFamily,
  getFontWeight,
  getFontSize,
} from '../../../mixins/typography';
import {
  FOCUS_VISIBLE_SELECTOR,
  focusedBoxShadow,
  focusedBorderShadow,
  focusedBorderColor,
  getBaseFocusState,
} from '../../../mixins/focus';
import { getBorderRadius, getHeight } from './button.css-rules';

const getCommonStyles = css`
  && {
    display: inline-block;
    min-width: 160px;
    padding: 0 15px;
    background: ${getPaletteColor('brand-primary-base')};
    border-width: 0;
    border-radius: ${getBorderRadius};
    color: ${getPaletteColor('white')};
    height: ${getHeight};
    font-family: ${getFontFamily};
    font-weight: ${getFontWeight};
    font-size: ${getFontSize};
    ${getBaseFocusState({})}
  }
  ${FOCUS_VISIBLE_SELECTOR} {
    box-shadow: ${focusedBoxShadow},
      ${focusedBorderShadow} ${focusedBorderColor};
  }
  &:hover {
    background: ${getPaletteColor('brand-primary-dark')};
  }
  &:active {
    background: ${getPaletteColor('brand-primary-fg')};
  }
  &[disabled] {
    background: ${getPaletteColor('greyscale-light')};
  }
`;

const ActualButton: PatchworkComponent<ButtonProps> = styled.button.attrs(
  props => ({
    type: props.type || 'button',
    style: getSpacingRules(props),
    bold: 'true',
  }),
)`
  ${getCommonStyles}
  line-height: 100%;
`;

const LinkButton: PatchworkComponent<ButtonProps> = styled.a.attrs(props => ({
  style: getSpacingRules(props),
  bold: 'true',
}))`
  ${getCommonStyles}
  line-height: ${getHeight};
  text-align: center;
  text-decoration: none;
`;

export const Button: AbstractComponent<ButtonProps, *> = React.forwardRef(
  ({ href, target, onClick, type, ...props }: ButtonProps, ref) =>
    href == null ? (
      <ActualButton onClick={onClick} type={type} {...props} ref={ref} />
    ) : (
      <LinkButton href={href} target={target} {...props} ref={ref} />
    ),
);

Button.displayName = 'Button';
