import {IconItem, MenuBuilder, MenuGroup, MenuItem, MenuItems} from '~/types/layout'
import {MENU_LINK_TYPE} from "~/types/enum/layout";
import {RuntimeConfig} from "@nuxt/schema";
import UrlUtils from "~/services/utils/urlUtils";
import {AnyAbility} from "@casl/ability";
import {AccessProfile, organizationState} from "~/types/interfaces";

/**
 * Classe de base des menus et sous-menus.
 *
 * La méthode principale est la méthode build
 */
abstract class AbstractMenuBuilder implements MenuBuilder {
  protected runtimeConfig: RuntimeConfig;
  protected ability: AnyAbility;
  protected organizationProfile: organizationState;
  protected accessProfile: AccessProfile;

  /**
   * Nom court désignant le menu que construit ce builder
   */
  static readonly menuName: string

  constructor (
      runtimeConfig: RuntimeConfig,
      ability: AnyAbility,
      organizationProfile: organizationState,
      accessProfile: AccessProfile,
  ) {
    this.runtimeConfig = runtimeConfig
    this.ability = ability
    this.organizationProfile = organizationProfile
    this.accessProfile = accessProfile
  }

  /**
   * Permet un accès non statique à la variable menuName
   */
  public getMenuName(): string {
    return Object.getPrototypeOf(this).constructor.menuName
  }

  /**
   * Construit et retourne un menu ou sous-menu selon le profil de l'utilisateur, le profil de son organisation
   * et les droits de l'utilisateur.
   *
   * Si le menu comporte plusieurs éléments, retourne une instance de MenuGroup
   * Si le menu ne comporte qu'un seul élément, retourne une instance de MenuItem
   * Si le menu ne comporte aucun élément, retourne null.
   */
  abstract build (): MenuItem | MenuGroup | null

  /**
   * Construit et retourne un MenuGroup
   *
   * @param label
   * @param icon
   * @param {Array<MenuItem>} children Tableau d'ItemMenu représentant les sous menu du menu principal
   * @param actions
   */
  protected createGroup(
      label: string,
      icon?: IconItem,
      children: MenuItems = [],
      actions: Array<MenuItem> = []
  ): MenuGroup {
    return { label, icon, children, actions }
  }

  /**
   * Construit et retourne un MenuItem
   *
   * @param {IconItem} icon
   * @param {string} label Titre qui sera traduit
   * @param to
   * @param type
   * @return {MenuItem}
   */
  protected createItem (
      label: string,
      icon?: IconItem,
      to: string = '',
      type: MENU_LINK_TYPE = MENU_LINK_TYPE.INTERNAL,
  ): MenuItem {
    let url: string

    switch(type) {
      case MENU_LINK_TYPE.V1:
        const v1BaseURL = this.runtimeConfig.baseUrlAdminLegacy || this.runtimeConfig.public.baseUrlAdminLegacy
        url = UrlUtils.join(v1BaseURL, to)
        break;
      case MENU_LINK_TYPE.EXTERNAL:
        url = UrlUtils.prependHttps(to)
        break;
      default:
        url = to
    }

    return { icon, label, to: url, type, active: false }
  }

  protected buildSubmenu(menuBuilder: typeof AbstractMenuBuilder) {
    // @ts-ignore
    const builder = new menuBuilder(this.runtimeConfig, this.ability, this.organizationProfile, this.accessProfile)
    return builder.build()

  }
}
export default AbstractMenuBuilder
