import Cookies from 'js-cookie'
import { setPreset, applyTheme } from '../services/style_setter/style_setter.js'
import messages from '../i18n/messages'
import localeService from '../services/locale/locale.service.js'

const BACKEND_LANGUAGE_COOKIE_NAME = 'userLanguage'

const browserLocale = (window.navigator.language || 'en').split('-')[0]

/* TODO this is a bit messy.
 * We need to declare settings with their types and also deal with
 * instance-default settings in some way, hopefully try to avoid copy-pasta
 * in general.
 */
export const multiChoiceProperties = [
  'postContentType',
  'subjectLineBehavior',
  'conversationDisplay', // tree | linear
  'conversationOtherRepliesButton', // below | inside
  'mentionLinkDisplay' // short | full_for_remote | full
]

export const defaultState = {
  profile: 'default',
  profileVersion: 0,
  expertLevel: 0, // used to track which settings to show and hide
  colors: {},
  theme: undefined,
  customTheme: undefined,
  customThemeSource: undefined,
  hideISP: false,
  hideInstanceWallpaper: false,
  // bad name: actually hides posts of muted USERS
  hideMutedPosts: undefined, // instance default
  hideMutedThreads: undefined, // instance default
  hideThreadsWithBlockedUsers: undefined, // instance default
  hideWordFilteredPosts: undefined, // instance default
  muteBotStatuses: undefined, // instance default
  collapseMessageWithSubject: true, // instance default
  padEmoji: true,
  showNavShortcuts: undefined, // instance default
  showPanelNavShortcuts: undefined, // instance default
  showWiderShortcuts: undefined, // instance default
  hideSiteFavicon: undefined, // instance default
  hideSiteName: undefined, // instance default
  hideAttachments: false,
  hideAttachmentsInConv: false,
  maxThumbnails: 16,
  hideNsfw: true,
  preloadImage: true,
  loopVideo: true,
  loopVideoSilentOnly: true,
  streaming: false,
  emojiReactionsOnTimeline: true,
  alwaysShowNewPostButton: false,
  autohideFloatingPostButton: false,
  pauseOnUnfocused: true,
  stopGifs: true,
  replyVisibility: 'all',
  thirdColumnMode: 'notifications',
  notificationVisibility: {
    follows: true,
    mentions: true,
    likes: true,
    repeats: true,
    moves: true,
    emojiReactions: true,
    followRequest: true,
    polls: true
  },
  webPushNotifications: false,
  webPushHideIfCW: true,
  muteWords: [],
  highlight: {},
  interfaceLanguage: browserLocale,
  hideScopeNotice: false,
  useStreamingApi: false,
  sidebarRight: undefined, // instance default
  scopeCopy: undefined, // instance default
  subjectLineBehavior: undefined, // instance default
  alwaysShowSubjectInput: undefined, // instance default
  postContentType: undefined, // instance default
  minimalScopesMode: undefined, // instance default
  // This hides statuses filtered via a word filter
  hideFilteredStatuses: undefined, // instance default
  modalOnRepeat: undefined, // instance default
  modalOnUnfollow: undefined, // instance default
  modalOnBlock: undefined, // instance default
  modalOnMute: undefined, // instance default
  modalOnDelete: undefined, // instance default
  modalOnLogout: undefined, // instance default
  modalOnApproveFollow: undefined, // instance default
  modalOnDenyFollow: undefined, // instance default
  playVideosInModal: false,
  useOneClickNsfw: false,
  useContainFit: true,
  disableStickyHeaders: false,
  showScrollbars: false,
  greentext: undefined, // instance default
  useAtIcon: undefined, // instance default
  mentionLinkDisplay: undefined, // instance default
  mentionLinkShowTooltip: undefined, // instance default
  mentionLinkShowAvatar: undefined, // instance default
  mentionLinkFadeDomain: undefined, // instance default
  mentionLinkShowYous: undefined, // instance default
  mentionLinkBoldenYou: undefined, // instance default
  hidePostStats: undefined, // instance default
  hideBotIndication: undefined, // instance default
  hideUserStats: undefined, // instance default
  virtualScrolling: undefined, // instance default
  sensitiveByDefault: undefined, // instance default
  sensitiveIfSubject: undefined,
  renderMisskeyMarkdown: undefined,
  renderMfmOnHover: undefined, // instance default
  conversationDisplay: undefined, // instance default
  conversationTreeAdvanced: undefined, // instance default
  conversationOtherRepliesButton: undefined, // instance default
  conversationTreeFadeAncestors: undefined, // instance default
  maxDepthInThread: undefined, // instance default
  translationLanguage: undefined, // instance default,
  supportedTranslationLanguages: {}, // instance default
  userProfileDefaultTab: 'statuses'
}

// caching the instance default properties
export const instanceDefaultProperties = Object.entries(defaultState)
  .filter(([key, value]) => value === undefined)
  .map(([key, value]) => key)

const config = {
  state: { ...defaultState },
  getters: {
    defaultConfig (state, getters, rootState, rootGetters) {
      const { instance } = rootState
      return {
        ...defaultState,
        ...Object.fromEntries(
          instanceDefaultProperties.map(key => [key, instance[key]])
        )
      }
    },
    mergedConfig (state, getters, rootState, rootGetters) {
      const { defaultConfig } = rootGetters
      return {
        ...defaultConfig,
        // Do not override with undefined
        ...Object.fromEntries(Object.entries(state).filter(([k, v]) => v !== undefined))
      }
    }
  },
  mutations: {
    setOption (state, { name, value }) {
      state[name] = value
    },
    setHighlight (state, { user, color, type }) {
      const data = this.state.config.highlight[user]
      if (color || type) {
        state.highlight[user] = { color: color || data.color, type: type || data.type }
      } else {
        delete state.highlight[user]
      }
    }
  },
  actions: {
    syncSettings: (store) => {
      store.commit('setOption', { name: 'profileVersion', value: store.state.profileVersion + 1 })
      const notice = {
        level: 'info',
        messageKey: 'settings_profile.synchronizing',
        messageArgs: { profile: store.state.profile },
        timeout: 5000
      }
      store.dispatch('pushGlobalNotice', notice)
      store.rootState.api.backendInteractor.saveSettingsProfile({
        settings: store.state, profileName: store.state.profile, version: store.state.profileVersion
      }).then(() => {
        store.dispatch('removeGlobalNotice', notice)
        store.dispatch('pushGlobalNotice', {
          level: 'success',
          messageKey: 'settings_profile.synchronized',
          messageArgs: { profile: store.state.profile },
          timeout: 2000
        })
        store.dispatch('listSettingsProfiles')
      }).catch((err) => {
        store.dispatch('removeGlobalNotice', notice)
        store.dispatch('pushGlobalNotice', {
          level: 'error',
          messageKey: 'settings_profile.synchronization_error',
          messageArgs: { error: err.message },
          timeout: 5000
        })
        console.error(err)
      })
    },
    deleteSettingsProfile (store, name) {
      store.rootState.api.backendInteractor.deleteSettingsProfile({ profileName: name }).then(() => {
        store.dispatch('listSettingsProfiles')
      })
    },
    loadSettings ({ dispatch }, data) {
      const knownKeys = new Set(Object.keys(defaultState))
      const presentKeys = new Set(Object.keys(data))
      const intersection = new Set()
      for (let elem of presentKeys) {
        if (knownKeys.has(elem)) {
          intersection.add(elem)
        }
      }

      intersection.forEach(
        name => dispatch('setOption', { name, value: data[name] })
      )
    },
    setHighlight ({ commit, dispatch }, { user, color, type }) {
      commit('setHighlight', { user, color, type })
    },
    setOption ({ commit, dispatch }, { name, value, manual }) {
      commit('setOption', { name, value })
      if (manual === true) {
        dispatch('syncSettings')
      }
      switch (name) {
        case 'theme':
          setPreset(value)
          break
        case 'customTheme':
        case 'customThemeSource':
          applyTheme(value)
          break
        case 'interfaceLanguage':
          messages.setLanguage(this.getters.i18n, value)
          Cookies.set(BACKEND_LANGUAGE_COOKIE_NAME, localeService.internalToBackendLocale(value))
          dispatch('setInstanceOption', { name: 'interfaceLanguage', value })
          break
        case 'thirdColumnMode':
          dispatch('setLayoutWidth', undefined)
          break
      }
    },
    getSettingsProfile (store, forceUpdate = false) {
      const profile = store.state.profile
      store.rootState.api.backendInteractor.getSettingsProfile({ store, profileName: profile })
        .then(({ settings, version }) => {
          console.log('found settings version', version)
          if (forceUpdate || (version > store.state.profileVersion)) {
            store.commit('setOption', { name: 'profileVersion', value: version })
            Object.entries(settings).forEach(([name, value]) => {
              if (store.state[name] !== value) {
                store.dispatch('setOption', { name, value })
              }
            })
          } else {
            console.log('settings are up to date')
          }
        })
        .catch((err) => {
          console.error(`could not fetch profile ${profile}`, err)
          if (err.statusCode === 404) {
            // create profile
            store.dispatch('pushGlobalNotice', {
              level: 'warning',
              messageKey: 'settings_profile.creating',
              messageArgs: { profile },
              timeout: 5000
            })
            store.dispatch('syncSettings')
          }
        })
    }
  }
}

export default config