text: import React from "react";
  import { FormattedMessage, defineMessages, injectIntl, intlShape } from "react-intl";
  import PropTypes from "prop-types";
  import { connect } from "react-redux";
  import { Button, Checkbox, Form, FormGroup, Modal, ModalVariant, TextInput, TextArea } from "@patternfly/react-core";
  import { setBlueprintUsers } from "../../core/actions/blueprints";
  import "./UserAccount.css";
  
  const ariaLabels = defineMessages({
    adminCheckbox: {
      defaultMessage: "Server admin checkbox",
    },
  });
  
  const messages = defineMessages({
    sshKeyHelp: {
      defaultMessage: "Paste the contents of your public SSH key file here. ",
    },
    usernameValidChars: {
      defaultMessage: "The user name can only consist of letters from a-z, digits, dots, dashes and underscores.",
    },
    usernameEmpty: {
      defaultMessage: "The user name cannot be empty.",
    },
    usernameDuplicate: {
      defaultMessage: "This user name already exists.",
    },
    passwordMatch: {
      defaultMessage: "The values entered for password do not match.",
    },
    labelName: {
      defaultMessage: "Full name",
    },
    labelUsername: {
      defaultMessage: "User name",
    },
    labelRole: {
      defaultMessage: "Role",
    },
    labelAdmin: {
      defaultMessage: "Server administrator",
    },
    labelPassword: {
      defaultMessage: "Password",
    },
    labelConfirmPassword: {
      defaultMessage: "Confirm password",
    },
    labelSSHKey: {
      defaultMessage: "SSH key",
    },
  });
  
  class UserAccount extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        isModalOpen: false,
        name: "",
        // state value for existing username when editing user
        usernameOld: "",
        username: "",
        usernameValidated: "default",
        isUsernameDuplicate: false,
        isUsernameEmpty: false,
        isUsernameValidChars: false,
        isAdmin: false,
        password: "",
        passwordConfirm: "",
        passwordValidated: "default",
        sshKey: "",
      };
      this.handleModalOpen = this.handleModalOpen.bind(this);
      this.handleModalClose = this.handleModalClose.bind(this);
      this.handleSetName = this.handleSetName.bind(this);
      this.handleSetUsername = this.handleSetUsername.bind(this);
      this.handleIsAdmin = this.handleIsAdmin.bind(this);
      this.validateUserName = this.validateUserName.bind(this);
      this.handleSetPassword = this.handleSetPassword.bind(this);
      this.handleSetPasswordConfirm = this.handleSetPasswordConfirm.bind(this);
      this.validatePassword = this.validatePassword.bind(this);
      this.handleSetSSHKey = this.handleSetSSHKey.bind(this);
      this.handleCreateUser = this.handleCreateUser.bind(this);
      this.handleUpdateUser = this.handleUpdateUser.bind(this);
    }
  
    componentDidMount() {
      if (this.props.edit) {
        this.setState({
          username: this.props.user.name,
          usernameOld: this.props.user.name,
          name: this.props.user.description,
          password: this.props.user.password,
          passwordConfirm: this.props.user.password,
          isAdmin: this.props.user.groups && this.props.user.groups[0] === "wheel",
          sshKey: this.props.user.key ? this.props.user.key : "",
        });
      }
    }
  
    handleModalOpen() {
      this.setState({ isModalOpen: true });
    }
  
    handleModalClose() {
      // clear state
      if (this.props.edit) {
        this.setState({
          username: this.props.user.name,
          usernameOld: this.props.user.name,
          name: this.props.user.description,
          password: this.props.user.password,
          passwordConfirm: this.props.user.password,
          isAdmin: this.props.user.groups && this.props.user.groups[0] === "wheel",
          sshKey: this.props.user.key ? this.props.user.key : "",
        });
      } else {
        this.setState({
          name: "",
          username: "",
          password: "",
          passwordConfirm: "",
          sshKey: "",
        });
      }
      // clear validation
      this.setState({
        usernameValidated: "default",
        isUsernameDuplicate: false,
        isUsernameEmpty: false,
        isUsernameValidChars: false,
        passwordValidated: "default",
      });
      // close modal
      this.setState({ isModalOpen: false });
    }
  
    handleSetName(name) {
      this.setState({ name });
    }
  
    handleSetUsername(username) {
      this.setState({ username });
      this.validateUserName(username);
    }
  
    handleIsAdmin(checked) {
      this.setState({ isAdmin: checked });
    }
  
    handleSetPassword(password) {
      this.setState({ password });
      if (!password && !this.state.passwordConfirm) {
        this.setState({ passwordValidated: "default" });
      } else if (password === this.state.passwordConfirm) {
        this.setState({ passwordValidated: "success" });
      } else if (this.state.passwordConfirm && password !== this.state.passwordConfirm) {
        this.setState({ passwordValidated: "error" });
      }
    }
  
    handleSetPasswordConfirm(passwordConfirm) {
      this.setState({ passwordConfirm });
      if (!this.state.password && !passwordConfirm) {
        this.setState({ passwordValidated: "default" });
      } else if (this.state.password === passwordConfirm) {
        this.setState({ passwordValidated: "success" });
      } else {
        this.setState({ passwordValidated: "error" });
      }
    }
  
    handleSetSSHKey(sshKey) {
      this.setState({ sshKey });
    }
  
    handleCreateUser() {
      const user = {
        name: this.state.username,
        description: this.state.name ? this.state.name : undefined,
        groups: this.state.isAdmin ? ["wheel"] : undefined,
        password: this.state.password,
        key: this.state.sshKey ? this.state.sshKey : undefined,
      };
      const users = this.props.users.concat(user);
      this.props.setBlueprintUsers(this.props.blueprintID, users);
      this.handleModalClose();
    }
  
    handleUpdateUser() {
      const userUpdated = {
        name: this.state.username,
        description: this.state.name ? this.state.name : undefined,
        groups: this.state.isAdmin ? ["wheel"] : undefined,
        password: this.state.password,
        key: this.state.sshKey ? this.state.sshKey : undefined,
      };
      const users = this.props.users.map((user) => {
        if (user.name === this.state.usernameOld) return userUpdated;
        return user;
      });
      this.props.setBlueprintUsers(this.props.blueprintID, users);
      this.handleModalClose();
    }
  
    validateUserName(username) {
      if (username === "") {
        this.setState({ usernameValidated: "error", isUsernameEmpty: true });
        return;
      }
  
      let isDuplicateUser = false;
      this.props.users.map((user) => {
        if (user.name === username && user.name !== this.state.usernameOld) {
          isDuplicateUser = true;
        }
      });
      if (isDuplicateUser) {
        this.setState({ usernameValidated: "error", isUsernameDuplicate: true });
        return;
      }
  
      const validCharacters = /^(\d|\w|-|_|\.){0,252}$/.test(username);
      if (!validCharacters) {
        this.setState({ usernameValidated: "error", isUsernameValidChars: true });
        return;
      }
  
      this.setState({
        usernameValidated: "success",
        isUsernameEmpty: false,
        isUsernameDuplicate: false,
        isUsernameValidChars: false,
      });
    }
  
    validatePassword() {
      if (!this.state.password && !this.state.passwordConfirm) {
        this.setState({ passwordValidated: "default" });
      } else if (this.state.password === this.state.passwordConfirm) {
        this.setState({ passwordValidated: "success" });
      } else {
        this.setState({ passwordValidated: "error" });
      }
    }
  
    render() {
      const { isModalOpen } = this.state;
      const { formatMessage } = this.props.intl;
  
      return (
        <>
          {this.props.edit ? (
            <Button id="button-edit-user" variant="primary" onClick={this.handleModalOpen}>
              <span className="pficon pficon-edit" />
            </Button>
          ) : (
            <Button variant="primary" onClick={this.handleModalOpen}>
              <FormattedMessage defaultMessage="Create user account" />
            </Button>
          )}
          <Modal
            id="user-account-modal"
            position="top"
            variant={ModalVariant.medium}
            title={
              this.props.edit ? (
                <FormattedMessage defaultMessage="Edit user account" />
              ) : (
                <FormattedMessage defaultMessage="Create user account" />
              )
            }
            isOpen={isModalOpen}
            onClose={this.handleModalClose}
            actions={[
              this.props.edit ? (
                <Button
                  key="update"
                  variant="primary"
                  onClick={this.handleUpdateUser}
                  isDisabled={!this.state.username || this.state.password !== this.state.passwordConfirm}
                >
                  <FormattedMessage defaultMessage="Update" />
                </Button>
              ) : (
                <Button
                  key="create"
                  variant="primary"
                  onClick={this.handleCreateUser}
                  isDisabled={!this.state.username || this.state.password !== this.state.passwordConfirm}
                >
                  <FormattedMessage defaultMessage="Create" />
                </Button>
              ),
              <Button key="cancel" variant="link" onClick={this.handleModalClose}>
                <FormattedMessage defaultMessage="Cancel" />
              </Button>,
            ]}
          >
            <Form isHorizontal>
              <FormattedMessage
                defaultMessage="The fields marked with {val} are required."
                values={{
                  val: <span className="required-pf">*</span>,
                }}
              />
              <FormGroup label={formatMessage(messages.labelName)} fieldId="user-account-name">
                <TextInput value={this.state.name} type="text" id="user-account-name" onChange={this.handleSetName} />
              </FormGroup>
              <FormGroup
                label={formatMessage(messages.labelUsername)}
                isRequired
                fieldId="user-account-username"
                helperText={formatMessage(messages.usernameValidChars)}
                helperTextInvalid={
                  (this.state.isUsernameValidChars && formatMessage(messages.usernameValidChars)) ||
                  (this.state.isUsernameEmpty && formatMessage(messages.usernameEmpty)) ||
                  (this.state.isUsernameDuplicate && formatMessage(messages.usernameDuplicate))
                }
                validated={this.state.usernameValidated}
              >
                <TextInput
                  value={this.state.username}
                  onChange={this.handleSetUsername}
                  validated={this.state.usernameValidated}
                  isRequired
                  type="text"
                  id="user-account-username"
                />
              </FormGroup>
              <FormGroup label={formatMessage(messages.labelRole)} fieldId="user-account-role">
                <Checkbox
                  className="admin-checkbox"
                  label={formatMessage(messages.labelAdmin)}
                  isChecked={this.state.isAdmin}
                  type="text"
                  id="user-account-role"
                  onChange={this.handleIsAdmin}
                  aria-label={formatMessage(ariaLabels.adminCheckbox)}
                />
              </FormGroup>
              <FormGroup
                label={formatMessage(messages.labelPassword)}
                fieldId="user-account-password"
                validated={this.state.passwordValidated}
              >
                <TextInput
                  value={this.state.password}
                  onChange={this.handleSetPassword}
                  onBlur={this.validatePassword}
                  validated={this.state.passwordValidated}
                  type="password"
                  id="user-account-password"
                />
              </FormGroup>
              <FormGroup
                label={formatMessage(messages.labelConfirmPassword)}
                fieldId="user-account-password-confirm"
                validated={this.state.passwordValidated}
                helperTextInvalid={formatMessage(messages.passwordMatch)}
              >
                <TextInput
                  value={this.state.passwordConfirm}
                  onChange={this.handleSetPasswordConfirm}
                  validated={this.state.passwordValidated}
                  type="password"
                  id="user-account-password-confirm"
                />
              </FormGroup>
              <FormGroup
                label={formatMessage(messages.labelSSHKey)}
                fieldId="user-account-ssh-key"
                helperText={formatMessage(messages.sshKeyHelp)}
              >
                <TextArea
                  value={this.state.sshKey}
                  onChange={this.handleSetSSHKey}
                  type="text"
                  id="user-account-ssh-key"
                />
              </FormGroup>
            </Form>
          </Modal>
        </>
      );
    }
  }
  
  UserAccount.propTypes = {
    user: PropTypes.object,
    edit: PropTypes.bool,
    blueprintID: PropTypes.string,
    users: PropTypes.arrayOf(PropTypes.object),
    setBlueprintUsers: PropTypes.func,
    intl: intlShape.isRequired,
  };
  
  UserAccount.defaultProps = {
    user: {},
    edit: false,
    blueprintID: "",
    users: [],
    setBlueprintUsers() {},
  };
  
  const mapDispatchToProps = (dispatch) => ({
    setBlueprintUsers: (id, users) => {
      dispatch(setBlueprintUsers(id, users));
    },
  });
  
  export default connect(null, mapDispatchToProps)(injectIntl(UserAccount));
  