"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = exports.generatePassword = void 0;

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _react = _interopRequireWildcard(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _classnames = _interopRequireDefault(require("classnames"));

var _constants = require("../../constants");

var _Button = _interopRequireDefault(require("../Button"));

var _FormField = _interopRequireDefault(require("../FormField"));

var _Input = _interopRequireDefault(require("../Input"));

var _Popover = _interopRequireDefault(require("../Popover"));

var _Translate = _interopRequireDefault(require("../Translate"));

var _passwordScore = _interopRequireWildcard(require("./passwordScore"));

var _enUS = _interopRequireDefault(require("./locale/en-US"));

// Copyright 1999-2021. Plesk International GmbH. All rights reserved.
const symbolClasses = {
  upper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
  lower: 'abcdefghijklmnopqrstuvwxyz',
  number: '0123456789',
  special: '!@#$%^&*?_~'
};

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
 */


exports.generatePassword = generatePassword;

class FormFieldPassword extends _react.Component {
  constructor(...args) {
    super(...args);
    (0, _defineProperty2.default)(this, "state", {
      visible: false,
      passwordMeterVisible: false
    });
    (0, _defineProperty2.default)(this, "targetRef", /*#__PURE__*/(0, _react.createRef)());
    (0, _defineProperty2.default)(this, "handleToggleClick", () => {
      this.setState(({
        visible
      }) => ({
        visible: !visible
      }));
    });
    (0, _defineProperty2.default)(this, "handleClosePasswordMeter", () => {
      this.setState({
        passwordMeterVisible: false
      });
    });
    (0, _defineProperty2.default)(this, "handleBlur", this.handleClosePasswordMeter);
  }

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

    const {
      passwordScoreRules
    } = this.props;
    const {
      score,
      unusedRules
    } = (0, _passwordScore.default)(value, passwordScoreRules);
    let intent = 'success';

    let strength = /*#__PURE__*/_react.default.createElement(_Translate.default, {
      content: "FormFieldPassword.strengthVeryStrong",
      fallback: _enUS.default.strengthVeryStrong
    });

    if (score < 16) {
      intent = 'danger';
      strength = /*#__PURE__*/_react.default.createElement(_Translate.default, {
        content: "FormFieldPassword.strengthVeryWeak",
        fallback: _enUS.default.strengthVeryWeak
      });
    } else if (score < 25) {
      intent = 'danger';
      strength = /*#__PURE__*/_react.default.createElement(_Translate.default, {
        content: "FormFieldPassword.strengthWeak",
        fallback: _enUS.default.strengthWeak
      });
    } else if (score < 35) {
      intent = 'warning';
      strength = /*#__PURE__*/_react.default.createElement(_Translate.default, {
        content: "FormFieldPassword.strengthMedium",
        fallback: _enUS.default.strengthMedium
      });
    } else if (score < 45) {
      intent = 'success';
      strength = /*#__PURE__*/_react.default.createElement(_Translate.default, {
        content: "FormFieldPassword.strengthStrong",
        fallback: _enUS.default.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.default.createElement(_Popover.default, (0, _extends2.default)({
      visible: passwordMeterVisible && !!value,
      target: target,
      targetRef: this.targetRef,
      placement: "bottom-right",
      intent: intent,
      canCloseOnOutsideClick: false,
      canCloseOnEscapePress: false,
      onClose: this.handleClosePasswordMeter
    }, passwordMeterProps), /*#__PURE__*/_react.default.createElement(_Translate.default, {
      content: "FormFieldPassword.passwordStrength",
      fallback: _enUS.default.passwordStrength,
      params: {
        strength: /*#__PURE__*/_react.default.createElement("b", null, strength)
      }
    }), /*#__PURE__*/_react.default.createElement("br", null), unusedRules.length ? /*#__PURE__*/_react.default.createElement(_react.Fragment, null, /*#__PURE__*/_react.default.createElement(_Translate.default, {
      content: "FormFieldPassword.improvePassword",
      fallback: _enUS.default.improvePassword
    }), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("ul", null, unusedRules.slice(0, 3).map(({
      rule
    }, index) => {
      const {
        name
      } = rule;
      let {
        message
      } = rule;

      if (name && !message) {
        message = /*#__PURE__*/_react.default.createElement(_Translate.default, {
          content: "FormFieldPassword.".concat(name),
          fallback: _enUS.default[name]
        });
      }

      return /*#__PURE__*/_react.default.createElement("li", {
        key: name || index.toString()
      }, message);
    }))) : /*#__PURE__*/_react.default.createElement(_Translate.default, {
      content: "FormFieldPassword.yourPasswordIsStrong",
      fallback: _enUS.default.yourPasswordIsStrong
    }));
  }

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

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

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

  render() {
    const {
      baseClassName,
      className,
      hideShowButton,
      generateButton,
      hideGenerateButton,
      hidePasswordMeter,
      passwordMeterProps,
      passwordScoreRules,
      size,
      autoFocus,
      autoComplete,
      ...props
    } = this.props;
    return /*#__PURE__*/_react.default.createElement(_FormField.default, (0, _extends2.default)({
      className: (0, _classnames.default)(baseClassName, className)
    }, props), ({
      getId,
      getName,
      getValue,
      setValue,
      isDisabled
    }) => {
      const input = /*#__PURE__*/_react.default.createElement(_Input.default, {
        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.default.createElement(_Button.default, {
          className: "".concat(baseClassName, "__button--show"),
          onClick: this.handleToggleClick,
          icon: this.state.visible ? 'visible' : 'invisible',
          tooltip: this.state.visible ? /*#__PURE__*/_react.default.createElement(_Translate.default, {
            content: "FormFieldPassword.hidePassword",
            fallback: _enUS.default.hidePassword
          }) : /*#__PURE__*/_react.default.createElement(_Translate.default, {
            content: "FormFieldPassword.showPassword",
            fallback: _enUS.default.showPassword
          }),
          ghost: true,
          disabled: isDisabled()
        }),
        disabled: isDisabled(),
        rootProps: {
          ref: this.targetRef
        }
      });

      return /*#__PURE__*/_react.default.createElement("div", {
        className: (0, _classnames.default)("".concat(baseClassName, "__control"), "".concat(baseClassName, "__control--").concat(size))
      }, /*#__PURE__*/_react.default.createElement("div", {
        className: (0, _classnames.default)("".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.default.bool,

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

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

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

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

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

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

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

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

  /**
   * @ignore
   */
  className: _propTypes.default.string,

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