/**
 * @mergeTarget
 * @module Src/Screens/Users
 */
import {
  LisioCategoryNames,
  LisioParameterNames,
  LisioProfileNames,
} from "@lisio/lisio-profils";
import { LisioScreen } from "../lisio-screen";
import { UserController } from "../../../controllers/user-controller";
import { CustomText } from "../../components/custom-text/custom-text";
import { CustomButton } from "../../components/custom-button/custom-button";
import { CustomChoice } from "../../components/inputs/choice/custom-choice";
import {
  BooleanParameterRenderObject,
  StringParameterRenderObject,
  NumberParameterRenderObject,
  CategoryRenderObject,
  ProfileRenderObject,
  VisualCategoryNames,
  ScreenNames,
} from "../screen-types";
import { CustomChoiceItemObject } from "../../components/component-types";
import { ElementsContainer } from "../../components/containers/elements-container/elements-container";
import { CustomTextInput } from "../../components/inputs/text/custom-text-input";
import { LisioComponent } from "@lisio/lisio-engine";
import { ManagementScreen } from "../management/management-screen";
import { CustomIcon } from "../../components/custom-icon/custom-icon";

/**
 * Class representing an users screen component extending LisioScreen.\
 * It aims to represent an users screen component.\
 * An users screen component is basically a component to render alln users categories, profiles and parameters.\
 */
class UsersScreen extends LisioScreen {
  /**
   * Protected attribute to store category render objects
   * @source
   */
  protected _categoryRenderObjects: Map<
    LisioCategoryNames,
    CategoryRenderObject
  > = new Map<LisioCategoryNames, CategoryRenderObject>();

  /**
   * Protected attribute to store profile render objects
   * @source
   */
  protected _profileRenderObjects: Map<LisioProfileNames, ProfileRenderObject> =
    new Map<LisioProfileNames, ProfileRenderObject>();

  /**
   * Protected attribute to store parameter render objects
   * @source
   */
  protected _parameterRenderObjects: Map<
    LisioParameterNames,
    | BooleanParameterRenderObject
    | StringParameterRenderObject
    | NumberParameterRenderObject
  > = new Map<
    LisioParameterNames,
    | BooleanParameterRenderObject
    | StringParameterRenderObject
    | NumberParameterRenderObject
  >();

  /**
   * @async
   * Public method implementing abstract method render of LisioComponent
   * @returns Returns a promise containing the representation of an users screen in HTML string
   * @source
   */
  public async render(): Promise<string> {
    return `
    <section id="${this._id}">
      <children></children>
    </section>
    `;
  }

  /**
   * Public method to be called after render
   * @returns Returns nothing
   * @source
   */
  public postRender(): void {
    UserController.current.checkDeleteButtonState();
  }

  /**
   * Constructor of class {@link UsersScreen | UsersScreen}
   * @source
   */
  constructor() {
    ScreenNames[UsersScreen.name] = "users-screen";
    super(UsersScreen.name, UsersScreen.name, undefined, ManagementScreen.name);
    const userItemObjects: CustomChoiceItemObject[] = [];
    for (const user of UserController.current.users?.values()) {
      userItemObjects.push({
        textId: user.name,
        value: user.name,
        isChecked: user.isSelected,
        noTranslate: true,
      });
    }
    const customChoice = new CustomChoice(
      userItemObjects,
      "users-choice",
      ScreenNames[UsersScreen.name],
      VisualCategoryNames.USERS,
      ManagementScreen.name,
      undefined,
      undefined,
      undefined,
      ["secondary"],
      ["secondary", "full"],
    );
    UserController.current.usersList = customChoice;
    const elementsTitleContainer: LisioComponent = new ElementsContainer(
      [
        this.createScreenSubtitle("management-title"),
        this.createScreenTitle("users-title"),
      ],
      undefined,
      ["column gap-0"],
    );

    const infoboxManageUser: LisioComponent = new ElementsContainer(
      [
        new CustomText(
          "p",
          "infobox-user-managment",
          false,
          ["info-text"],
          undefined,
          "infobox-user-managment",
        ),
      ],
      undefined,
      ["full", "secondary", "infobox", "width-90", "margin-top-50px"],
    );

    const renameInput: CustomTextInput = new CustomTextInput(
      "rename-user",
      UserController.current.currentUser
        ? UserController.current.currentUser.name
        : "aucun utilisateur",
      ScreenNames[UsersScreen.name],
      VisualCategoryNames.USERS,
      ManagementScreen.name,
      "rename-user-label",
      ["medium"],
      { describedby: "rename-user-description" },
    );

    UserController.current.userRenameInput = renameInput;

    const deleteButton: CustomButton = new CustomButton(
      "delete-user-button",
      [new CustomText("p", "delete-user-button", undefined, ["regular"])],
      () => {
        UserController.current.deleteUser(
          UserController.current.currentUser!.name,
        );
      },
      ["btn-pill", "secondary", "btn-small", "red"],
      {
        label: {
          id: "aria-delete-user",
        },
      },
    );

    const modifUser = () => {
      const regex: RegExp = new RegExp("^[a-zA-Z0-9-]+$");
      const newUsername =
        renameInput.htmlElement?.querySelector("input")!.value;
      if (newUsername != undefined && regex.test(newUsername)) {
        UserController.current.renameUser(newUsername);
      }
    };

    UserController.current.deleteButton = deleteButton;

    const renameInputBox = new ElementsContainer(
      [
        renameInput,
        new ElementsContainer(
          [
            deleteButton,
            new CustomButton(
              "rename-user-button",
              [
                new CustomText("p", "validate-user-button", undefined, [
                  "regular",
                ]),
              ],
              modifUser,
              ["btn-pill", "btn-small", "btn-outline-grey"],
              {
                label: {
                  id: "aria-update-user",
                },
              },
            ),
          ],
          undefined,
          ["row", "full", "justify-content-center"],
        ),
      ],
      undefined,
      ["column"],
    );

    const userManagementElement = new ElementsContainer(
      [
        new ElementsContainer([renameInputBox], undefined, [
          "row",
          "secondary",
          "align-items-center",
          "justify-content-center",
          "full",
        ]),
      ],
      undefined,
      ["full", "column"],
    );

    this.children.push(
      elementsTitleContainer,
      customChoice,
      new CustomButton(
        "add-user",
        [
          new CustomIcon("misc-icons", "User", ["white"]),
          new CustomText("p", "add-user-button", undefined, ["regular"]),
        ],
        async () => {
          await UserController.current.createNewUser();
        },
        ["btn-pill", "btn-grey", "width-75"],
      ),
      infoboxManageUser,
      userManagementElement,
    );
  }
}

export { UsersScreen };
