import axios from 'axios';
import * as Constants from '../../constants';
import {createAction} from '@reduxjs/toolkit';
import {notifyError} from './error_actions';
import {
  saveState,
  setAllowMount,
  setApplicationReady,
  showWindow
} from './common_actions';
import {
  checkVersionInstalled,
  setDismissDependencies
} from './install_actions';
import {unmountAll} from './mount_actions';
import {
  checkNewReleases,
  getIPCRenderer,
  getNewReleases, getSelectedVersionFromState
} from '../../utils';

export const CLEAR_UI_UPGRADE = 'relver/clearUIUpgrade';
export const clearUIUpgrade = () => {
  return {
    type: CLEAR_UI_UPGRADE,
    payload: null,
  };
};

const cleanupOldReleases = versionList => {
  return dispatch => {
    const ipcRenderer = getIPCRenderer();
    if (ipcRenderer) {
      ipcRenderer.sendSync(Constants.IPC_Cleanup_Releases + '_sync', {
        version_list: versionList
      });
    }
  };
};

export const detectUIUpgrade = () => {
  return (dispatch, getState) => {
    axios
      .get(Constants.UI_RELEASES_URL)
      .then(response => {
        const state = getState();
        const appPlatform = state.common.AppPlatform;
        const version = state.common.Version;
        const data = response.data;

        if (data.Versions &&
          data.Versions[appPlatform] &&
          (data.Versions[appPlatform].length > 0) &&
          (data.Versions[appPlatform][0] !== version)) {
          dispatch(setUIUpgradeData(data.Locations[appPlatform][data.Versions[appPlatform][0]], data.Versions[appPlatform][0]));
          if (!state.relver.UpgradeDismissed) {
            dispatch(showWindow());
          }
        } else {
          dispatch(clearUIUpgrade());
        }
      }).catch(() => {
        dispatch(clearUIUpgrade());
    });
  };
};

export const loadReleases = () => {
  return (dispatch, getState) => {
    const dispatchActions = (locationsLookup, versionLookup)=> {
      const state = getState().relver;
      let release = state.Release;
      if (release >= Constants.RELEASE_TYPES.length) {
        release = state.ReleaseDefault;
      }

      let latestVersion = versionLookup[Constants.RELEASE_TYPES[release]].length - 1;
      let version = state.Version;
      if (versionLookup[Constants.RELEASE_TYPES[release]][0] === 'unavailable') {
        release = state.ReleaseDefault;
        version = latestVersion = versionLookup[Constants.RELEASE_TYPES[release]].length - 1
      } else if ((version === -1) || !versionLookup[Constants.RELEASE_TYPES[release]][version]) {
        version = latestVersion;
      }

      dispatch(setReleaseData(locationsLookup, versionLookup));

      const dispatchActions = (processAllowDismiss = true) => {
        dispatch(setReleaseUpgradeAvailable((version !== latestVersion)));
        dispatch(setApplicationReady(true));
        dispatch(detectUIUpgrade());
        if (processAllowDismiss) {
          dispatch(setAllowDismissDependencies(versionLookup[Constants.RELEASE_TYPES[release]].length > 1));
        }
        dispatch(checkVersionInstalled());

        let versionList = [];
        for (const key of Object.keys(locationsLookup)) {
          versionList.push(key);
        }
        dispatch(cleanupOldReleases(versionList))
      };

      if ((version !== state.Version) || (release !== state.Release)) {
        dispatch(unmountAll(() => {
          dispatch(setActiveRelease(release, version));
          dispatchActions(false);
          dispatch(showWindow());
          dispatch(saveState());
        }));
      } else {
        dispatchActions();
      }
    };

    axios
      .get(Constants.RELEASES_URL)
      .then(response => {
        const appPlatform = getState().common.AppPlatform;
        const versionLookup = {
          Release: response.data.Versions.Release[appPlatform],
          RC: response.data.Versions.RC[appPlatform],
          Beta: response.data.Versions.Beta[appPlatform],
          Alpha: response.data.Versions.Alpha[appPlatform],
        };
        const locationsLookup = {
          ...response.data.Locations[appPlatform],
        };

        const storedReleases = localStorage.getItem('releases');
        let newReleases = [];
        if (storedReleases && (storedReleases.length > 0)) {
          newReleases = getNewReleases(JSON.parse(storedReleases).VersionLookup, versionLookup, getSelectedVersionFromState(getState()));
        }

        localStorage.setItem('releases', JSON.stringify({
          LocationsLookup: locationsLookup,
          VersionLookup: versionLookup
        }));
        dispatchActions(locationsLookup, versionLookup);

        dispatch(setNewReleasesAvailable(newReleases));
        if (getState().relver.NewReleasesAvailable.length > 0) {
          dispatch(setNewReleasesAvailable2(newReleases));
          localStorage.setItem('previous_releases', storedReleases);
          dispatch(showWindow());
        } else if ((newReleases = checkNewReleases(getSelectedVersionFromState(getState()))).length > 0) {
          dispatch(setNewReleasesAvailable2(newReleases));
        }
      }).catch(error => {
        const releases = localStorage.getItem('releases');
        if (releases && (releases.length > 0)) {
          const obj = JSON.parse(releases);
          const locationsLookup = obj.LocationsLookup;
          const versionLookup = obj.VersionLookup;

          dispatchActions(locationsLookup, versionLookup);
        } else {
          dispatch(notifyError(error, true));
        }
      });
  };
};

export const NOTIFY_ACTIVE_RELEASE = 'relver/notifyActiveRelease';
export const notifyActiveRelease = (release, version) => {
  return {
    type: NOTIFY_ACTIVE_RELEASE,
    payload: {
      release: release,
      version: version
    },
  };
};

export const setActiveRelease = (release, version) => {
  return (dispatch, getState) => {
    dispatch(setAllowMount(false));
    const relver = getState().relver;
    const common = getState().common;
    if (release >= Constants.RELEASE_TYPES.length) {
      release = relver.ReleaseDefault;
      version = -1;
    }
    const versions = relver.VersionLookup[Constants.RELEASE_TYPES[release]];
    dispatch(setAllowDismissDependencies(versions && (versions.length > 1)));
    dispatch(setDismissDependencies(false));
    dispatch(notifyActiveRelease(release, version));
    if (common.AppReady) {
      dispatch(checkVersionInstalled());
    }
  };
};

export const setAllowDismissDependencies = createAction('relver/setAllowDismissDependencies');
export const setDismissNewReleasesAvailable = createAction('relver/setDismissNewReleasesAvailable');
export const setDismissUIUpgrade = createAction('relver/setDismissUIUpgrade');
export const setInstalledVersion = createAction('relver/setInstalledVersion');
export const setNewReleasesAvailable = createAction('relver/setNewReleasesAvailable');
export const setNewReleasesAvailable2 = createAction('relver/setNewReleasesAvailable2');

export const SET_RELEASE_DATA = 'relver/setReleaseData';
export const setReleaseData = (locationsLookup, versionLookup)=> {
  return {
    type: SET_RELEASE_DATA,
    payload: {
      locations: locationsLookup,
      versions: versionLookup,
    }
  }
};

export const setReleaseUpgradeAvailable = createAction('relver/setReleaseUpgradeAvailable');

export const SET_UI_UPGRADE_DATA = 'relver/setUIUpgradeData';
export const setUIUpgradeData = (upgradeData, version) => {
  return {
    type: SET_UI_UPGRADE_DATA,
    payload: {
      upgrade_data: upgradeData,
      version: version,
    }
  }
};
