import { ref, useContext, Ref } from '@nuxtjs/composition-api'
import { Ability } from '@casl/ability'
import { ItemMenu, ItemsMenu, OrganizationStore } from '~/types/interfaces'
import { getAccessMenu } from '~/composables/layout/Menus/accessMenu'
import { getAgendaMenu } from '~/composables/layout/Menus/agendaMenu'
import { getEquipmentMenu } from '~/composables/layout/Menus/equipmentMenu'
import { getEducationalMenu } from '~/composables/layout/Menus/educationalMenu'
import { getBillingMenu } from '~/composables/layout/Menus/billingMenu'
import { getCommunicationMenu } from '~/composables/layout/Menus/communicationMenu'
import { getDonorsMenu } from '~/composables/layout/Menus/donorsMenu'
import { getMedalsMenu } from '~/composables/layout/Menus/medalsMenu'
import { getStatsMenu } from '~/composables/layout/Menus/statsMenu'
import { getCotisationsMenu } from '~/composables/layout/Menus/cotisationsMenu'
import { getAdmin2iosMenu } from '~/composables/layout/Menus/admin2iosMenu'
import { getWebsiteMenu } from '~/composables/layout/Menus/websiteMenu'
import { getConfigurationMenu } from '~/composables/layout/Menus/configurationMenu'
import { getMyFamilyMenu } from '~/composables/layout/Menus/myFamilyMenu'
import { getMyAccessesMenu } from '~/composables/layout/Menus/myAccessesMenu'
import { getAccountMenu } from '~/composables/layout/Menus/accountMenu'

/**
 * @category composables/layout
 * @class Menu
 * Use Classe pour la construction du Menu
 */
class Menu {
  private $ability!: Ability;
  private $config!: any;
  private $store!: OrganizationStore;

  /**
   * Initialise le context NUXT
   */
  setupContext () {
    const { $ability, $config, store } = useContext()
    this.$ability = $ability
    this.$config = $config
    this.$store = store
    return this
  }

  /**
   * Construit le menu et mets à jour le state du profile d'access
   */
  useLateralMenuConstruct (): Ref {
    const menu: ItemsMenu = []

    const accessMenu: ItemMenu | null = getAccessMenu(this.$config, this.$ability, this.$store)
    if (accessMenu) { menu.push(accessMenu) }

    const agendaMenu: ItemMenu | null = getAgendaMenu(this.$config, this.$ability)
    if (agendaMenu) { menu.push(agendaMenu) }

    const equipmentMenu: ItemMenu | null = getEquipmentMenu(this.$config, this.$ability)
    if (equipmentMenu) { menu.push(equipmentMenu) }

    const educationalMenu: ItemMenu | null = getEducationalMenu(this.$config, this.$ability)
    if (educationalMenu) { menu.push(educationalMenu) }

    const billingMenu: ItemMenu | null = getBillingMenu(this.$config, this.$ability)
    if (billingMenu) { menu.push(billingMenu) }

    const communicationMenu: ItemMenu | null = getCommunicationMenu(this.$config, this.$ability)
    if (communicationMenu) { menu.push(communicationMenu) }

    const donorsMenu: ItemMenu | null = getDonorsMenu(this.$config, this.$ability)
    if (donorsMenu) { menu.push(donorsMenu) }

    const medalsMenu: ItemMenu | null = getMedalsMenu(this.$config, this.$ability)
    if (medalsMenu) { menu.push(medalsMenu) }

    const websiteMenu: ItemMenu | null = getWebsiteMenu(this.$config, this.$ability, this.$store).getMenu()
    if (websiteMenu) { menu.push(websiteMenu) }

    const cotisationsMenu: ItemMenu | null = getCotisationsMenu(this.$config, this.$ability)
    if (cotisationsMenu) { menu.push(cotisationsMenu) }

    const statsMenu: ItemMenu | null = getStatsMenu(this.$config, this.$ability)
    if (statsMenu) { menu.push(statsMenu) }

    const admin2iosMenu: ItemMenu | null = getAdmin2iosMenu(this.$config, this.$ability)
    if (admin2iosMenu) { menu.push(admin2iosMenu) }

    // Si l'utilisateur possède au moins un menu alors le menu latéral sera accessible
    this.$store.commit('profile/access/setHasLateralMenu', menu.length > 0)

    return ref(menu)
  }

  /**
   * Construit le menu configuration et met à jour le state du profile d'access
   */
  useConfigurationMenuConstruct (): Ref {
    const menu: ItemMenu | null = getConfigurationMenu(this.$config, this.$ability, this.$store)
    // Si l'utilisateur possède au moins un menu alors le menu configuration sera accessible
    this.$store.commit('profile/access/setHasConfigurationMenu', menu != null)
    return ref(menu)
  }

  /**
   * Construit le menu Mon Compte
   */
  useAccountMenuConstruct (): Ref {
    return ref(getAccountMenu(this.$config, this.$ability, this.$store))
  }

  /**
   * Construit le menu Mes structure et mets à jour le state du profile d'access
   */
  useMyAccessesMenuConstruct (): Ref {
    const menu: ItemMenu | null = getMyAccessesMenu(this.$config, this.$ability, this.$store)
    // Si l'utilisateur possède au moins un menu alors le menu mes structures sera accessible
    this.$store.commit('profile/access/setHasAccessesMenu', menu != null)
    return ref(menu)
  }

  /**
   * Construit le menu Changement d'utilisateur et mets à jour le state du profile d'access
   */
  useMyFamilyMenuConstruct (): Ref {
    const menu: ItemMenu | null = getMyFamilyMenu(this.$config, this.$ability, this.$store)
    // Si l'utilisateur possède au moins un menu alors le menu changement d'utilisateur sera accessible
    this.$store.commit('profile/access/setHasFamilyMenu', menu != null)
    return ref(menu)
  }

  /**
   * Construit le menu site internet du header
   */
  useWebSiteMenuConstruct (): Ref {
    return ref(getWebsiteMenu(this.$config, this.$ability, this.$store).getHeaderMenu())
  }
}

export const $useMenu = new Menu()
