import React, { useState, useEffect, useContext } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { I18nContext } from '../../../contexts/i18n';
import ButtonGroup from '../../../components/ui/button-group';
import Button from '../../../components/ui/button';
import InfoTooltip from '../../../components/ui/info-tooltip';
import ToggleButton from '../../../components/ui/toggle-button';
import Box from '../../../components/ui/box';
import Typography from '../../../components/ui/typography';
import {
  TYPOGRAPHY,
  FONT_WEIGHT,
  ALIGN_ITEMS,
  DISPLAY,
} from '../../../helpers/constants/design-system';
import { getTranslatedStxErrorMessage } from '../swaps.util';
import { SLIPPAGE } from '../../../../shared/constants/swaps';

export default function SlippageButtons({
  onSelect,
  maxAllowedSlippage,
  currentSlippage,
  smartTransactionsEnabled,
  smartTransactionsOptInStatus,
  setSmartTransactionsOptInStatus,
  currentSmartTransactionsError,
  isDirectWrappingEnabled,
}) {
  const t = useContext(I18nContext);
  const [customValue, setCustomValue] = useState(() => {
    if (
      typeof currentSlippage === 'number' &&
      !Object.values(SLIPPAGE).includes(currentSlippage)
    ) {
      return currentSlippage.toString();
    }
    return '';
  });
  const [enteringCustomValue, setEnteringCustomValue] = useState(false);
  const [activeButtonIndex, setActiveButtonIndex] = useState(() => {
    if (currentSlippage === SLIPPAGE.HIGH) {
      return 1; // 3% slippage.
    } else if (currentSlippage === SLIPPAGE.DEFAULT) {
      return 0; // 2% slippage.
    } else if (typeof currentSlippage === 'number') {
      return 2; // Custom slippage.
    }
    return 0;
  });
  const [open, setOpen] = useState(() => {
    return currentSlippage !== SLIPPAGE.DEFAULT; // Only open Advanced Options by default if it's not default slippage.
  });
  const [inputRef, setInputRef] = useState(null);

  let errorText = '';
  if (customValue) {
    // customValue is a string, e.g. '0'
    if (Number(customValue) < 0) {
      errorText = t('swapSlippageNegative');
    } else if (Number(customValue) > 0 && Number(customValue) <= 1) {
      // We will not show this warning for 0% slippage, because we will only
      // return non-slippage quotes from off-chain makers.
      errorText = t('swapLowSlippageError');
    } else if (
      Number(customValue) >= 5 &&
      Number(customValue) <= maxAllowedSlippage
    ) {
      errorText = t('swapHighSlippageWarning');
    } else if (Number(customValue) > maxAllowedSlippage) {
      errorText = t('swapsExcessiveSlippageWarning');
    }
  }

  const customValueText = customValue || t('swapCustom');

  useEffect(() => {
    if (
      inputRef &&
      enteringCustomValue &&
      window.document.activeElement !== inputRef
    ) {
      inputRef.focus();
    }
  }, [inputRef, enteringCustomValue]);

  return (
    <div className="slippage-buttons">
      <button
        onClick={() => setOpen(!open)}
        className={classnames('slippage-buttons__header', {
          'slippage-buttons__header--open': open,
        })}
      >
        <div className="slippage-buttons__header-text">
          {t('swapsAdvancedOptions')}
        </div>
        {open ? (
          <i className="fa fa-angle-up" />
        ) : (
          <i className="fa fa-angle-down" />
        )}
      </button>
      <div className="slippage-buttons__content">
        {open && (
          <>
            {!isDirectWrappingEnabled && (
              <div className="slippage-buttons__dropdown-content">
                <div className="slippage-buttons__buttons-prefix">
                  <div className="slippage-buttons__prefix-text">
                    {t('swapsMaxSlippage')}
                  </div>
                  <InfoTooltip
                    position="top"
                    contentText={t('swapAdvancedSlippageInfo')}
                  />
                </div>
                <ButtonGroup
                  defaultActiveButtonIndex={
                    activeButtonIndex === 2 && !customValue
                      ? 1
                      : activeButtonIndex
                  }
                  variant="radiogroup"
                  newActiveButtonIndex={activeButtonIndex}
                  className={classnames(
                    'button-group',
                    'slippage-buttons__button-group',
                  )}
                >
                  <Button
                    onClick={() => {
                      setCustomValue('');
                      setEnteringCustomValue(false);
                      setActiveButtonIndex(0);
                      onSelect(SLIPPAGE.DEFAULT);
                    }}
                  >
                    {t('swapSlippagePercent', [SLIPPAGE.DEFAULT])}
                  </Button>
                  <Button
                    onClick={() => {
                      setCustomValue('');
                      setEnteringCustomValue(false);
                      setActiveButtonIndex(1);
                      onSelect(SLIPPAGE.HIGH);
                    }}
                  >
                    {t('swapSlippagePercent', [SLIPPAGE.HIGH])}
                  </Button>
                  <Button
                    className={classnames(
                      'slippage-buttons__button-group-custom-button',
                      {
                        'radio-button--danger': errorText,
                      },
                    )}
                    onClick={() => {
                      setActiveButtonIndex(2);
                      setEnteringCustomValue(true);
                    }}
                  >
                    {enteringCustomValue ? (
                      <div
                        className={classnames(
                          'slippage-buttons__custom-input',
                          {
                            'slippage-buttons__custom-input--danger': errorText,
                          },
                        )}
                      >
                        <input
                          onChange={(event) => {
                            const { value } = event.target;
                            const isValueNumeric = !isNaN(Number(value));
                            if (isValueNumeric) {
                              setCustomValue(value);
                              onSelect(Number(value));
                            }
                          }}
                          type="text"
                          maxLength="4"
                          ref={setInputRef}
                          onBlur={() => {
                            setEnteringCustomValue(false);
                          }}
                          value={customValue || ''}
                        />
                      </div>
                    ) : (
                      customValueText
                    )}
                    {(customValue || enteringCustomValue) && (
                      <div className="slippage-buttons__percentage-suffix">
                        %
                      </div>
                    )}
                  </Button>
                </ButtonGroup>
              </div>
            )}
            {smartTransactionsEnabled && (
              <Box marginTop={2} display={DISPLAY.FLEX}>
                <Box
                  display={DISPLAY.FLEX}
                  alignItems={ALIGN_ITEMS.CENTER}
                  paddingRight={3}
                >
                  <Typography
                    variant={TYPOGRAPHY.H6}
                    boxProps={{ paddingRight: 2 }}
                    fontWeight={FONT_WEIGHT.BOLD}
                  >
                    {t('smartTransaction')}
                  </Typography>
                  {currentSmartTransactionsError ? (
                    <InfoTooltip
                      position="top"
                      contentText={getTranslatedStxErrorMessage(
                        currentSmartTransactionsError,
                        t,
                      )}
                    />
                  ) : (
                    <InfoTooltip position="top" contentText={t('stxTooltip')} />
                  )}
                </Box>
                <ToggleButton
                  value={smartTransactionsOptInStatus}
                  onToggle={(value) => {
                    setSmartTransactionsOptInStatus(!value, value);
                  }}
                  offLabel={t('off')}
                  onLabel={t('on')}
                  disabled={Boolean(currentSmartTransactionsError)}
                />
              </Box>
            )}
          </>
        )}
        {errorText && (
          <div className="slippage-buttons__error-text">{errorText}</div>
        )}
      </div>
    </div>
  );
}

SlippageButtons.propTypes = {
  onSelect: PropTypes.func.isRequired,
  maxAllowedSlippage: PropTypes.number.isRequired,
  currentSlippage: PropTypes.number,
  smartTransactionsEnabled: PropTypes.bool.isRequired,
  smartTransactionsOptInStatus: PropTypes.bool,
  setSmartTransactionsOptInStatus: PropTypes.func,
  currentSmartTransactionsError: PropTypes.string,
  isDirectWrappingEnabled: PropTypes.bool,
};