/**
 * @mergeTarget
 * @module Src/Screens/Synth
 */
import {
  LisioBooleanParameterNames,
  LisioCategoryNames,
  LisioNumericParameterNames,
  LisioParameterNames,
  LisioProfileNames,
  LisioUser,
  defautValueOfNumericParameters,
} from "@lisio/lisio-profils";
import { LisioScreen } from "../lisio-screen";
import {
  BooleanParameterRenderObject,
  StringParameterRenderObject,
  NumberParameterRenderObject,
  ComponentAndPosition,
  CategoryRenderObject,
  ProfileRenderObject,
  VisualCategoryNames,
  ScreenNames,
} from "../screen-types";
import { ListContainer } from "../../components/containers/list-container/list-container";
import { HomeScreen } from "../home/home-screen";
import { CustomText } from "../../components/custom-text/custom-text";
import { CustomIcon } from "../../components/custom-icon/custom-icon";
import { ElementsContainer } from "../../components/containers/elements-container/elements-container";
import { LisioComponent } from "@lisio/lisio-engine";
import { MoreScreen } from "../more/more-screen";
import { isTouchDevice } from "../../../../misc/functions";

/**
 * Class representing a synth screen component extending LisioScreen.\
 * It aims to represent a synth screen component.\
 * A synth screen component is basically a component to render all synth categories, profiles and parameters.\
 */
class SynthScreen extends LisioScreen {
  /**
   * Protected attribute to store category render objects
   * @source
   */
  protected _categoryRenderObjects: Map<
    VisualCategoryNames,
    CategoryRenderObject
  > = new Map<VisualCategoryNames, CategoryRenderObject>([
    [
      VisualCategoryNames.MORE,
      {
        buttonId: `${this.id}-more`,
        icon: {
          fileName: "footer-icons",
          iconName: "More",
        },
        titleId: "more-button",
        nextScreenName: MoreScreen.name,
        position: 10,
        isActive: false,
        activeSubObjects: new Set(),
        firstIconClasses: ["grey2"],
        iconsClasses: ["grey"],
        cssClasses: ["secondary", "footer-button"],
      },
    ],
  ]);

  /**
   * 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.SPEECH_SYNTHESIS_STATE,
      {
        type: "boolean",
        name: LisioBooleanParameterNames.SPEECH_SYNTHESIS_STATE,
        buttonId: "speech-synth-state",
        titleId: "speech-synth-state-button-disabled",
        activeTitleId: "speech-synth-state-button-enabled",
        value: false,
        position: 0,
        cssClasses: ["width-100", "btn-pill", "secondary", "space-between"],
        aria: { describedby: "infobox-speech-synth-state" },
      } as BooleanParameterRenderObject,
    ],
    [
      LisioNumericParameterNames.SPEECH_SYNTHESIS_RATE,
      {
        type: "number",
        name: LisioNumericParameterNames.SPEECH_SYNTHESIS_RATE,
        buttonId: "speech-synth-rate",
        titleId: "speech-synth-rate-button",
        defaultValue: defautValueOfNumericParameters.get(
          LisioNumericParameterNames.SPEECH_SYNTHESIS_RATE,
        ),
        currentValue: 1,
        minValue: 0.25,
        maxValue: 2,
        step: 0.25,
        position: 1,
        cssClasses: ["secondary"],
        icon: {
          fileName: "misc-icons",
          iconName: "SynthSpeed",
        },
        iconClasses: ["primary"],
      } as NumberParameterRenderObject,
    ],
    [
      LisioNumericParameterNames.SPEECH_SYNTHESIS_PITCH,
      {
        type: "number",
        name: LisioNumericParameterNames.SPEECH_SYNTHESIS_PITCH,
        buttonId: "speech-synth-pitch",
        titleId: "speech-synth-pitch-button",
        defaultValue: defautValueOfNumericParameters.get(
          LisioNumericParameterNames.SPEECH_SYNTHESIS_PITCH,
        ),
        currentValue: 1,
        minValue: 0.25,
        maxValue: 2,
        step: 0.25,
        position: 2,
        cssClasses: ["secondary"],
        icon: {
          fileName: "misc-icons",
          iconName: "SynthPitch",
        },
        iconClasses: ["primary"],
      } as NumberParameterRenderObject,
    ],
  ]);

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

  /**
   * Constructor of class {@link SynthScreen | SynthScreen}
   * @param {LisioUser | undefined} user - Current user
   * @source
   */
  constructor(isCompensation?: boolean, user?: LisioUser) {
    ScreenNames[SynthScreen.name] = "synth-screen";
    super(
      SynthScreen.name,
      SynthScreen.name,
      LisioCategoryNames.SPEECH_SYNTHESIS,
      HomeScreen.name,
    );
    const parametersElements: ComponentAndPosition[] = this.initParameters(
      Array.from(this._parameterRenderObjects.keys()),
      [],
      user?.customParameters,
    );
    parametersElements.sort((a, b) => a.position - b.position);

    const elementsTitleContainer: LisioComponent =
      this.createScreenTitle("synth-title");

    const elementsContainer: LisioComponent = new ListContainer(
      [parametersElements[0].component],
      undefined,
      ["full", "column", "secondary", "lines-h"],
    );

    const textSection: LisioComponent = new ElementsContainer(
      [
        new CustomText(
          "p",
          "infobox-speech-synth-state",
          false,
          ["info-text"],
          undefined,
          "infobox-speech-synth-state",
        ),
        new ElementsContainer(
          [
            new ElementsContainer(
              [
                new ElementsContainer(
                  [
                    new CustomIcon(
                      "synth-icons",
                      isTouchDevice() ? "Play" : "PlayCursor",
                      ["synth"],
                    ),
                  ],
                  undefined,
                  ["width-auto"],
                ),
                new CustomText(
                  "p",
                  isTouchDevice() ? "synth-play-button" : "synth-play-cursor",
                ),
              ],
              undefined,
              ["align-items-center", "row"],
            ),
            new ElementsContainer(
              [
                new ElementsContainer(
                  [
                    new CustomIcon(
                      "synth-icons",
                      isTouchDevice() ? "Pause" : "PauseCursor",
                      ["synth"],
                    ),
                  ],
                  undefined,
                  ["width-auto"],
                ),
                new CustomText(
                  "p",
                  isTouchDevice() ? "synth-pause-button" : "synth-pause-cursor",
                ),
              ],
              undefined,
              ["align-items-center", "row"],
            ),
          ],
          undefined,
          ["justify-content-evenly", "column"],
        ),
      ],
      undefined,
      ["column", "full", "secondary", "infobox"],
    );

    const elementsContainer2: LisioComponent = new ListContainer(
      [parametersElements[1].component, parametersElements[2].component],
      undefined,
      ["full", "row", "secondary", "wrap"],
    );

    const contentAndFooterContainer: LisioComponent = new ListContainer(
      [
        elementsContainer,
        textSection,
        elementsContainer2,
        ...(isCompensation ? this.createFooter(isCompensation) : []),
      ],
      undefined,
      ["column test", "screen-ul", "width-100"],
    );
    this._children?.push(
      this.createScreenSubtitle("synth-title"),
      elementsTitleContainer,
      contentAndFooterContainer,
    );
  }
}

export { SynthScreen };
