"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.baseHandler = baseHandler;
exports.calculationHandler = calculationHandler;
exports.configurationHandler = configurationHandler;
exports.configurationModifierHandler = configurationModifierHandler;
exports.dataHandler = dataHandler;
exports["default"] = configuratorReducer;
exports.filterOptionclassifications = filterOptionclassifications;
exports.optionAndOptionclassificationHandler = optionAndOptionclassificationHandler;
exports.setSubReducers = exports.setStateChangeReducers = void 0;
exports.uiHandler = uiHandler;
var actionTypes = _interopRequireWildcard(require("./Actions"));
var _get = _interopRequireDefault(require("lodash/get"));
var _isObject = _interopRequireDefault(require("lodash/isObject"));
var _mergeWith = _interopRequireDefault(require("lodash/mergeWith"));
var _merge = _interopRequireDefault(require("lodash/merge"));
var _filter = _interopRequireDefault(require("lodash/filter"));
var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
var _isArray = _interopRequireDefault(require("lodash/isArray"));
var _find = _interopRequireDefault(require("lodash/find"));
var _findIndex = _interopRequireDefault(require("lodash/findIndex"));
var _omit = _interopRequireDefault(require("lodash/omit"));
var _forEach = _interopRequireDefault(require("lodash/forEach"));
var _reduce = _interopRequireDefault(require("lodash/reduce"));
var _set = _interopRequireDefault(require("../../../Utils/Immutable/set"));
var _Reducer = require("../DesignData/Reducer");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
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; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
var initialState = {
  configuration: {
    item: {},
    optionclassifications: []
  },
  options: [],
  optionsWithDetails: [],
  selectedoptionclassification: {},
  calculation: {},
  calculationAutoResolve: true,
  optiondetails: {},
  validation: null,
  configurationvariants: [],
  codesnippets: [],
  client: null,
  inspirations: {},
  profile: {},
  loadCode: null,
  loadIdentifier: null,
  resetCode: null,
  // this code is only set at initial loading and load by code - we reset to those configurations
  stockInformationOption: null,
  inspirationsIdentifier: null,
  calculationIsEnabled: true,
  checkedOptionclassifications: {},
  filteredOptionclassifications: [],
  selectedVariantIdentifier: null,
  selectedAmountsUpdated: false,
  optionInputTexts: []
};
function configurationHandler(state, action) {
  switch (action.type) {
    case actionTypes.RECEIVE_CONFIGURATION:
      {
        var configuration = action.data;
        if (!(0, _isObject["default"])(configuration)) {
          throw new Error("Server side error! The configuration must be a JSON structure! Data: ".concat(configuration));
        }

        // update the selected option classification
        var selectedoptionclassification = state.selectedoptionclassification;
        if (selectedoptionclassification.identifier) {
          selectedoptionclassification = (0, _find["default"])(configuration.optionclassifications, {
            identifier: selectedoptionclassification.identifier
          }) || selectedoptionclassification;
        }

        // set validation from the received configuration
        var validation = (0, _get["default"])(configuration, 'information.validation_result');
        return _objectSpread(_objectSpread({}, state), {}, {
          selectedoptionclassification: selectedoptionclassification,
          configuration: configuration,
          validation: validation,
          resetCode: configuration.code,
          inspirationsIdentifier: configuration.item.identifier,
          checkedOptionclassifications: {}
        });
      }
    case actionTypes.RECEIVE_SWITCHOPTIONSRESULT:
      {
        var _configuration = action.data;

        // the selectedoptionclassification should be updated with the optionclassification data from the response
        // eg. to keep the selectedoptions updated
        var _selectedoptionclassification = state.selectedoptionclassification,
          options = state.options;
        var optionclassifications = _configuration.optionclassifications;
        if (_selectedoptionclassification.identifier) {
          var optionclassificationData = (0, _find["default"])(optionclassifications, {
            identifier: _selectedoptionclassification.identifier
          });
          if (optionclassificationData) {
            _selectedoptionclassification = optionclassificationData;

            // the options should be updated with the data from the selectedoptions
            var _selectedoptionclassi = _selectedoptionclassification,
              selectedoptions = _selectedoptionclassi.selectedoptions;
            for (var soi in selectedoptions) {
              for (var oi in options) {
                if (selectedoptions[soi].identifier === options[oi].identifier) {
                  options[oi] = (0, _mergeWith["default"])(options[oi],
                  // dst
                  selectedoptions[soi],
                  // src
                  function (dstValue, srcValue) {
                    // if the value present in the src, then copy it from there
                    // selectedoption always rules
                    if (srcValue !== null && srcValue !== undefined) {
                      return srcValue;
                    }
                    return dstValue;
                  });
                }
              }
            }
          }
        }
        var optionsWithDetails = filterOptionsWithDetails(options);
        return _objectSpread(_objectSpread({}, state), {}, {
          configuration: _configuration,
          options: options,
          optionsWithDetails: optionsWithDetails,
          selectedoptionclassification: _selectedoptionclassification
        });
      }
    case actionTypes.RECEIVE_SAVEDCONFIGURATION:
      {
        var _configuration2 = action.data;

        // update the selected option classification
        var _selectedoptionclassification2 = state.selectedoptionclassification;
        if (_selectedoptionclassification2.identifier) {
          _selectedoptionclassification2 = (0, _find["default"])(_configuration2.optionclassifications, {
            identifier: _selectedoptionclassification2.identifier
          }) || _selectedoptionclassification2;
        }
        return _objectSpread(_objectSpread({}, state), {}, {
          configuration: _configuration2,
          selectedoptionclassification: _selectedoptionclassification2
        });
      }
    default:
      return state;
  }
}
function optionAndOptionclassificationHandler(state, action) {
  switch (action.type) {
    case actionTypes.SELECT_OPTIONCLASSIFICATION:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          selectedoptionclassification: action.optionclassification || {},
          options: [],
          // clear options
          optionsWithDetails: []
        });
      }
    case actionTypes.RECEIVE_OPTIONS:
      {
        var options = (0, _cloneDeep["default"])(action.data);

        // the selected options of the selected optionclassification should be updated
        // eg. after the switchoption call added a partial object (it contains only the identifier and amount)
        // but only missing values are updated
        var keepDstProps = ['amount'];
        var selectedoptionclassification = (0, _cloneDeep["default"])(state.selectedoptionclassification);
        for (var oi in options) {
          var option = options[oi];
          var _selectedoptions = selectedoptionclassification.selectedoptions;
          for (var os in _selectedoptions) {
            var selectedoption = _selectedoptions[os];
            if (selectedoption.identifier === option.identifier) {
              options[oi] = _selectedoptions[os] = (0, _mergeWith["default"])(_selectedoptions[os],
              // dst
              option,
              // src
              function (dstValue, srcValue, key) {
                // update only when there is a real value in the source, otherwise use the original
                if (keepDstProps.indexOf(key) === -1 && srcValue !== null && srcValue !== undefined) {
                  return srcValue;
                }
                return dstValue;
              });
            }
          }
        }
        var selectedoptions = selectedoptionclassification.selectedoptions;

        // update the option data with the selected group item
        for (var _os in selectedoptions) {
          var _selectedoption = selectedoptions[_os];
          for (var _oi in options) {
            var itemGroupChildren = (0, _get["default"])(options[_oi], 'option_group.children');
            if (itemGroupChildren instanceof Array) {
              for (var ci in itemGroupChildren) {
                if (itemGroupChildren[ci].identifier === _selectedoption.identifier) {
                  options[_oi] = (0, _mergeWith["default"])((0, _cloneDeep["default"])(options[_oi]),
                  // dst
                  itemGroupChildren[ci],
                  // src
                  function (dstValue, srcValue) {
                    return (
                      // if the value is present in the src then use it, otherwise leave the original
                      srcValue !== null && srcValue !== undefined ? srcValue : dstValue
                    );
                  });
                }
              }
            }
          }
        }
        var optionsWithDetails = filterOptionsWithDetails(options);
        return _objectSpread(_objectSpread({}, state), {}, {
          selectedoptionclassification: selectedoptionclassification,
          options: options,
          optionsWithDetails: optionsWithDetails
        });
      }
    case actionTypes.SET_OPTIONCLASSIFICATION_CHECKED:
      {
        if (_typeof(action.optionclassification) === 'object') {
          return _objectSpread(_objectSpread({}, state), {}, {
            checkedOptionclassifications: _objectSpread(_objectSpread({}, state.checkedOptionclassifications), {}, _defineProperty({}, action.optionclassification.identifier, true))
          });
        }
        return state;
      }
    case actionTypes.SET_CONFLICTING_SWITCHOPTION_DATA:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          conflictingSwitchOptionData: action.switchOptionData
        });
      }
    default:
      return state;
  }
}
function calculationHandler(state, action) {
  switch (action.type) {
    case actionTypes.RECEIVE_CALCULATION:
      {
        var calculation = action.data;
        return _objectSpread(_objectSpread({}, state), {}, {
          calculation: calculation,
          calculationAutoResolve: state.calculationAutoResolve === 'skipNext' && !calculation.errors || state.calculationAutoResolve
        });
      }
    case actionTypes.INVALIDATE_CALCULATION:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          calculation: _objectSpread(_objectSpread({}, state.calculation), {}, {
            invalidated: true
          })
        });
      }
    case actionTypes.SET_CALCULATION_ENABLED:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          calculationIsEnabled: action.enabled
        });
      }
    case actionTypes.SET_CALCULATION_ERRORS_RESOLVED:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          calculation: state.calculation.errors ? null : state.calculation
        });
      }
    case actionTypes.SET_CALCULATION_AUTO_RESOLVE_ENABLED:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          calculationAutoResolve: action.enabled
        });
      }
    default:
      return state;
  }
}
function dataHandler(state, action) {
  switch (action.type) {
    case actionTypes.RECEIVE_OPTIONDETAILS:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          optiondetails: action.data
        });
      }
    case actionTypes.RECEIVE_VALIDATION:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          validation: action.data
        });
      }
    case actionTypes.RECEIVE_CONFIGURATIONVARIANTS:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          configurationvariants: action.data
        });
      }
    case actionTypes.RECEIVE_CODESNIPPETS:
      {
        if (!(0, _isArray["default"])(action.data)) {
          throw new Error("Server side error! The code snippets must be a JSON array! Data: ".concat(action.data));
        }
        return _objectSpread(_objectSpread({}, state), {}, {
          codesnippets: action.data || []
        });
      }
    case actionTypes.RECEIVE_CLIENT_DATA:
      {
        if (action.data.success === false) {
          return state;
        }
        var clientData = action.data;
        var color = (0, _get["default"])(clientData, 'theme.highlightColor');
        if (/^[0-9a-fA-F]{6}$/i.test(color)) {
          // if color is hex with missing '#'
          color = '#' + color;
        } else if (color.charAt(0) !== '#') {
          // if color string to get rgb color code
          var element = document.createElement('div');
          document.body.appendChild(element);
          element.style.color = color;
          var styles = window.getComputedStyle(element);
          color = styles.color;
          document.body.removeChild(element);
        }
        return _objectSpread(_objectSpread({}, state), {}, {
          client: _objectSpread(_objectSpread({}, clientData), {}, {
            theme: _objectSpread(_objectSpread({}, clientData.theme), {}, {
              highlightColor: color
            })
          })
        });
      }
    case actionTypes.RECEIVE_INSPIRATIONS:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          inspirations: action.data
        });
      }
    default:
      return state;
  }
}
function uiHandler(state, action) {
  switch (action.type) {
    case actionTypes.SET_STOCK_INFORMATION_OPTION:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          stockInformationOption: action.stockInformationOption
        });
      }
    case actionTypes.SET_SELECTED_VARIANT_IDENTIFIER:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          selectedVariantIdentifier: action.selectedVariantIdentifier
        });
      }
    default:
      return state;
  }
}
function baseHandler(state, action) {
  switch (action.type) {
    case actionTypes.SET_LOAD_CODE:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          loadCode: action.loadCode,
          loadIdentifier: null
        });
      }
    case actionTypes.SET_LOAD_IDENTIFIER:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          loadIdentifier: action.loadIdentifier,
          loadCode: null
        });
      }
    case actionTypes.SET_SELECTED_AMOUNT:
      {
        var selectedAmountsPath = 'customdata.selectedAmounts';
        var selectedAmounts = (0, _get["default"])(state.configuration, selectedAmountsPath, {});
        var configuration = (0, _set["default"])(state.configuration, selectedAmountsPath, action.amount === 0 ? (0, _omit["default"])(selectedAmounts, action.identifier) : _objectSpread(_objectSpread({}, selectedAmounts), {}, _defineProperty({}, action.identifier, action.amount)));
        return _objectSpread(_objectSpread({}, state), {}, {
          selectedAmountsUpdated: !!action.isUpdatedByUser,
          configuration: configuration
        });
      }
    case actionTypes.SWITCH_SELECTED_AMOUNT:
      {
        var srcIdentifier = action.srcIdentifier,
          dstIdentifier = action.dstIdentifier;
        var _selectedAmountsPath = 'customdata.selectedAmounts';
        var _selectedAmounts = (0, _get["default"])(state.configuration, _selectedAmountsPath, {});
        if (!(srcIdentifier in _selectedAmounts)) {
          return state;
        }
        var _configuration3 = (0, _set["default"])(state.configuration, _selectedAmountsPath, (0, _omit["default"])(_objectSpread(_objectSpread({}, _selectedAmounts), {}, _defineProperty({}, dstIdentifier, _selectedAmounts[srcIdentifier])), srcIdentifier));
        return _objectSpread(_objectSpread({}, state), {}, {
          configuration: _configuration3
        });
      }
    case actionTypes.SET_SELECTED_AMOUNTS:
      {
        var _selectedAmountsPath2 = 'configuration.customdata.selectedAmounts';
        var _selectedAmounts2 = (0, _get["default"])(state, _selectedAmountsPath2, {});
        var nextAmounts = _objectSpread(_objectSpread({}, _selectedAmounts2), action.sizes);
        var newState = _objectSpread(_objectSpread({}, state), {}, {
          selectedAmountsUpdated: !!action.isUpdatedByUser
        });
        return (0, _set["default"])(newState, _selectedAmountsPath2, _objectSpread({}, (0, _reduce["default"])(nextAmounts, function (selectedAmounts, amount, identifier) {
          if (amount !== 0) {
            return _objectSpread(_objectSpread({}, selectedAmounts), {}, _defineProperty({}, identifier, amount));
          } else {
            return selectedAmounts;
          }
        }, {})));
      }
    case actionTypes.DELETE_SELECTED_AMOUNTS:
      {
        var _selectedAmountsPath3 = 'configuration.customdata.selectedAmounts';
        var _selectedAmounts3 = (0, _cloneDeep["default"])((0, _get["default"])(state, _selectedAmountsPath3, {}));
        (0, _forEach["default"])(_selectedAmounts3, function (selectedAmount, identifier) {
          var variantIdentifier = (0, _find["default"])(action.variant.sizes, {
            identifier: identifier
          });
          if (variantIdentifier) {
            delete _selectedAmounts3[variantIdentifier.identifier];
          }
        });
        return (0, _set["default"])(state, _selectedAmountsPath3, _selectedAmounts3);
      }
    default:
      return state;
  }
}
function configurationModifierHandler(state, action) {
  switch (action.type) {
    case actionTypes.SET_CUSTOM_TITLE:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          configuration: _objectSpread(_objectSpread({}, state.configuration), {}, {
            customdata: _objectSpread(_objectSpread({}, state.configuration.customdata), {}, {
              title: action.title
            })
          })
        });
      }
    case actionTypes.SET_COMMENT:
      {
        return _objectSpread(_objectSpread({}, state), {}, {
          configuration: _objectSpread(_objectSpread({}, state.configuration), {}, {
            customdata: _objectSpread(_objectSpread({}, state.configuration.customdata), {}, {
              comment: action.comment
            })
          })
        });
      }
    case actionTypes.CLEAR_BULKNAMES:
      {
        return (0, _set["default"])(state, 'configuration.customdata.bulkNames', {});
      }
    case actionTypes.SAVE_BULKNAMES:
      {
        var bulkNamesPath = 'configuration.customdata.bulkNames';
        var bulkNames = (0, _get["default"])(state, bulkNamesPath, {});
        return (0, _set["default"])(state, bulkNamesPath, _objectSpread(_objectSpread({}, bulkNames), {}, _defineProperty({}, action.identifier, action.bulkNamesData)));
      }
    case actionTypes.DELETE_SELECTED_AMOUNT:
      {
        var selectedAmountsPath = 'configuration.customdata.selectedAmounts';
        var selectedAmounts = (0, _cloneDeep["default"])((0, _get["default"])(state, selectedAmountsPath, {}));
        delete selectedAmounts[action.identifier];
        return (0, _set["default"])(state, selectedAmountsPath, selectedAmounts);
      }
    case actionTypes.SET_SELECTED_CALCULATION:
      {
        return (0, _set["default"])(state, "configuration.customdata.userSelectedCalculation.".concat(action.identifier), action.value);
      }
    case actionTypes.SET_OPTION_INPUT_TEXT:
      {
        var optionInputTexts = state.optionInputTexts;
        var optionInputTextIndex = (0, _findIndex["default"])(optionInputTexts, ['optionIdentifier', action.identifier]);
        if (optionInputTextIndex !== -1) {
          optionInputTexts[optionInputTextIndex] = {
            optionIdentifier: action.identifier,
            inputText: action.value
          };
        } else if (optionInputTextIndex === -1 && action.value) {
          optionInputTexts.push({
            optionIdentifier: action.identifier,
            inputText: action.value
          });
        }
        return _objectSpread(_objectSpread({}, state), {}, {
          optionInputTexts: optionInputTexts
        });
      }
    case actionTypes.RESET_OPTION_INPUT_TEXTS:
      {
        var _optionInputTexts = [];
        return _objectSpread(_objectSpread({}, state), {}, {
          optionInputTexts: _optionInputTexts
        });
      }
    default:
      return state;
  }
}
function filterOptionclassifications(state, prevState) {
  // if the optionclassifications has changed it should be re-filtered
  if (prevState.configuration.optionclassifications !== state.configuration.optionclassifications) {
    return _objectSpread(_objectSpread({}, state), {}, {
      filteredOptionclassifications: state.configuration.optionclassifications
    });
  }
}
var subReducers = {
  baseHandler: baseHandler,
  configurationHandler: configurationHandler,
  optionAndOptionclassificationHandler: optionAndOptionclassificationHandler,
  calculationHandler: calculationHandler,
  dataHandler: dataHandler,
  uiHandler: uiHandler,
  configurationModifierHandler: configurationModifierHandler,
  designDataHandler: _Reducer.designDataHandler
};
var stateChangeReducers = {
  filterOptionclassifications: filterOptionclassifications
};
var reducerArray = Object.values(subReducers);
var stateReducerArray = Object.values(stateChangeReducers);
var setSubReducers = exports.setSubReducers = function setSubReducers(customSubReducers) {
  (0, _merge["default"])(subReducers, customSubReducers);
  reducerArray = Object.values(subReducers);
};
var setStateChangeReducers = exports.setStateChangeReducers = function setStateChangeReducers(customStateChangeReducers) {
  (0, _merge["default"])(stateChangeReducers, customStateChangeReducers);
  stateReducerArray = Object.values(stateChangeReducers);
};
function configuratorReducer() {
  var prevState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState;
  var action = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  // apply the reducers after each other (from left to right)
  // the idea comes from reduce-reducers package (https://github.com/redux-utilities/reduce-reducers)
  var nextState = reducerArray.reduce(function (newState, reducer) {
    return reducer(newState, action) || newState;
  }, prevState);

  // apply the state change reducers after each other (from left to right)
  var state = stateReducerArray.reduce(function (newState, reducer) {
    return reducer(newState, prevState, action) || newState;
  }, nextState);
  return state;
}
function filterOptionsWithDetails(options) {
  return (0, _filter["default"])(options, function (option) {
    return !!(option["abstract"] || option.description || option.detailImageExists === true);
  });
}