import { Mutation, VuexModule } from 'vuex-module-decorators'

type ModelId = string | number | null
type PrimaryKey = 'id' | 'uid' | 'uuid'

type BaseModel = {
  [key: string]: any
  id?: ModelId
  uid?: ModelId
  uuid?: ModelId
}

export default class BaseStore<Model extends BaseModel> extends VuexModule {
  models: Model[] = []
  model: Model | null = null
  modelPrimaryKey: PrimaryKey = 'id'
  isLoadingModels = false
  isLoadingModel = false
  isLoadingSaveModel = false
  isLoadingRemoveModel = false

  get modelsById(): any {
    return this.models.reduce((result: any, model) => {
      result[model.id as number] = model
      return result
    }, {})
  }

  @Mutation
  public setModelsLoading(value: boolean) {
    this.isLoadingModels = value
  }

  @Mutation
  public setModelLoading(value: boolean) {
    this.isLoadingModel = value
  }

  @Mutation
  public setSaveModelLoading(value: boolean) {
    this.isLoadingSaveModel = value
  }

  @Mutation
  public setRemoveModelLoading(value: boolean) {
    this.isLoadingRemoveModel = value
  }

  @Mutation
  public setPrimaryKey(key: PrimaryKey) {
    this.modelPrimaryKey = key
  }

  @Mutation
  public setModels(models: Model[]) {
    this.models = models
  }

  @Mutation
  public setModel(model: Model | null) {
    this.model = model
  }

  @Mutation
  public addModel(model: Model, toEnd?: boolean) {
    toEnd ? this.models.push(model) : this.models.unshift(model)
  }

  @Mutation
  public updateModelInList(changedModel: Model) {
    const index = this.models.findIndex(model => {
      return model[this.modelPrimaryKey] === changedModel[this.modelPrimaryKey]
    })

    this.models.splice(index, 1, changedModel)
  }

  @Mutation
  public removeModel(modelId: ModelId) {
    this.models.splice(
      this.models.findIndex(model => {
        return model[this.modelPrimaryKey] === modelId
      }),
      1
    )
  }
}
