import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import isNil from '../../../node_modules/lodash-es/isNil.js';
import _merge from '../../../node_modules/lodash-es/merge.js';
import 'core-js/modules/es.array.filter.js';
import 'core-js/modules/es.symbol.js';
import 'core-js/modules/es.array.find.js';
import 'core-js/modules/es.array.find-index.js';
import 'core-js/modules/es.array.map.js';
import 'core-js/modules/es.object.get-own-property-descriptor.js';
import 'core-js/modules/es.object.get-own-property-descriptors.js';
import 'core-js/modules/es.object.get-own-property-names.js';
import 'core-js/modules/es.object.keys.js';
import 'core-js/modules/es.object.to-string.js';
import 'core-js/modules/web.dom-collections.for-each.js';
import * as React from 'react';
import update from 'immutability-helper';
import PropTypes from 'prop-types';
import { HotspotPropTypes } from '../../../constants/SharedPropTypes.js';

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var hotspotTypes = {
  FIXED: 'fixed',
  DYNAMIC: 'dynamic',
  TEXT: 'text'
};
var hotspotStateProptypes = {
  /** The current thresholds from a card configuration object */
  thresholds: PropTypes.arrayOf(PropTypes.object),
  /** All the curren hotspots, including dynamic demo hotspots */
  hotspots: PropTypes.arrayOf(HotspotPropTypes),
  /** The type of hotspot that is currently being shown by the context switcher */
  currentType: PropTypes.oneOf([hotspotTypes.FIXED, hotspotTypes.DYNAMIC, hotspotTypes.TEXT]),
  /** The currently selected hotspot */
  selectedHotspot: HotspotPropTypes,
  /** The data item containing the x source of the dynammic hotspot */
  dynamicHotspotSourceX: PropTypes.shape({
    dataSourceId: PropTypes.string
  }),
  /** The data item containing the y source of the dynammic hotspot */
  dynamicHotspotSourceY: PropTypes.shape({
    dataSourceId: PropTypes.string
  }),
  /** Loading flag for dynamic hotspots */
  dynamicHotspotsLoading: PropTypes.bool
};
var hotspotActionTypes = {
  hotspotDataSourceChange: 'HOTSPOT_DATA_SOURCE_CHANGE',
  hotspotDataSourceSettingsChange: 'HOTSPOT_DATA_SOURCE_SETTINGS_CHANGE',
  hotspotTooltipChange: 'HOTSPOT_TOOLTIP_CHANGE',
  hotspotPositionChange: 'HOTSPOT_POSITION_CHANGE',
  hotspotSelect: 'HOTSPOT_SELECT',
  hotspotsAdd: 'HOTSPOTS_ADD',
  textHotspotStyleChange: 'TEXT_HOTSPOT_STYLE_CHANGE',
  textHotspotContentChange: 'TEXT_HOTSPOT_CONTENT_CHANGE',
  currentTypeSwitch: 'CURRENT_TYPE_SWITCH',
  selectedHotspotDelete: 'SELECTED_HOTSPOT_DELETE',
  dynamicHotspotSourceClear: 'DYNAMIC_HOTSPOT_SOURCE_CLEAR',
  dynamicHotspotSourceXChange: 'DYNAMIC_HOTSPOT_SOURCE_X_CHANGE',
  dynamicHotspotSourceYChange: 'DYNAMIC_HOTSPOT_SOURCE_Y_CHANGE',
  dynamicHotspotsLoadingChange: 'DYNAMIC_HOTSPOTS_LOADING_CHANGE',
  dynamicHotspotsSet: 'DYNAMIC_HOTSPOTS_SET'
};
var isHotspotMatch = function isHotspotMatch(hotspot, position) {
  return hotspot.x === position.x && hotspot.y === position.y;
};
var getSelectedIndex = function getSelectedIndex(state) {
  return state.hotspots.findIndex(function (hotspot) {
    return isHotspotMatch(hotspot, state.selectedHotspot);
  });
};
var getDynamicHotspotsUpdateFunction = function getDynamicHotspotsUpdateFunction(mergeSpec) {
  return function (arr) {
    return arr.map(function (hotspot) {
      return hotspot.type === hotspotTypes.DYNAMIC ? update(hotspot, mergeSpec) : hotspot;
    });
  };
};

/**
 * Returns an updated state for hotspot updates. It will update both the
 * selectedHotspot and the hotspots collection.
 */
var getHotspotUpdate = function getHotspotUpdate(state, mergeSpec) {
  var isMultiHotspotUpdate = state.selectedHotspot.type === hotspotTypes.DYNAMIC;
  var modifiedHotspot = update(state.selectedHotspot, mergeSpec);
  var collectionUpdateSpec = isMultiHotspotUpdate ? getDynamicHotspotsUpdateFunction(mergeSpec) : _defineProperty({}, getSelectedIndex(state), {
    $set: modifiedHotspot
  });
  return update(state, {
    hotspots: collectionUpdateSpec,
    selectedHotspot: {
      $set: modifiedHotspot
    }
  });
};

/**
 * hotspotEditorReducer
 * @param {hotspotStateProptypes} state
 * @param {*} action
 */
function hotspotEditorReducer(state, _ref2) {
  var type = _ref2.type,
    payload = _ref2.payload;
  switch (type) {
    // HOTSPOT DATA SOURCE CHANGE
    case hotspotActionTypes.hotspotDataSourceChange:
      {
        return getHotspotUpdate(state, {
          content: {
            attributes: {
              $set: payload.attributes
            }
          }
        });
      }
    // HOTSPOT DATA SOURCE SETTINGS CHANGE
    case hotspotActionTypes.hotspotDataSourceSettingsChange:
      {
        var _state$selectedHotspo, _state$selectedHotspo2;
        var attributeIndex = (_state$selectedHotspo = (_state$selectedHotspo2 = state.selectedHotspot.content) === null || _state$selectedHotspo2 === void 0 || (_state$selectedHotspo2 = _state$selectedHotspo2.attributes) === null || _state$selectedHotspo2 === void 0 ? void 0 : _state$selectedHotspo2.findIndex(function (attr) {
          return attr.dataSourceId === payload.dataSourceId;
        })) !== null && _state$selectedHotspo !== void 0 ? _state$selectedHotspo : 0;
        var mergeSpec = {
          content: {
            attributes: _defineProperty({}, attributeIndex, {
              $merge: {
                dataItemId: payload.dataItemId,
                aggregationMethod: payload.aggregationMethod,
                label: payload.label,
                unit: payload.unit,
                dataFilter: payload.dataFilter,
                thresholds: payload.thresholds,
                precision: payload.precision
              }
            })
          }
        };
        return getHotspotUpdate(state, mergeSpec);
      }
    // HOTSPOT TOOLTIP CHANGE
    case hotspotActionTypes.hotspotTooltipChange:
      {
        var _mergeSpec = payload.content ? {
          content: {
            $merge: payload.content
          }
        } : {
          $merge: payload
        };
        return getHotspotUpdate(state, _mergeSpec);
      }
    // HOTSPOT POSITION CHANGE
    case hotspotActionTypes.hotspotPositionChange:
      {
        var isPositionAvailable = !state.hotspots.find(function (hotspot) {
          return isHotspotMatch(hotspot, payload.position);
        });
        if (isPositionAvailable) {
          // Find the updated hotspot in the new hotspots array to maintain selection
          var updatedSelectedHotspot = payload.newHotspots.find(function (hotspot) {
            return isHotspotMatch(hotspot, payload.position);
          });
          return update(state, {
            hotspots: {
              $set: payload.newHotspots
            },
            selectedHotspot: {
              $set: updatedSelectedHotspot
            }
          });
        }
        return state;
      }
    // HOTSPOTS ADD
    case hotspotActionTypes.hotspotsAdd:
      {
        var _isPositionAvailable = !state.hotspots.find(function (hotspot) {
          return isHotspotMatch(hotspot, payload.position);
        });
        var defaultContent = state.currentType === hotspotTypes.TEXT ? {
          title: ''
        } : {};
        var createableType = state.currentType === hotspotTypes.DYNAMIC ? hotspotTypes.FIXED : state.currentType;
        var newHotspot = _objectSpread(_objectSpread(_objectSpread({}, payload.hotspotDefaults), payload.position), {}, {
          content: defaultContent,
          type: createableType
        });
        return _isPositionAvailable ? update(state, {
          selectedHotspot: {
            $set: newHotspot
          },
          hotspots: {
            $push: [newHotspot]
          }
        }) : state;
      }
    // HOTSPOT SELECT
    case hotspotActionTypes.hotspotSelect:
      {
        var _hotspot$type;
        var x = payload.x,
          y = payload.y;
        var hotspotIndex = state.hotspots.findIndex(function (hotspot) {
          return isHotspotMatch(hotspot, {
            x: x,
            y: y
          });
        });
        var hotspot = state.hotspots[hotspotIndex];
        var defaultTypeWhenMissing = hotspotTypes.FIXED;
        return update(state, {
          selectedHotspot: {
            $set: hotspot
          },
          currentType: {
            $set: (_hotspot$type = hotspot === null || hotspot === void 0 ? void 0 : hotspot.type) !== null && _hotspot$type !== void 0 ? _hotspot$type : defaultTypeWhenMissing
          }
        });
      }
    // TEXT HOTSPOT STYLE CHANGE
    case hotspotActionTypes.textHotspotStyleChange:
      {
        var styleKey = Object.getOwnPropertyNames(payload)[0];
        var updateSpec = isNil(payload[styleKey]) ? {
          $unset: [styleKey]
        } : {
          $merge: payload
        };
        var modifiedHotspot = update(state.selectedHotspot, updateSpec);
        return update(state, {
          selectedHotspot: {
            $set: modifiedHotspot
          },
          hotspots: _defineProperty({}, getSelectedIndex(state), {
            $set: modifiedHotspot
          })
        });
      }
    // CURRENT TYPE SWITCH
    case hotspotActionTypes.currentTypeSwitch:
      {
        return update(state, {
          currentType: {
            $set: payload
          },
          $unset: ['selectedHotspot']
        });
      }
    // SELECTED HOTSPOT DELETE
    case hotspotActionTypes.selectedHotspotDelete:
      {
        return update(state, {
          hotspots: {
            $splice: [[getSelectedIndex(state), 1]]
          },
          $unset: ['selectedHotspot']
        });
      }
    // TEXT HOTSPOT CONTENT CHANGE
    case hotspotActionTypes.textHotspotContentChange:
      {
        var _modifiedHotspot = update(state.selectedHotspot, {
          content: {
            $merge: payload
          }
        });
        return update(state, {
          selectedHotspot: {
            $set: _modifiedHotspot
          },
          hotspots: _defineProperty({}, getSelectedIndex(state), {
            $set: _modifiedHotspot
          })
        });
      }

    // DYNAMIC HOTSPOT SOURCE X CHANGE
    case hotspotActionTypes.dynamicHotspotSourceXChange:
      {
        return update(state, {
          $unset: ['selectedHotspot'],
          dynamicHotspotSourceX: {
            $set: payload
          }
        });
      }

    // DYNAMIC HOTSPOT SOURCE Y CHANGE
    case hotspotActionTypes.dynamicHotspotSourceYChange:
      {
        return update(state, {
          $unset: ['selectedHotspot'],
          dynamicHotspotSourceY: {
            $set: payload
          }
        });
      }

    // DYNAMIC HOTSPOTS LOADING CHANGE
    case hotspotActionTypes.dynamicHotspotsLoadingChange:
      {
        return update(state, {
          dynamicHotspotsLoading: {
            $set: payload
          }
        });
      }

    // DYNAMIC HOTSPOTS SET, this clears the previous dynamic hotspots but leaves the static ones
    case hotspotActionTypes.dynamicHotspotsSet:
      {
        var stateWithoutDynamicHotspots = update(state, {
          hotspots: function hotspots(arr) {
            return arr.filter(function (hotspot) {
              return hotspot.type !== hotspotTypes.DYNAMIC;
            });
          }
        });
        return update(stateWithoutDynamicHotspots, {
          hotspots: {
            $push: payload
          }
        });
      }

    // DYNAMIC HOTSPOT SOURCE CLEAR
    case hotspotActionTypes.dynamicHotspotSourceClear:
      {
        return update(state, {
          hotspots: function hotspots(arr) {
            return arr.filter(function (hotspot) {
              return hotspot.type !== hotspotTypes.DYNAMIC;
            });
          },
          $unset: ['selectedHotspot', 'dynamicHotspotSourceX', 'dynamicHotspotSourceY']
        });
      }
    default:
      {
        throw new Error("Unhandled type: ".concat(type));
      }
  }
}

/**
 * The HotspotEditorModal's custom state manager hook that allows for inversion of control
 * by accepting a custom the reducer, which can be based on the exported default hotspotEditorReducer.
 * @param {Object} Configuration with 'reducer' and 'initialState'
 */
function useHotspotEditorState() {
  var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
    _ref3$reducer = _ref3.reducer,
    reducer = _ref3$reducer === void 0 ? hotspotEditorReducer : _ref3$reducer,
    _ref3$initialState = _ref3.initialState,
    initialState = _ref3$initialState === void 0 ? {} : _ref3$initialState;
  var defaultState = {
    hotspots: [],
    currentType: hotspotTypes.FIXED,
    selectedHotspot: undefined,
    dynamicHotspotSourceX: undefined,
    dynamicHotspotSourceY: undefined,
    dynamicHotspotsLoading: false
  };
  var mergedInitialState = _merge({}, defaultState, initialState);
  var _React$useReducer = React.useReducer(reducer, mergedInitialState),
    _React$useReducer2 = _slicedToArray(_React$useReducer, 2),
    _React$useReducer2$ = _React$useReducer2[0],
    hotspots = _React$useReducer2$.hotspots,
    selectedHotspot = _React$useReducer2$.selectedHotspot,
    currentType = _React$useReducer2$.currentType,
    thresholds = _React$useReducer2$.thresholds,
    dynamicHotspotsLoading = _React$useReducer2$.dynamicHotspotsLoading,
    dynamicHotspotSourceX = _React$useReducer2$.dynamicHotspotSourceX,
    dynamicHotspotSourceY = _React$useReducer2$.dynamicHotspotSourceY,
    dispatch = _React$useReducer2[1];
  var addHotspot = function addHotspot(hotspotCoordinates) {
    return dispatch({
      type: hotspotActionTypes.hotspotsAdd,
      payload: hotspotCoordinates
    });
  };
  var deleteSelectedHotspot = function deleteSelectedHotspot() {
    dispatch({
      type: hotspotActionTypes.selectedHotspotDelete
    });
  };

  /** update the hotspot data items for instance renaming or adding thresholds to a data item */
  var updateHotspotDataSource = function updateHotspotDataSource(dataSourceChange) {
    if (dataSourceChange.attributes) {
      dispatch({
        type: hotspotActionTypes.hotspotDataSourceChange,
        payload: dataSourceChange
      });
    } else {
      dispatch({
        type: hotspotActionTypes.hotspotDataSourceSettingsChange,
        payload: dataSourceChange
      });
    }
  };

  /**
   * Update the properties of the tooltip like 'title', 'description', 'icon', or 'color'
   * TODO: the title and description are under the content section so the `hotspotContent` argument needs to put those title and description updates
   * under a content key.  We should really just do that in the reducer ideally
   *
   */
  var updateHotspotTooltip = function updateHotspotTooltip(hotspotContent) {
    return dispatch({
      type: hotspotActionTypes.hotspotTooltipChange,
      payload: hotspotContent
    });
  };
  var updateHotspotPosition = function updateHotspotPosition(hotspotPosition) {
    return dispatch({
      type: hotspotActionTypes.hotspotPositionChange,
      payload: hotspotPosition
    });
  };

  /** Updates the properties of the text hotspot, passes a payload like {color: 'blue'} */
  var updateTextHotspotStyle = function updateTextHotspotStyle(textHotspotStyle) {
    return dispatch({
      type: hotspotActionTypes.textHotspotStyleChange,
      payload: textHotspotStyle
    });
  };

  /**
   * User clicks on the hotspot and this should change the selection
   * @param {*} hotspotPosition
   */
  var setSelectedHotspot = function setSelectedHotspot(hotspotPosition) {
    return dispatch({
      type: hotspotActionTypes.hotspotSelect,
      payload: hotspotPosition
    });
  };
  var switchCurrentType = function switchCurrentType(contentName) {
    return dispatch({
      type: hotspotActionTypes.currentTypeSwitch,
      payload: contentName
    });
  };

  /**
   *
   * @param {object} contentChange an example to update the title would be {title: 'my new title'}
   */
  var updateTextHotspotContent = function updateTextHotspotContent(contentChange) {
    return dispatch({
      type: hotspotActionTypes.textHotspotContentChange,
      payload: contentChange
    });
  };
  var updateDynamicHotspotSourceX = function updateDynamicHotspotSourceX(sourceId) {
    return dispatch({
      type: hotspotActionTypes.dynamicHotspotSourceXChange,
      payload: sourceId
    });
  };
  var updateDynamicHotspotSourceY = function updateDynamicHotspotSourceY(sourceId) {
    return dispatch({
      type: hotspotActionTypes.dynamicHotspotSourceYChange,
      payload: sourceId
    });
  };
  var setLoadingDynamicHotspots = function setLoadingDynamicHotspots(isLoading) {
    return dispatch({
      type: hotspotActionTypes.dynamicHotspotsLoadingChange,
      payload: isLoading
    });
  };

  /**
   * the assumption here is that demo hotspots are loaded to show in the image carrd
   * @param {*} dynamicHotspots
   */
  var setDynamicHotspots = function setDynamicHotspots(dynamicHotspots) {
    return dispatch({
      type: hotspotActionTypes.dynamicHotspotsSet,
      payload: dynamicHotspots
    });
  };
  var clearDynamicHotspotsSource = function clearDynamicHotspotsSource() {
    return dispatch({
      type: hotspotActionTypes.dynamicHotspotSourceClear
    });
  };
  return {
    currentType: currentType,
    hotspots: hotspots,
    selectedHotspot: selectedHotspot,
    thresholds: thresholds,
    dynamicHotspotsLoading: dynamicHotspotsLoading,
    dynamicHotspotSourceX: dynamicHotspotSourceX,
    dynamicHotspotSourceY: dynamicHotspotSourceY,
    addHotspot: addHotspot,
    deleteSelectedHotspot: deleteSelectedHotspot,
    clearDynamicHotspotsSource: clearDynamicHotspotsSource,
    setSelectedHotspot: setSelectedHotspot,
    setLoadingDynamicHotspots: setLoadingDynamicHotspots,
    setDynamicHotspots: setDynamicHotspots,
    switchCurrentType: switchCurrentType,
    updateHotspotDataSource: updateHotspotDataSource,
    updateHotspotTooltip: updateHotspotTooltip,
    updateHotspotPosition: updateHotspotPosition,
    updateTextHotspotStyle: updateTextHotspotStyle,
    updateTextHotspotContent: updateTextHotspotContent,
    updateDynamicHotspotSourceX: updateDynamicHotspotSourceX,
    updateDynamicHotspotSourceY: updateDynamicHotspotSourceY
  };
}
useHotspotEditorState.prototypes = {
  configuration: PropTypes.shape({
    reducer: PropTypes.func,
    initialState: hotspotStateProptypes
  })
};

export { hotspotActionTypes, hotspotEditorReducer, hotspotTypes, useHotspotEditorState };
