import Vuex from 'vuex'
import Vue from 'vue'
import createPersistedState from 'vuex-persistedstate'
import { getStoreBuilder } from 'vuex-typex'

// @ts-ignore
import './modules/ui'
// @ts-ignore
import './modules/authentication'
// @ts-ignore
import './modules/feedback_list/feedback-search-options'
// @ts-ignore
import './modules/feedback_list/feedback-table'
// @ts-ignore
import './modules/subscriptions'
// @ts-ignore
import './modules/submission-notes'
// @ts-ignore
import './modules/student-page'
// @ts-ignore
import './modules/tutor-overview'

import './mutations'
import './actions'
import './getters'

import { UIState } from './modules/ui'
import { AuthState } from './modules/authentication'
import { FeedbackSearchOptionsState } from './modules/feedback_list/feedback-search-options'
import { SubscriptionsState } from './modules/subscriptions'
import { FeedbackTableState } from './modules/feedback_list/feedback-table'
import { SubmissionNotesState } from './modules/submission-notes'
import { StudentPageState } from './modules/student-page'
import { TutorOverviewState, TutorOverview } from './modules/tutor-overview'

import { lastInteraction } from '@/store/plugins/lastInteractionPlugin'
import {
  Exam, Feedback,
  Statistics,
  StudentInfoForListView,
  SubmissionNoType,
  SubmissionType, Tutor, FeedbackLabel
} from '@/models'
import { FeedbackLabelsState } from './modules/feedback-labels';

Vue.use(Vuex)

export interface RootInitialState {
    lastAppInteraction: number
    examTypes: {[pk: string]: Exam}
    submissionTypes: {[pk: string]: SubmissionType}
    submissions: {[pk: string]: SubmissionNoType}
    students: {[pk: string]: StudentInfoForListView}
    studentMap: {
      [matrikel: string]: {
        matrikelNo: string, name: string
      }
    } // is used to map obfuscated student data back to the original
    statistics: Statistics
}

export interface RootState extends RootInitialState{
  UI: UIState,
  Authentication: AuthState,
  FeedbackSearchOptions: FeedbackSearchOptionsState,
  FeedbackTable: FeedbackTableState,
  Subscriptions: SubscriptionsState,
  SubmissionNotes: SubmissionNotesState,
  StudentPage: StudentPageState,
  TutorOverview: TutorOverviewState,
  FeedbackLabels: FeedbackLabelsState
}

export function initialState (): RootInitialState {
  return {
    lastAppInteraction: Date.now(),
    examTypes: {},
    submissionTypes: {},
    submissions: {},
    students: {},
    studentMap: {}, // is used to map obfuscated student data back to the original
    statistics: {
      submissionsPerType: 0,
      submissionsPerStudent: 0,
      currentMeanScore: 0,
      submissionTypeProgress: []
    }
  }
}

export const persistedStateKey = 'grady'

const store = getStoreBuilder<RootState>().vuexStore({
  strict: process.env.NODE_ENV === 'development',
  plugins: [
    createPersistedState({
      key: persistedStateKey,
      storage: window.sessionStorage,
      // Authentication.token is manually saved since using it with this plugin caused issues
      // when manually reloading the page
      paths: Object.keys(initialState()).concat(
        ['UI', 'StudentPage', 'SubmissionNotes', 'FeedbackSearchOptions', 'Subscriptions',
          'TutorOverview',
          'Authentication.user', 'Authentication.jwtTimeDelta',
          'Authentication.tokenCreationTime'])
    }),
    lastInteraction],
  // TODO is there a better way than casting the initialState ?
  state: <RootState> initialState()
})

export default store