/*
Copyright (C) 2017  Cloudbase Solutions SRL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

import React from "react";
import { observer } from "mobx-react";
import styled from "styled-components";

import type { User } from "@src/@types/User";
import type { Project } from "@src/@types/Project";
import type { Field as FieldType } from "@src/@types/Field";
import Button from "@src/components/ui/Button";
import Modal from "@src/components/ui/Modal";
import FieldInput from "@src/components/ui/FieldInput";

import LabelDictionary from "@src/utils/LabelDictionary";
import KeyboardManager from "@src/utils/KeyboardManager";

import { ThemeProps } from "@src/components/Theme";
import userImage from "./images/user.svg";

const Wrapper = styled.div<any>`
  padding: 48px 0 32px 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
`;
const Image = styled.div<any>`
  width: 96px;
  height: 96px;
  background: url("${userImage}") center no-repeat;
  margin: 0 auto;
`;
const Form = styled.div<any>`
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  margin-top: 64px;
  overflow: auto;
  padding: 0 32px;

  > div {
    margin-top: 16px;
  }
`;
const Buttons = styled.div<any>`
  margin-top: 32px;
  display: flex;
  justify-content: space-between;
  padding: 0 32px;
`;

type Props = {
  user?: User;
  isLoggedUser?: boolean;
  loading: boolean;
  isNewUser?: boolean;
  projects: Project[];
  editPassword?: boolean;
  onRequestClose: () => void;
  onUpdateClick: (user: User) => void;
};

type State = {
  name: string;
  email: string;
  enabled?: boolean;
  projectId?: string;
  highlightFieldNames: string[];
  password: string;
  confirmPassword: string;
  description?: string;
};
@observer
class UserModal extends React.Component<Props, State> {
  UNSAFE_componentWillMount() {
    this.setState({
      name: this.props.user ? this.props.user.name : "",
      email: this.props.user ? this.props.user.email : "",
      description: this.props.user ? this.props.user.description : "",
      projectId: this.props.user ? this.props.user.project_id : "",
      enabled: this.props.user ? this.props.user.enabled : true,
      highlightFieldNames: [],
      password: "",
      confirmPassword: "",
    });
  }

  componentDidMount() {
    KeyboardManager.onEnter(
      "editUserModal",
      () => {
        this.handleUpdateClick();
      },
      2,
    );
  }

  componentWillUnmount() {
    KeyboardManager.removeKeyDown("editUserModal");
  }

  handleUpdateClick() {
    if (
      (this.props.isNewUser && this.highlightAllFields()) ||
      (!this.props.isNewUser &&
        !this.props.editPassword &&
        this.highlightDetailsFields()) ||
      (!this.props.isNewUser &&
        this.props.editPassword &&
        this.highlightPasswordFields())
    ) {
      return;
    }

    this.props.onUpdateClick({
      id: "",
      project: { id: "", name: "" },
      project_id: this.state.projectId,
      name: this.state.name,
      email: this.state.email,
      description: this.state.description,
      password: this.state.password,
      enabled: this.state.enabled,
    });
  }

  highlightAllFields() {
    const highlightFieldNames = [];
    if (!this.state.name) {
      highlightFieldNames.push("username");
    }
    if (!this.state.password) {
      highlightFieldNames.push("new_password");
    }
    if (
      this.state.password &&
      this.state.password !== this.state.confirmPassword
    ) {
      highlightFieldNames.push("confirm_password");
    }
    if (highlightFieldNames.length > 0) {
      this.setState({ highlightFieldNames });
      return true;
    }
    this.setState({ highlightFieldNames: [] });
    return false;
  }

  highlightDetailsFields(): boolean {
    if (!this.state.name) {
      this.setState({ highlightFieldNames: ["username"] });
      return true;
    }

    this.setState({ highlightFieldNames: [] });
    return false;
  }

  highlightPasswordFields(): boolean {
    if (!this.state.password) {
      this.setState({ highlightFieldNames: ["new_password"] });
      return true;
    }
    if (this.state.password !== this.state.confirmPassword) {
      this.setState({ highlightFieldNames: ["confirm_password"] });
      return true;
    }
    this.setState({ highlightFieldNames: [] });
    return false;
  }

  renderField(field: FieldType, value: any, onChange: (value: any) => void) {
    const disabled =
      this.props.loading ||
      (this.props.isLoggedUser && field.name === "enabled");

    return (
      <FieldInput
        layout="modal"
        key={field.name}
        name={field.name}
        label={LabelDictionary.get(field.name)}
        type={field.type || "string"}
        value={value}
        onChange={onChange}
        width={ThemeProps.inputSizes.large.width}
        disabled={disabled}
        enum={field.enum}
        password={
          field.name === "new_password" || field.name === "confirm_password"
        }
        required={field.required}
        highlight={Boolean(
          this.state.highlightFieldNames.find(n => n === field.name),
        )}
        noSelectionMessage="Choose a project"
      />
    );
  }

  renderForm() {
    let fields;
    const passwordFields = [
      this.renderField(
        { name: "new_password", required: true },
        this.state.password,
        password => {
          this.setState({ password });
        },
      ),
      this.renderField(
        { name: "confirm_password", required: true },
        this.state.confirmPassword,
        confirmPassword => {
          this.setState({ confirmPassword });
        },
      ),
    ];
    const detailsFields = [
      this.renderField(
        { name: "username", required: true },
        this.state.name,
        name => {
          this.setState({ name });
        },
      ),
      this.renderField(
        { name: "description" },
        this.state.description,
        description => {
          this.setState({ description });
        },
      ),
      this.renderField({ name: "Email" }, this.state.email, email => {
        this.setState({ email });
      }),
      this.renderField(
        {
          name: "Primary Project",

          enum: [{ name: "Choose a project", id: null } as any].concat(
            this.props.projects.concat([]),
          ),
        },
        this.state.projectId,
        projectId => {
          this.setState({ projectId });
        },
      ),
    ];
    const enabledField = this.renderField(
      { name: "enabled", type: "boolean" },
      this.state.enabled,
      enabled => {
        this.setState({ enabled });
      },
    );

    if (this.props.isNewUser) {
      fields = detailsFields.concat(passwordFields).concat(enabledField);
    } else if (this.props.editPassword) {
      fields = passwordFields;
    } else {
      fields = detailsFields.concat(enabledField);
    }

    return <Form>{fields}</Form>;
  }

  render() {
    const label = this.props.isNewUser
      ? "New User"
      : this.props.editPassword
        ? "Change Password"
        : "Update User";

    return (
      <Modal isOpen title={label} onRequestClose={this.props.onRequestClose}>
        <Wrapper>
          <Image />
          {this.renderForm()}
          <Buttons>
            <Button secondary large onClick={this.props.onRequestClose}>
              Cancel
            </Button>
            <Button
              large
              disabled={this.props.loading}
              onClick={() => {
                this.handleUpdateClick();
              }}
            >
              {label}
            </Button>
          </Buttons>
        </Wrapper>
      </Modal>
    );
  }
}

export default UserModal;
