// @flow
import React, { useState } from 'react';
import { startCase } from 'lodash';
import styled from 'styled-components';
import { action } from '@storybook/addon-actions';
import { TextInput } from './text-input.component';
import type { TextInputProps } from './text-input.proptypes';
import type { FormInputType } from '../internals/form-input';
import { MarginChecker } from '../../../mixins/spacing/story-support/margin-checker';
import { StackeeChecker } from '../../../mixins/stackee/story-support/stackee-checker';
import docs from './text-input.mdx';
import { Box } from '../../../primitives/box';
import { SectionHeader } from '../../typography/section-header';

export default {
  component: TextInput,
  title: 'Components/Inputs/TextInput',
  parameters: {
    docs: {
      page: docs,
    },
  },
};

const TextInputDemo = ({
  value,
  large,
  iconType,
  iconPosition,
  label,
  hideLabel,
  placeholder,
  onFocus,
  onBlur,
  disabled,
  error,
  focusOnMount,
  fontSize,
  mask,
  maskOptions,
  className = '',
  buttonText,
  inputMode,
  hideBorder = false,
  type,
  hideValueButtonLabel = 'hide',
  revealValueButtonLabel = 'show',
  floatLabel,
  spacing,
}: $Shape<TextInputProps<string>>) => {
  const [demoValue, setDemoValue] = useState(value);
  return (
    <TextInput
      label={label}
      onChange={setDemoValue}
      value={demoValue}
      iconType={iconType}
      iconPosition={iconPosition}
      placeholder={placeholder}
      onFocus={onFocus}
      onBlur={onBlur}
      large={large}
      disabled={disabled}
      error={error}
      focusOnMount={focusOnMount}
      fontSize={fontSize}
      className={className}
      mask={mask}
      maskOptions={maskOptions}
      buttonText={buttonText}
      inputMode={inputMode}
      hideBorder={hideBorder}
      type={type}
      hideValueButtonLabel={hideValueButtonLabel}
      revealValueButtonLabel={revealValueButtonLabel}
      floatLabel={floatLabel}
      hideLabel={hideLabel}
      spacing={spacing}
    />
  );
};

type TextInputVariantsProps = {
  type: FormInputType,
  hideLabel?: boolean,
  floatLabel?: boolean,
  large?: boolean,
};
const TextInputVariants = ({
  type,
  hideLabel = false,
  floatLabel = false,
  large = false,
}: TextInputVariantsProps) => {
  const variantName = startCase(type);
  return (
    <Box spacing="p2" basis={450}>
      <SectionHeader>
        <p>Type: {variantName}</p>
      </SectionHeader>
      <TextInputDemo
        key={type}
        label="Label"
        hideLabel={hideLabel}
        floatLabel={floatLabel}
        placeholder={hideLabel ? 'Placeholder' : undefined}
        type={type}
        spacing="m1"
        large={large}
      />
      <TextInputDemo
        key={`${type}-disabled`}
        label="Label"
        hideLabel={hideLabel}
        floatLabel={floatLabel}
        placeholder={hideLabel ? 'Placeholder' : undefined}
        type={type}
        spacing="m1"
        disabled
        large={large}
      />
      <TextInputDemo
        key={`${type}-error`}
        label="Label"
        hideLabel={hideLabel}
        floatLabel={floatLabel}
        placeholder={hideLabel ? 'Placeholder' : undefined}
        type={type}
        spacing="m1"
        iconType="lock"
        large={large}
      />
      <TextInputDemo
        key={`${type}-error`}
        label="Label"
        hideLabel={hideLabel}
        floatLabel={floatLabel}
        placeholder={hideLabel ? 'Placeholder' : undefined}
        type={type}
        spacing="m1"
        iconType="checkmark"
        large={large}
      />
      <TextInputDemo
        key={`${type}-error`}
        label="Label"
        hideLabel={hideLabel}
        floatLabel={floatLabel}
        placeholder={hideLabel ? 'Placeholder' : undefined}
        type={type}
        spacing="m1"
        iconType="lock"
        iconPosition="left"
        large={large}
      />
      <TextInputDemo
        key={`${type}-error`}
        label="Label"
        hideLabel={hideLabel}
        floatLabel={floatLabel}
        placeholder={hideLabel ? 'Placeholder' : undefined}
        type={type}
        spacing="m1"
        iconType="checkmark"
        iconPosition="left"
        large={large}
      />
      <TextInputDemo
        key={`${type}-error`}
        label="Label"
        hideLabel={hideLabel}
        floatLabel={floatLabel}
        placeholder={hideLabel ? 'Placeholder' : undefined}
        type={type}
        spacing="m1"
        error
        large={large}
      />
      <TextInputDemo
        key={`${type}-error`}
        label="Label"
        hideLabel={hideLabel}
        floatLabel={floatLabel}
        placeholder={hideLabel ? 'Placeholder' : undefined}
        type={type}
        spacing="m1"
        iconType="error"
        iconPosition="left"
        large={large}
      />
      <TextInputDemo
        key={`${type}-error-message`}
        label="Label"
        hideLabel={hideLabel}
        floatLabel={floatLabel}
        placeholder={hideLabel ? 'Placeholder' : undefined}
        type={type}
        spacing="m1"
        error="Oh noes!"
        large={large}
      />
    </Box>
  );
};

export const KitchenSinkSmallVisibleLabel = () => (
  <Box stacked="row" wrap>
    {['text', 'password', 'email', 'number', 'date'].map((type) => (
      <TextInputVariants type={type} />
    ))}
  </Box>
);

export const KitchenSinkSmallHiddenLabelWithPlaceholder = () => (
  <Box stacked="row" wrap>
    {['text', 'password', 'email', 'number', 'date'].map((type) => (
      <TextInputVariants type={type} hideLabel />
    ))}
  </Box>
);

export const KitchenSinkLargeVisibleLabel = () => (
  <Box stacked="row" wrap>
    {['text', 'password', 'email', 'number', 'date'].map((type) => (
      <TextInputVariants type={type} large />
    ))}
  </Box>
);

export const KitchenSinkLargeHiddenLabelWithPlaceholder = () => (
  <Box stacked="row" wrap>
    {['text', 'password', 'email', 'number', 'date'].map((type) => (
      <TextInputVariants type={type} hideLabel large />
    ))}
  </Box>
);

export const KitchenSinkLargeFloatingLabel = () => (
  <Box stacked="row" wrap>
    {['text', 'password', 'email', 'number', 'date'].map((type) => (
      <Box>
        <TextInputVariants type={type} floatLabel large />
      </Box>
    ))}
  </Box>
);

const StyledTextInputDemo = styled(TextInputDemo)`
  width: 400px;
  padding-right: 25px;
  border: 5px solid red;
`;

export const Password = () => (
  <TextInputDemo
    label="Password"
    hideLabel
    onChange={action('onChange')}
    value="hunter2"
    placeholder="Password"
    large
    type="password"
    hideValueButtonLabel="hide password"
    revealValueButtonLabel="reveal password"
  />
);

export const PasswordDisabled = () => (
  <TextInputDemo
    label="Password"
    disabled
    hideLabel
    onChange={action('onChange')}
    value="hunter2"
    placeholder="Password"
    large
    type="password"
    hideValueButtonLabel="hide password"
    revealValueButtonLabel="reveal password"
  />
);

export const PasswordSmall = () => (
  <TextInputDemo
    label="Password"
    hideLabel
    onChange={action('onChange')}
    value="hunter2"
    placeholder="Password"
    type="password"
    hideValueButtonLabel="hide password"
    revealValueButtonLabel="reveal password"
  />
);

export const Default = () => (
  <TextInputDemo label="Enter some text" onChange={action('onChange')} />
);

export const large = () => (
  <TextInputDemo label="Enter some text" large onChange={action('onChange')} />
);

export const SpecifyFontSize = () => (
  <TextInputDemo
    label="Enter some text"
    onChange={action('onChange')}
    fontSize="f5"
    large
  />
);

export const WithButtonText = () => (
  <TextInputDemo
    label="Enter some text"
    onChange={action('onChange')}
    buttonText="Show"
  />
);

export const WithButtonTextAndError = () => (
  <TextInputDemo
    label="Enter some text"
    onChange={action('onChange')}
    buttonText="Show"
    error
  />
);

export const WithValueDisabled = () => (
  <TextInputDemo
    label="Omg a label"
    disabled
    placeholder="Look a placeholder that's really long!"
    value="Wooo a value!"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
  />
);

export const WithIconLeft = () => (
  <TextInputDemo
    label="Omg a label"
    iconType="lock"
    iconPosition="left"
    placeholder="Look a placeholder that's really long!"
    value="Wooo a value!"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
  />
);

export const WithIconRight = () => (
  <TextInputDemo
    label="Omg a label"
    iconType="lock"
    iconPosition="right"
    placeholder="Look a placeholder that's really long!"
    value="Wooo a value!"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
  />
);

export const WithCheckmarkIconRightLarge = () => (
  <TextInputDemo
    label="Omg a label"
    iconType="checkmark"
    iconPosition="right"
    placeholder="Look a placeholder that's really long!"
    value="Wooo a value!"
    large
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
  />
);

export const WithIconRightDisabled = () => (
  <TextInputDemo
    label="Omg a label"
    iconType="lock"
    iconPosition="right"
    disabled
    placeholder="Look a placeholder that's really long!"
    value="Wooo a value!"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
  />
);

export const WithErrorIcon = () => (
  <TextInputDemo
    label="Omg a label"
    iconType="lock"
    iconPosition="right"
    error
    placeholder="Look a placeholder that's really long!"
    value="Wooo a value!"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
  />
);

export const WithError = () => (
  <TextInputDemo
    label="Omg a label"
    placeholder="Look a placeholder that's really long!"
    value="O no, an error"
    error
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
  />
);

export const ErrorString = () => (
  <TextInputDemo
    label="Omg a label"
    placeholder="Look a placeholder that's really long!"
    value="O no, an error"
    error="dangnamit I'm broken"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    large
  />
);

export const ErrorArray = () => (
  <TextInputDemo
    label="Omg a label"
    placeholder="Look a placeholder that's really long!"
    value="O no, an error"
    error={["dangnamit I'm broken", "dangnamit I'm broken"]}
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    large
  />
);

export const FocusOnMount = () => (
  <TextInputDemo
    label="Omg a label"
    placeholder="Look a placeholder that's really long!"
    value="Your input here"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    focusOnMount
  />
);

export const WithExtendedStyles = () => (
  <StyledTextInputDemo
    label="Omg a label"
    placeholder="Look a placeholder that's really long!"
    value="Your input here"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    focusOnMount
  />
);

export const DateFormattingMask = () => (
  <TextInputDemo
    label="Enter a date"
    placeholder="DD / MM / YYYY"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    mask
    maskOptions={{
      date: true,
      datePattern: ['d', 'm', 'Y'],
      delimiter: ' / ',
    }}
  />
);

export const DateFormattingMaskLarge = () => (
  <TextInputDemo
    label="Enter a date"
    placeholder="DD / MM / YYYY"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    mask
    maskOptions={{
      date: true,
      datePattern: ['d', 'm', 'Y'],
      delimiter: ' / ',
    }}
    large
  />
);

export const DateFormattingMaskError = () => (
  <TextInputDemo
    label="Enter a date"
    placeholder="DD / MM / YYYY"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    mask
    maskOptions={{
      date: true,
      datePattern: ['d', 'm', 'Y'],
      delimiter: ' / ',
    }}
    error="dangnamit I'm broken"
  />
);

export const DateFormattingMaskFocusOnMount = () => (
  <TextInputDemo
    label="Enter a date"
    placeholder="DD / MM / YYYY"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    mask
    maskOptions={{
      date: true,
      datePattern: ['d', 'm', 'Y'],
      delimiter: ' / ',
    }}
    focusOnMount
  />
);

export const DateFormattingMaskIconLeft = () => (
  <TextInputDemo
    label="Enter a date"
    placeholder="DD / MM / YYYY"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    mask
    maskOptions={{
      date: true,
      datePattern: ['d', 'm', 'Y'],
      delimiter: ' / ',
    }}
    iconType="lock"
    iconPosition="left"
  />
);

export const DateFormattingMaskIconRight = () => (
  <TextInputDemo
    label="Enter a date"
    placeholder="DD / MM / YYYY"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    mask
    maskOptions={{
      date: true,
      datePattern: ['d', 'm', 'Y'],
      delimiter: ' / ',
    }}
    iconType="lock"
    iconPosition="right"
  />
);

export const PhoneNumberMask = () => (
  <TextInputDemo
    label="Enter a phone number (CA)"
    placeholder="555 444 3333"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    type="number"
    mask
    maskOptions={{
      phone: true,
      phoneRegionCode: 'CA',
    }}
  />
);

export const Numeric = () => (
  <TextInputDemo
    label="Enter a number"
    placeholder="2"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    inputMode="numeric"
    type="number"
  />
);

export const CurrencyMask = () => (
  <TextInputDemo
    label="Enter a number"
    placeholder="$0.00"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    mask
    maskOptions={{
      numeral: true,
      prefix: '$',
      noImmediatePrefix: true,
      rawValueTrimPrefix: true,
    }}
    focusOnMount={false}
  />
);

export const NoBorder = () => (
  <TextInputDemo label="Label" onChange={action('onChange')} hideBorder />
);

export const NoBorderDisabled = () => (
  <TextInputDemo
    label="Label"
    onChange={action('onChange')}
    hideBorder
    disabled
  />
);

export const NoBorderDisabledLockIcon = () => (
  <TextInputDemo
    label="Label"
    onChange={action('onChange')}
    hideBorder
    disabled
    iconType="lock"
    iconPosition="right"
  />
);

export const MixinsMarginOnlySpacing = () => (
  <MarginChecker
    Component={TextInput}
    label="Label"
    onChange={action('onChange')}
  />
);

export const FloatingLabelText = () => (
  <TextInputDemo
    label="floating label!"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    type="text"
    value=""
    floatLabel
  />
);

export const FloatingLabelPassword = () => (
  <TextInputDemo
    label="Password"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    type="password"
    value=""
    floatLabel
    hideValueButtonLabel="Hide"
    revealValueButtonLabel="Show"
  />
);

export const FloatingLabelMaskedPassword = () => (
  <TextInputDemo
    label="Password"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    type="password"
    value=""
    floatLabel
    mask
    maskOptions={{
      delimiter: '',
    }}
    hideValueButtonLabel="Hide"
    revealValueButtonLabel="Show"
  />
);

export const FloatingLabelPasswordDisabled = () => (
  <TextInputDemo
    label="Password"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    type="password"
    value=""
    floatLabel
    hideValueButtonLabel="Hide"
    revealValueButtonLabel="Show"
    disabled
  />
);

export const FloatingLabelError = () => (
  <TextInputDemo
    label="floating label in error!"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    type="email"
    value="harry.potter@hogwartsfgdfgd"
    floatLabel
    error="that is not a valid hogwarts email address"
  />
);

export const FloatingLabelMaskedInput = () => (
  <TextInputDemo
    label="floating label with mask"
    onChange={action('onChange')}
    onFocus={action('onFocus')}
    onBlur={action('onBlur')}
    type="text"
    value=""
    floatLabel
    mask
    maskOptions={{
      date: true,
      datePattern: ['d', 'm', 'Y'],
      delimiter: ' / ',
    }}
  />
);

export const MixinsStackee = () => (
  <StackeeChecker
    Component={TextInput}
    label="Label"
    onChange={action('onChange')}
  />
);
