import _extends from "@babel/runtime/helpers/extends";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
// Copyright 1999-2021. Plesk International GmbH. All rights reserved.
import React, { Component, Fragment, createRef } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { CLS_PREFIX } from '../../constants';
import Button from '../Button';
import FormField from '../FormField';
import Input from '../Input';
import Popover from '../Popover';
import Translate from '../Translate';
import passwordScore, { PASSWORD_SCORE_RULES } from './passwordScore';
import locale from './locale/en-US';
const symbolClasses = {
  upper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
  lower: 'abcdefghijklmnopqrstuvwxyz',
  number: '0123456789',
  special: '!@#$%^&*?_~'
};
export const generatePassword = () => {
  const password = ['upper', 'lower', 'lower', 'lower', 'number', 'number', 'special', 'number', 'upper', 'upper', 'lower', 'lower', 'lower', 'lower', 'lower', 'lower'];
  return password.sort((a, b) => Math.floor(b.length * Math.random()) - Math.floor(a.length * Math.random())).map(symbolClass => symbolClasses[symbolClass][Math.floor(symbolClasses[symbolClass].length * Math.random())]).join('');
};
/**
 * `FormFieldPassword` component provides secure way to enter a password.
 * @since 0.0.58
 */

class FormFieldPassword extends Component {
  constructor(...args) {
    super(...args);

    _defineProperty(this, "state", {
      visible: false,
      passwordMeterVisible: false
    });

    _defineProperty(this, "targetRef", /*#__PURE__*/createRef());

    _defineProperty(this, "handleToggleClick", () => {
      this.setState(({
        visible
      }) => ({
        visible: !visible
      }));
    });

    _defineProperty(this, "handleClosePasswordMeter", () => {
      this.setState({
        passwordMeterVisible: false
      });
    });

    _defineProperty(this, "handleBlur", this.handleClosePasswordMeter);
  }

  passwordScore(value) {
    if (!value) {
      return {
        intent: null,
        strength: null,
        unusedRules: []
      };
    }

    const {
      passwordScoreRules
    } = this.props;
    const {
      score,
      unusedRules
    } = passwordScore(value, passwordScoreRules);
    let intent = 'success';
    let strength = /*#__PURE__*/React.createElement(Translate, {
      content: "FormFieldPassword.strengthVeryStrong",
      fallback: locale.strengthVeryStrong
    });

    if (score < 16) {
      intent = 'danger';
      strength = /*#__PURE__*/React.createElement(Translate, {
        content: "FormFieldPassword.strengthVeryWeak",
        fallback: locale.strengthVeryWeak
      });
    } else if (score < 25) {
      intent = 'danger';
      strength = /*#__PURE__*/React.createElement(Translate, {
        content: "FormFieldPassword.strengthWeak",
        fallback: locale.strengthWeak
      });
    } else if (score < 35) {
      intent = 'warning';
      strength = /*#__PURE__*/React.createElement(Translate, {
        content: "FormFieldPassword.strengthMedium",
        fallback: locale.strengthMedium
      });
    } else if (score < 45) {
      intent = 'success';
      strength = /*#__PURE__*/React.createElement(Translate, {
        content: "FormFieldPassword.strengthStrong",
        fallback: locale.strengthStrong
      });
    }

    return {
      intent,
      strength,
      unusedRules
    };
  }

  renderPasswordMeter(value, target) {
    const {
      passwordMeterVisible
    } = this.state;
    const {
      passwordMeterProps
    } = this.props;
    const {
      intent,
      strength,
      unusedRules
    } = this.passwordScore(value);
    return /*#__PURE__*/React.createElement(Popover, _extends({
      visible: passwordMeterVisible && !!value,
      target: target,
      targetRef: this.targetRef,
      placement: "bottom-right",
      intent: intent,
      canCloseOnOutsideClick: false,
      canCloseOnEscapePress: false,
      onClose: this.handleClosePasswordMeter
    }, passwordMeterProps), /*#__PURE__*/React.createElement(Translate, {
      content: "FormFieldPassword.passwordStrength",
      fallback: locale.passwordStrength,
      params: {
        strength: /*#__PURE__*/React.createElement("b", null, strength)
      }
    }), /*#__PURE__*/React.createElement("br", null), unusedRules.length ? /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(Translate, {
      content: "FormFieldPassword.improvePassword",
      fallback: locale.improvePassword
    }), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("ul", null, unusedRules.slice(0, 3).map(({
      rule
    }, index) => {
      const {
        name
      } = rule;
      let {
        message
      } = rule;

      if (name && !message) {
        message = /*#__PURE__*/React.createElement(Translate, {
          content: "FormFieldPassword.".concat(name),
          fallback: locale[name]
        });
      }

      return /*#__PURE__*/React.createElement("li", {
        key: name || index.toString()
      }, message);
    }))) : /*#__PURE__*/React.createElement(Translate, {
      content: "FormFieldPassword.yourPasswordIsStrong",
      fallback: locale.yourPasswordIsStrong
    }));
  }

  renderGenerateButton({
    setValue,
    isDisabled
  }) {
    const {
      baseClassName,
      generateButton
    } = this.props;
    const generateButtonProps = {
      className: "".concat(baseClassName, "__button--generate"),
      onClick: () => setValue(generatePassword()),
      tooltip: /*#__PURE__*/React.createElement(Translate, {
        content: "FormFieldPassword.generateButtonHint",
        fallback: locale.generateButtonHint
      }),
      disabled: isDisabled(),
      children: /*#__PURE__*/React.createElement(Translate, {
        content: "FormFieldPassword.generateButton",
        fallback: locale.generateButton
      })
    };
    let button;

    if (typeof generateButton === 'function') {
      button = generateButton(generateButtonProps);
    } else {
      button = /*#__PURE__*/React.createElement(Button, generateButtonProps);
    }

    return /*#__PURE__*/React.createElement(Fragment, null, " ", button);
  }

  render() {
    const {
      baseClassName,
      className,
      hideShowButton,
      generateButton,
      hideGenerateButton,
      hidePasswordMeter,
      passwordMeterProps,
      passwordScoreRules,
      size,
      autoFocus,
      autoComplete,
      ...props
    } = this.props;
    return /*#__PURE__*/React.createElement(FormField, _extends({
      className: classNames(baseClassName, className)
    }, props), ({
      getId,
      getName,
      getValue,
      setValue,
      isDisabled
    }) => {
      const input = /*#__PURE__*/React.createElement(Input, {
        id: getId(),
        name: getName(),
        type: this.state.visible ? 'text' : 'password',
        value: getValue(''),
        onChange: e => {
          setValue(e.target.value);
          this.setState({
            passwordMeterVisible: true
          });
        },
        onFocus: this.handleFocus,
        onBlur: this.handleBlur,
        autoFocus: autoFocus,
        autoComplete: autoComplete,
        className: "".concat(baseClassName, "__input"),
        size: size,
        suffix: hideShowButton ? null : /*#__PURE__*/React.createElement(Button, {
          className: "".concat(baseClassName, "__button--show"),
          onClick: this.handleToggleClick,
          icon: this.state.visible ? 'visible' : 'invisible',
          tooltip: this.state.visible ? /*#__PURE__*/React.createElement(Translate, {
            content: "FormFieldPassword.hidePassword",
            fallback: locale.hidePassword
          }) : /*#__PURE__*/React.createElement(Translate, {
            content: "FormFieldPassword.showPassword",
            fallback: locale.showPassword
          }),
          ghost: true,
          disabled: isDisabled()
        }),
        disabled: isDisabled(),
        rootProps: {
          ref: this.targetRef
        }
      });
      return /*#__PURE__*/React.createElement("div", {
        className: classNames("".concat(baseClassName, "__control"), "".concat(baseClassName, "__control--").concat(size))
      }, /*#__PURE__*/React.createElement("div", {
        className: classNames("".concat(baseClassName, "__field"), "".concat(baseClassName, "__field--").concat(size))
      }, hidePasswordMeter ? input : this.renderPasswordMeter(getValue(), input)), hideGenerateButton ? null : this.renderGenerateButton({
        setValue,
        isDisabled
      }));
    });
  }

}

FormFieldPassword.propTypes = {
  /**
   * Is show button hidden?
   * @since 0.0.59
   */
  hideShowButton: PropTypes.bool,

  /**
   * Is generate button hidden?
   * @since 0.0.59
   */
  hideGenerateButton: PropTypes.bool,

  /**
   * Is password meter hidden?
   * @since 0.0.59
   */
  hidePasswordMeter: PropTypes.bool,

  /**
   * Additional props for password meter. . See [Popover](#!/Popover) for more information.
   * @since 1.5.6
   */
  passwordMeterProps: PropTypes.object,

  /**
   * A set of custom password score rules.
   * @since 3.21.0
   */
  passwordScoreRules: PropTypes.arrayOf(PropTypes.shape({
    name: PropTypes.string,
    message: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
    score: PropTypes.func.isRequired
  })),

  /**
   * Size of the control
   * @since 1.5.6
   */
  size: PropTypes.oneOf(['md', 'lg', 'xl', 'fill']),

  /**
   * The browser will automatically focus on the component upon rendering the screen
   * @since 1.9.0
   */
  autoFocus: PropTypes.bool,

  /**
   * Prevent password autocompletion.
   * @since 2.5.1
   */
  autoComplete: PropTypes.oneOf(['new-password']),

  /**
   * A render function for customizing the password generation button.
   * @since 3.13.0
   */
  generateButton: PropTypes.func,

  /**
   * @ignore
   */
  className: PropTypes.string,

  /**
   * @ignore
   */
  baseClassName: PropTypes.string
};
FormFieldPassword.defaultProps = {
  hideShowButton: false,
  generateButton: undefined,
  hideGenerateButton: false,
  hidePasswordMeter: false,
  passwordMeterProps: {},
  passwordScoreRules: undefined,
  size: 'md',
  autoFocus: undefined,
  autoComplete: undefined,
  className: undefined,
  baseClassName: "".concat(CLS_PREFIX, "form-field-password")
};
FormFieldPassword.PASSWORD_SCORE_RULES = PASSWORD_SCORE_RULES;
export default FormFieldPassword;