import React, { FC, HTMLAttributes, useState, useCallback } from 'react';
import styled from 'styled-components';
import useDimensions from 'react-use-dimensions';
import { ConvertCard } from './styled/ConvertCard';
import { IconX } from './IconX';
import { IconCopy } from './IconCopy';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import { InMenuOptionStuff } from './InMenuOptionStuff';
import { OutMenuOptionStuff } from './OutMenuOptionStuff';
import { IInOption, InOptions, IOutOption, OutOptions } from './types';
import { CaseBar } from './CaseBar';
import { SideBar } from './SideBar';
import { TextAreaContentTop, TextAreaContentBottom } from './TextAreaContent';
import { TextAreaWrapper } from './TextAreaWrapper';
import { Spacer } from './Spacer';
import { OptionsOverlay } from './OptionsOverlay';
import { IconContainer } from './styled/IconContainer';
import { MoreOptionsIconContainer } from './MoreOptionsIconContainer';
import {
  IMaxContentLengthIndicator,
  MaxContentLengthIndicator,
} from './MaxContentLengthIndicator';
import { Textarea } from './styled/Textarea';

export { IInOption, IOutOption, InOptions, OutOptions };

const ConvertCardContent = styled.div`
  width: 100%;
  display: flex;
  position: relative;

  @media (max-width: 720px) {
    flex-direction: column;
  }
`;

const OptionsContainer = styled.div`
  display: flex;

  @media (max-width: 576px) {
    display: none;
  }
`;

const Flex = styled.div`
  display: flex;
`;

const liveMeasure = true;

export interface Props extends HTMLAttributes<HTMLDivElement> {
  inOptions: InOptions;
  inValue: string;
  outValue: string;
  onInInput: (text: string) => void;
  onInOptionsUpdate: (newInOptions: InOptions) => void;
  outOptions: OutOptions;
  onOutOptionsUpdate: (newOutOptions: OutOptions) => void;
  maxContentLength?: number;
  onCopy?: () => void;
  maxContentLengthIndicator?: null | IMaxContentLengthIndicator;
  autoCloseMenuOnOptionSelection?: boolean;
}

export const InOutTextarea: FC<Props> = props => {
  const [menuInOptions, setMenuInOptions] = useState<InOptions>([]);
  const [menuOutOptions, setMenuOutOptions] = useState<OutOptions>([]);
  const [inOptionsMenuRef, inOptionsMenuRefSizes] = useDimensions({
    liveMeasure,
  });
  const [outOptionsMenuRef, outOptionsMenuRefSizes] = useDimensions({
    liveMeasure,
  });
  const [convertCardRef, convertCardSizes] = useDimensions({ liveMeasure });

  const [showAdditionalInOptions, setShowAdditionalInOptions] = useState<
    boolean
  >(false);

  const [showAdditionalOutOptions, setShowAdditionalOutOptions] = useState<
    boolean
  >(false);

  const onInMoreOptionsClick = useCallback(() => {
    setShowAdditionalOutOptions(false);
    setShowAdditionalInOptions(!showAdditionalInOptions);
  }, [showAdditionalInOptions]);

  const onOutMoreOptionsClick = useCallback(() => {
    setShowAdditionalInOptions(false);
    setShowAdditionalOutOptions(!showAdditionalOutOptions);
  }, [showAdditionalOutOptions]);

  const {
    inOptions,
    inValue,
    onInInput,
    onInOptionsUpdate,
    outOptions,
    onOutOptionsUpdate,
    outValue,
    maxContentLength,
    onCopy,
    maxContentLengthIndicator,
    autoCloseMenuOnOptionSelection = true,
  } = props;

  const onInOverlayOptionClick = useCallback(() => {
    if (autoCloseMenuOnOptionSelection) setShowAdditionalInOptions(false);
  }, [autoCloseMenuOnOptionSelection]);

  const onOutOverlayOptionClick = useCallback(() => {
    if (autoCloseMenuOnOptionSelection) setShowAdditionalOutOptions(false);
  }, [autoCloseMenuOnOptionSelection]);

  return (
    <ConvertCard>
      <CaseBar>
        <SideBar>
          <OptionsContainer>
            {inOptions
              .sort(a => {
                if (a.active) return -1;
                return 0;
              })
              .map(option => {
                return (
                  <InMenuOptionStuff
                    key={option.name}
                    inOptionsMenuRefSizes={inOptionsMenuRefSizes}
                    liveMeasure={liveMeasure}
                    menuOptions={menuInOptions}
                    option={option}
                    inOptions={inOptions}
                    onInOptionsUpdate={onInOptionsUpdate}
                    setMenuOptions={setMenuInOptions}
                  />
                );
              })}
          </OptionsContainer>
          <MoreOptionsIconContainer
            ref={inOptionsMenuRef}
            onClick={onInMoreOptionsClick}
            active={showAdditionalInOptions}
          />
        </SideBar>
        <Spacer />
        <SideBar>
          <OptionsContainer>
            {outOptions
              .sort(a => {
                if (a.activeClicked) return -1;
                if (a.active) return -1;
                return 0;
              })
              .map(option => {
                return (
                  <OutMenuOptionStuff
                    key={option.name}
                    outOptionsMenuRefSizes={outOptionsMenuRefSizes}
                    liveMeasure={liveMeasure}
                    menuOptions={menuOutOptions}
                    option={option}
                    outOptions={outOptions}
                    onOutOptionsUpdate={onOutOptionsUpdate}
                    setMenuOptions={setMenuOutOptions}
                  />
                );
              })}
          </OptionsContainer>
          <MoreOptionsIconContainer
            right
            ref={outOptionsMenuRef}
            onClick={onOutMoreOptionsClick}
            active={showAdditionalOutOptions}
          />
        </SideBar>
      </CaseBar>
      <ConvertCardContent ref={convertCardRef}>
        {showAdditionalOutOptions && (
          <OptionsOverlay
            convertCardSizes={convertCardSizes}
            shownMenuOptions={menuOutOptions}
            allMenuOptions={outOptions}
            onAllMenuOptionsUpdate={onOutOptionsUpdate}
            onOptionClick={onOutOverlayOptionClick}
          />
        )}
        {showAdditionalInOptions && (
          <OptionsOverlay
            convertCardSizes={convertCardSizes}
            shownMenuOptions={menuInOptions}
            allMenuOptions={inOptions}
            onAllMenuOptionsUpdate={onInOptionsUpdate}
            onOptionClick={onInOverlayOptionClick}
          />
        )}
        <TextAreaContentTop>
          <Flex>
            <TextAreaWrapper>
              <Textarea
                data-test="from-textarea"
                placeholder="..."
                rows={2}
                smallerFont={false}
                value={inValue}
                maxLength={maxContentLength}
                onChange={(event: React.ChangeEvent<HTMLTextAreaElement>) => {
                  if (
                    event.target.value === null ||
                    event.target.value === undefined
                  )
                    return;
                  onInInput(event.target.value);
                }}
              />
            </TextAreaWrapper>
            <IconContainer onClick={() => onInInput('')}>
              <IconX size={32} />
            </IconContainer>
          </Flex>
          {maxContentLengthIndicator &&
            maxContentLengthIndicator.show &&
            maxContentLength && (
              <MaxContentLengthIndicator
                currentLength={inValue ? inValue.length : 0}
                maxContentLength={maxContentLength}
                maxContentLengthIndicator={maxContentLengthIndicator}
              />
            )}
        </TextAreaContentTop>
        <TextAreaContentBottom>
          <TextAreaWrapper>
            <Textarea
              disabled
              smallerFont={false}
              showCopyCursor
              value={outValue}
            />
          </TextAreaWrapper>
          <CopyToClipboard
            text={outValue}
            onCopy={() => {
              if (onCopy) {
                onCopy();
              }
            }}
          >
            <IconContainer>
              <IconCopy size={24} />
            </IconContainer>
          </CopyToClipboard>
        </TextAreaContentBottom>
      </ConvertCardContent>
    </ConvertCard>
  );
};