import { Query as VuexQuery } from '@vuex-orm/core'
import { Collection, Item } from '@vuex-orm/core/dist/src/data/Data'
import { $objectProperties } from '~/services/utils/objectProperties'
import { AnyJson } from '~/types/interfaces'
import {OrderByVuexOrm} from "~/types/types";

/**
 * Classe Wrapper pour assurer les opérations les plus communes des Query de VuexORM
 */
class Query {
  /**
   * Récupération de l'Item souhaité
   *
   * @param {VuexQuery} query
   * @param {number|string} id
   * @return {Item} l'Item
   */
  public getItem (query: VuexQuery, id: number|string): Item {
    const item = query.find(id)
    if (!item || typeof item === 'undefined') { throw new Error('item not found') }
    return item
  }

  /**
   * Récupération du premier item
   *
   * @param {VuexQuery} query
   * @return {Item} l'Item
   */
  public getFirstItem (query: VuexQuery): Item {
    const item = query.first()
    if (!item || typeof item === 'undefined') { throw new Error('item not found') }
    return item
  }

  /**
   * Récupération la collection de la Query
   *
   * @param {VuexQuery} query
   * @return {Collection} Array d'Item
   */
  public getCollection (query: VuexQuery, orderBy?: OrderByVuexOrm): Collection {
    if(orderBy){
      for(const orderKey in orderBy){
        query.orderBy(orderKey, orderBy[orderKey])
      }
    }

    return query.get()
  }

  /**
   * Récupération de l'Item souhaité puis transformation en JSON aplati
   *
   * @param {VuexQuery} query
   * @param {number|string} id
   * @return {AnyJson} réponse
   */
  public getFlattenEntry (query: VuexQuery, id: number|string): AnyJson {
    return $objectProperties.cloneAndFlatten(this.getItem(query, id) as AnyJson)
  }

  /**
   * Récupération la collection de la Query puis transformation en JSON aplati
   *
   * @param {VuexQuery} query
   * @return {Array<AnyJson>} réponse
   */
  public getFlattenEntries (query: VuexQuery): Array<AnyJson> {
    const entries = this.getCollection(query)
    return entries.map((entry: AnyJson) => {
      return $objectProperties.cloneAndFlatten(entry)
    })
  }
}

export const queryHelper = new Query()
