import axios from 'axios';
import moment from 'moment';
import content from '@/../../common/script/content/index';
import * as commonConstants from '@/../../common/script/constants';
import { DAY_MAPPING } from '@/../../common/script/cron';
import deepFreeze from '@/libs/deepFreeze';
import Store from '@/libs/store';
import { asyncResourceFactory } from '@/libs/asyncResource';
import { setUpAxios } from '@/libs/auth';

import actions from './actions';
import getters from './getters';

const IS_TEST = process.env.NODE_ENV === 'test'; // eslint-disable-line no-process-env

// Load user auth parameters and determine if it's logged in
// before trying to load data
let isUserLoggedIn = false;

// eg, -240 - this will be converted on server as (offset/60)
const browserTimezoneUtcOffset = moment().utcOffset();

axios.defaults.headers.common['x-client'] = 'habitica-web';

let AUTH_SETTINGS = window.localStorage.getItem('habit-mobile-settings');
if (AUTH_SETTINGS) {
  AUTH_SETTINGS = JSON.parse(AUTH_SETTINGS);
  isUserLoggedIn = setUpAxios(AUTH_SETTINGS);
}

const i18nData = window && window['habitica-i18n'];

let availableLanguages = [];
let selectedLanguage = {};

if (i18nData) {
  availableLanguages = i18nData.availableLanguages;
  selectedLanguage = i18nData.language;
}

// Export a function that generates the store and not the store directly
// so that we can regenerate it multiple times for testing, when not testing
// always export the same route

let existingStore;
export default function clientStore () {
  if (!IS_TEST && existingStore) return existingStore;

  existingStore = new Store({
    actions,
    getters,
    state: {
      serverAppVersion: null,
      title: 'Habitica',
      isUserLoggedIn,
      // Means the user and the user's tasks are ready
      // @TODO use store.user.loaded since it's an async resource?
      isUserLoaded: false,
      isAmazonReady: false, // Whether the Amazon Payments lib can be used
      user: asyncResourceFactory(),
      // Keep track of the ids of notifications that have been removed
      // to make sure they don't get shown again. It happened due to concurrent requests
      // which in some cases could result in a read notification showing up again
      // see https://github.com/HabitRPG/habitica/issues/9242
      notificationsRemoved: [],
      worldState: asyncResourceFactory(),
      credentials: isUserLoggedIn ? {
        API_ID: AUTH_SETTINGS.auth.apiId,
        API_TOKEN: AUTH_SETTINGS.auth.apiToken,
      } : {},
      // store the timezone offset in case it's different than the one in
      // user.preferences.timezoneOffset and change it after the user is synced
      // in app.vue
      browserTimezoneUtcOffset,
      tasks: asyncResourceFactory(), // user tasks
      // @TODO use asyncresource?
      completedTodosStatus: 'NOT_LOADED',
      party: asyncResourceFactory(),
      partyMembers: asyncResourceFactory(),
      shops: {
        market: asyncResourceFactory(),
        quests: asyncResourceFactory(),
        seasonal: asyncResourceFactory(),
        'time-travelers': asyncResourceFactory(),
      },
      myGuilds: [],
      groupFormOptions: {
        creatingParty: false,
        groupId: '',
      },
      avatarEditorOptions: {
        editingUser: false,
        startingPage: '',
        subpage: '',
      },
      challengeOptions: {
        cloning: false,
        tasksToClone: {},
        workingChallenge: {},
      },
      editingGroup: {}, // @TODO move to local state
      // content data, frozen to prevent Vue from modifying it since it's static and never changes
      // @TODO apply freezing to the entire codebase (the server) and not only to the client side?
      // NOTE this takes about 10-15ms on a fast computer
      content: deepFreeze(content),
      constants: deepFreeze({ ...commonConstants, DAY_MAPPING }),
      i18n: deepFreeze({
        availableLanguages,
        selectedLanguage,
      }),
      hideHeader: false,
      memberModalOptions: {
        viewingMembers: [],
        groupId: '',
        challengeId: '',
        group: {},
        loading: false,
      },
      openedItemRows: [],
      spellOptions: {
        castingSpell: false,
        spellDrawOpen: true,
      },
      profileOptions: {
        startingPage: '',
      },
      giftModalOptions: {
        startingPage: '',
      },
      rageModalOptions: {
        npc: '',
      },
      profileUser: {},
      upgradingGroup: {},
      notificationStore: [],
      modalStack: [],
      equipmentDrawerOpen: true,
      groupPlans: asyncResourceFactory(),
      isRunningYesterdailies: false,
      privateMessageOptions: {
        userIdToMessage: '',
        displayName: '',
        username: '',
        backer: {},
        contributor: {},
      },
      firstDropsOptions: {
        egg: '',
        hatchingPotion: '',
      },
      bugReportOptions: {
        question: false,
      },
      postLoadModal: '',
    },
  });

  return existingStore;
}
