import {createAction} from '@reduxjs/toolkit';

import * as Constants from '../../constants';
import {getIPCRenderer} from '../../utils';

import {confirmYesNo, saveState} from './common_actions';
import {notifyError} from './error_actions';

export const addRemoteMount = (hostNameOrIp, port, token) => {
  return (dispatch, getState) => {
    const ipcRenderer = getIPCRenderer();

    const provider = 'Remote' + hostNameOrIp + ':' + port;
    dispatch(setBusy(true));

    ipcRenderer.once(Constants.IPC_Set_Config_Values_Reply, (_, arg) => {
      if (arg.data.Success) {
        dispatch(addRemoteMount2(provider));
        ipcRenderer.send(Constants.IPC_Detect_Mount, {
          Provider: provider,
          RemoteMounts: getState().mounts.RemoteMounts,
          S3Mounts: getState().mounts.S3Mounts,
          Version: getState().relver.InstalledVersion,
        });
      } else {
        dispatch(
          notifyError('Failed to set \'RemoteToken\': ' + arg.data.Error));
        dispatch(setBusy(false));
      }
    });

    ipcRenderer.send(Constants.IPC_Set_Config_Values, {
      Items: [
        {Name: 'RemoteMount.RemoteHostNameOrIp', Value: hostNameOrIp},
        {Name: 'RemoteMount.RemoteToken', Value: token},
        {Name: 'RemoteMount.RemotePort', Value: port},
        {Name: 'RemoteMount.IsRemoteMount', Value: 'true'},
      ],
      Provider: provider,
      Remote: true,
      Version: getState().relver.InstalledVersion,
    });
  };
};

export const addS3Mount = (name, accessKey, secretKey, region, bucketName, url) => {
  return (dispatch, getState) => {
    const ipcRenderer = getIPCRenderer();

    const provider = 'S3' + name;
    dispatch(setBusy(true));

    ipcRenderer.once(Constants.IPC_Set_Config_Values_Reply, (_, arg) => {
      if (arg.data.Success) {
        dispatch(addS3Mount2(provider));
        ipcRenderer.send(Constants.IPC_Detect_Mount, {
          Provider: provider,
          RemoteMounts: getState().mounts.RemoteMounts,
          S3Mounts: getState().mounts.S3Mounts,
          Version: getState().relver.InstalledVersion,
        });
      } else {
        dispatch(
          notifyError('Failed to create S3 instance: ' + arg.data.Error));
        dispatch(setBusy(false));
      }
    });

    ipcRenderer.send(Constants.IPC_Set_Config_Values, {
      Items: [
        {Name: 'S3Config.AccessKey', Value: accessKey},
        {Name: 'S3Config.SecretKey', Value: secretKey},
        {Name: 'S3Config.Region', Value: region},
        {Name: 'S3Config.BucketName', Value: bucketName},
        {Name: 'S3Config.URL', Value: url},
      ],
      Provider: provider,
      S3: true,
      Version: getState().relver.InstalledVersion,
    });
  };
};

export const addRemoteMount2 = createAction('mounts/addRemoteMount2');
export const addS3Mount2 = createAction('mounts/addS3Mount2');

export const DISPLAY_CONFIGURATION = 'mounts/displayConfiguration';
export const displayConfiguration = (provider, remote, s3) => {
  return {
    type: DISPLAY_CONFIGURATION,
    payload: {
      provider,
      remote,
      s3,
    },
  };
};

export const removeRemoteMount = provider => {
  return dispatch => {
    dispatch(confirmYesNo('Delete [' + provider.substr(6) + ']?'))
    .then(confirmed => {
      if (confirmed) {
        dispatch(removeRemoteMount2(provider));
      }
    });
  };
};

const removeRemoteMount2 = provider => {
  return dispatch => {
    const ipcRenderer = getIPCRenderer();
    ipcRenderer.once(Constants.IPC_Remove_Remote_Mount_Reply, (_, arg) => {
      if (arg.data.Success) {
        dispatch(removeRemoteMount3(provider));
        dispatch(saveState());
      }
    });
    ipcRenderer.send(Constants.IPC_Remove_Remote_Mount, provider.substr(6));
  };
};

export const removeRemoteMount3 = createAction('mounts/removeRemoteMount3');

export const RESET_MOUNTS_STATE = 'mounts/resetMountsState';
export const resetMountsState = () => {
  return {type: RESET_MOUNTS_STATE, payload: null,}
};

export const SET_ALLOW_MOUNT = 'mounts/setAllowMount';
export const setAllowMount =
  (provider,
   allow) => {
    return {type: SET_ALLOW_MOUNT, payload: {provider, allow}};
  };

export const SET_AUTO_MOUNT_PROCESSED = 'mounts/setAutoMountProcessed';
export const setAutoMountProcessed = (provider, processed) => {
  return {type: SET_AUTO_MOUNT_PROCESSED, payload: {provider, processed}};
};

export const setBusy = createAction('mounts/setBusy');

export const SET_MOUNT_STATE = 'mounts/setMountState';
export const setMountState =
  (provider,
   state) => {
    return {type: SET_MOUNT_STATE, payload: {provider, state}};
  };

export const SET_MOUNTED = 'mounts/setMounted';
export const setMounted =
  (provider,
   mounted) => {
    return {type: SET_MOUNTED, payload: {provider, mounted}};
  };

export const SET_PROVIDER_STATE = 'mounts/setProviderState';
export const setProviderState = (provider, state) => {
  return {type: SET_PROVIDER_STATE, payload: {provider, state}}
};

export const unmountAll = completedCallback => {
  return dispatch => {
    const ipcRenderer = getIPCRenderer();
    const unmountedCallback = () => {
      dispatch(resetMountsState());
      completedCallback();
    };
    ipcRenderer.once(Constants.IPC_Unmount_All_Drives_Reply, unmountedCallback);
    ipcRenderer.send(Constants.IPC_Unmount_All_Drives);
  }
};
