/**
 * @mergeTarget
 * @module Src/Screens/Management
 */

import {
  LisioParameterNames,
  LisioBooleanParameterNames,
  LisioUser,
  LisioProfileNames,
} from "@lisio/lisio-profils";
import { LisioScreen } from "../lisio-screen";
import {
  CategoryRenderObject,
  BooleanParameterRenderObject,
  StringParameterRenderObject,
  NumberParameterRenderObject,
  ComponentAndPosition,
  ProfileRenderObject,
  VisualCategoryNames,
  MergedCategoriesNames,
  ScreenNames,
} from "../screen-types";
import { ListContainer } from "../../components/containers/list-container/list-container";
import { UsersScreen } from "../users/users-screen";
import { ResetScreen } from "../reset/reset-screen";
import { LisioComponent } from "@lisio/lisio-engine";
import { Group } from "../../../versions/widget-version";
import { UserController } from "../../../controllers/user-controller";
import { ElementsContainer } from "../../components/containers/elements-container/elements-container";
import { CustomText } from "../../components/custom-text/custom-text";

/**
 * Class representing a management screen component extending LisioScreen.\
 * It aims to represent a management screen component.\
 * A management screen component is basically a component to render all management categories, profiles and parameters.\
 */
class ManagementScreen extends LisioScreen {
  /**
   * Protected attribute to store category render objects
   * @source
   */
  protected _categoryRenderObjects: Map<
    MergedCategoriesNames,
    CategoryRenderObject
  > = new Map<MergedCategoriesNames, CategoryRenderObject>([
    [
      VisualCategoryNames.USERS,
      {
        buttonId: "users",
        icon: {
          fileName: "misc-icons",
          iconName: "User",
        },
        titleId: "users-title",
        nextScreenName: UsersScreen.name,
        position: 8,
        isActive: false,
        activeSubObjects: new Set(),
        firstIconClasses: ["primary"],
        iconsClasses: ["grey"],
        cssClasses: ["secondary", "space-between"],
      },
    ],
    [
      VisualCategoryNames.RESET,
      {
        buttonId: "reset",
        icon: {
          fileName: "misc-icons",
          iconName: "Reset",
        },
        titleId: "reset-title",
        nextScreenName: ResetScreen.name,
        position: 10,
        isActive: false,
        activeSubObjects: new Set(),
        iconsClasses: ["red"],
        cssClasses: ["reset", "space-between"],
      },
    ],
  ]);

  /**
   * 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
  >([
    [
      LisioBooleanParameterNames.IS_ACTIVE,
      {
        buttonId: "adaptation",
        titleId: "adaptation-disabled",
        activeTitleId: "adaptation-enabled",
        name: LisioBooleanParameterNames.IS_ACTIVE,
        position: 9,
        cssClasses: ["btn-pill", "secondary", "width-100"],
        aria: { describedby: "infobox-adaptation" },
        icon: {
          fileName: "misc-icons",
          iconName: "Deactivate",
        },
        iconClasses: ["red"],
      } as BooleanParameterRenderObject,
    ],
  ]);

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

  /**
   * Constructor of class {@link ManagementScreen | ManagementScreen}
   * @param {Group[]} groups - Groups to display in this screen
   * @param {LisioUser | undefined} user - Current user
   * @source
   */
  constructor(groups: Group[], user?: LisioUser) {
    ScreenNames[ManagementScreen.name] = "management-screen";
    super(
      ManagementScreen.name,
      ManagementScreen.name,
      VisualCategoryNames.MANAGEMENT,
    );
    let elementsTitleContainer: LisioComponent;

    elementsTitleContainer = this.createScreenTitle("management-title");

    const introductionText = new ElementsContainer(
      [
        new CustomText(
          "p",
          "infobox-adaptation",
          false,
          ["info-text"],
          undefined,
          "infobox-adaptation",
        ),
      ],
      undefined,
      ["infobox", "column", "full", "secondary"],
    );

    const managementContainerChildren: LisioComponent[] = [];

    for (const group of groups) {
      const categoriesElements: ComponentAndPosition[] = this.initCategories(
        group.categories,
      );
      const profilesElements: ComponentAndPosition[] = this.initProfiles(
        group.profiles,
        [],
        user?.profiles,
      );
      const parametersElements: ComponentAndPosition[] = this.initParameters(
        group.parameters,
        [],
        user?.customParameters,
      );
      const groupElements: ComponentAndPosition[] = categoriesElements
        .concat(profilesElements)
        .concat(parametersElements);
      groupElements.sort((a, b) => a.position - b.position);

      const elementContainerClasses: string[] = [
        "column",
        "full",
        "secondary",
        "p-0",
      ];
      // if (group.categories[0] === "users") {
      //   elementContainerClasses.push("margin-top-50px");
      // }
      const elementsContainer: LisioComponent = new ListContainer(
        groupElements.map((groupElement) => groupElement.component),
        undefined,
        elementContainerClasses,
      );
      group.categories.includes(VisualCategoryNames.USERS)
        ? (UserController.current.userGroup = elementsContainer)
        : (UserController.current.activationGroup = elementsContainer);

      managementContainerChildren.unshift(elementsContainer);
    }
    const managementContainer = new ListContainer(
      managementContainerChildren,
      "management-container",
      ["column", "width-100", "lines-h"],
    );
    const test = new ElementsContainer(
      [introductionText, managementContainer],
      undefined,
      ["column"],
    );
    this._children.push(elementsTitleContainer, test);
  }
}

export { ManagementScreen };
