import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
import _merge2 from "lodash/merge";
import _cloneDeep from "lodash/cloneDeep";
import _debounce from "lodash/debounce";
import _pick from "lodash/pick";
import _isEqual from "lodash/isEqual";

var _templateObject;

import invariant from "invariant";
import dotProp from "dot-prop-immutable";
import gql from "graphql-tag";
import { createAction, addMiddleware, addReducer, addHigherOrderReducer } from "../redux";
import { getPlugin, getPlugins } from "../../plugins";
import { getPage, getElementWithChildren, getParentElementWithChildren } from "../selectors";
import { updateChildPaths } from "../utils";
import undoable from "./history";
export var DRAG_START = "Drag start";
export var DRAG_END = "Drag end";
export var ELEMENT_CREATED = "Element created";
export var ELEMENT_DROPPED = "Element dropped";
export var TOGGLE_PLUGIN = "Toggle plugin";
export var DEACTIVATE_PLUGIN = "Deactivate plugin";
export var HIGHLIGHT_ELEMENT = "Highlight element";
export var ACTIVATE_ELEMENT = "Activate element";
export var DEACTIVATE_ELEMENT = "Deactivate element";
export var UPDATE_ELEMENT = "Update element";
export var DELETE_ELEMENT = "Delete element";
export var FLATTEN_ELEMENTS = "Flatten elements";
export var SETUP_EDITOR = "Setup editor";
export var UPDATE_REVISION = "Update revision";
export var SAVING_REVISION = "Save revision";
export var START_SAVING = "Started saving";
export var FINISH_SAVING = "Finished saving";
/***************** HISTORY REDUCER *****************/

var horStatePath = "page.content";
addHigherOrderReducer([UPDATE_ELEMENT, DELETE_ELEMENT, ELEMENT_DROPPED, SETUP_EDITOR, "@@redux-undo/UNDO", "@@redux-undo/REDO", "@@redux-undo/INIT"], horStatePath, function () {
  return undoable(function () {
    var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
    var action = arguments.length > 1 ? arguments[1] : undefined;

    var _ref = arguments.length > 2 ? arguments[2] : undefined,
        statePath = _ref.statePath,
        reducer = _ref.reducer;

    // Get original reducer state path
    var relativeStatePath = statePath !== horStatePath ? statePath.replace(horStatePath + ".", "") : null;
    var relativeStateSlice = relativeStatePath ? dotProp.get(state, relativeStatePath) : state; // Execute original reducer

    var newState = reducer(relativeStateSlice, action); // Assign new data to HOR state

    return relativeStatePath ? dotProp.set(state, relativeStatePath, newState) : newState;
  }, {
    initTypes: ["@@redux-undo/INIT"],
    ignoreInitialState: true,
    filter: function filter(action) {
      if (action.payload && action.payload.history === false) {
        return false;
      }

      return true;
    }
  });
});
addReducer(["@@redux-undo/UNDO", "@@redux-undo/REDO", "@@redux-undo/INIT"], "page.content", function (state) {
  return state;
});
/***************** EDITOR ACTIONS *****************/

addReducer([SETUP_EDITOR], null, function (state, action) {
  return _objectSpread(_objectSpread({}, state), action.payload);
});
export var togglePlugin = createAction(TOGGLE_PLUGIN);
addReducer([TOGGLE_PLUGIN], "ui.plugins", function (state, action) {
  var _action$payload = action.payload,
      name = _action$payload.name,
      params = _action$payload.params,
      _action$payload$close = _action$payload.closeOtherInGroup,
      closeOtherInGroup = _action$payload$close === void 0 ? false : _action$payload$close;
  var plugin = getPlugin(name);

  if (!plugin) {
    return state;
  }

  var typePlugins = dotProp.get(state, plugin.type);

  if (!Array.isArray(typePlugins)) {
    typePlugins = [];
  }

  var alreadyActive = typePlugins.findIndex(function (pl) {
    return pl.name === plugin.name;
  });

  if (alreadyActive > -1) {
    typePlugins = dotProp.delete(typePlugins, alreadyActive);
  } else {
    if (closeOtherInGroup) {
      typePlugins = [{
        name: name,
        params: params
      }];
    } else {
      typePlugins.push({
        name: name,
        params: params
      });
    }
  }

  return dotProp.set(state, "".concat(plugin.type), typePlugins);
});
export var deactivatePlugin = createAction(DEACTIVATE_PLUGIN);
addReducer([DEACTIVATE_PLUGIN], "ui.plugins", function (state, action) {
  var name = action.payload.name;
  var plugin = getPlugin(name);

  if (!plugin) {
    return state;
  }

  var typePlugins = dotProp.get(state, plugin.type);

  if (!Array.isArray(typePlugins)) {
    typePlugins = [];
  }

  var alreadyActive = typePlugins.findIndex(function (pl) {
    return pl.name === plugin.name;
  });

  if (alreadyActive > -1) {
    typePlugins = dotProp.delete(typePlugins, alreadyActive);
  }

  return dotProp.set(state, "".concat(plugin.type), typePlugins);
});
export var highlightElement = createAction(HIGHLIGHT_ELEMENT, {
  log: false
});
addReducer([HIGHLIGHT_ELEMENT], "ui.highlightElement", function (state, action) {
  return action.payload.element ? action.payload.element : null;
});
export var activateElement = createAction(ACTIVATE_ELEMENT);
addReducer([ACTIVATE_ELEMENT], "ui.activeElement", function (state, action) {
  return action.payload.element;
});
export var deactivateElement = createAction(DEACTIVATE_ELEMENT);
addReducer([DEACTIVATE_ELEMENT], "ui.activeElement", function () {
  return null;
});
export var dragStart = createAction(DRAG_START);
addReducer([DRAG_START], "ui.dragging", function () {
  return true;
});
export var dragEnd = createAction(DRAG_END);
addReducer([DRAG_END], "ui.dragging", function () {
  return false;
});
export var elementCreated = createAction(ELEMENT_CREATED);
export var updateElement = createAction(UPDATE_ELEMENT);
addReducer([UPDATE_ELEMENT], function (action) {
  var element = action.payload.element;

  if (element.type === "document") {
    return "page.content";
  } // .slice(2) removes `0.` from the beginning of the generated path


  return "page.content." + action.payload.element.path.replace(/\./g, ".elements.").slice(2);
}, function (state, action) {
  var _action$payload2 = action.payload,
      element = _action$payload2.element,
      _action$payload2$merg = _action$payload2.merge,
      merge = _action$payload2$merg === void 0 ? false : _action$payload2$merg;

  if (element.elements && typeof element.elements[0] === "string") {
    delete element["elements"];
  }

  updateChildPaths(element);

  if (!merge) {
    return _objectSpread(_objectSpread({}, state), element);
  }

  return _merge2({}, state, element);
});
export var deleteElement = createAction(DELETE_ELEMENT);
addMiddleware([DELETE_ELEMENT], function (_ref2) {
  var store = _ref2.store,
      next = _ref2.next,
      action = _ref2.action;
  next(action);
  store.dispatch(deactivateElement());
  var state = store.getState();
  var element = action.payload.element;
  var parent = getParentElementWithChildren(state, element.id); // Remove child from parent

  if (!parent) {
    return;
  }

  var index = parent.elements.findIndex(function (el) {
    return el.id === element.id;
  });
  parent = dotProp.delete(parent, "elements." + index);
  store.dispatch(updateElement({
    element: parent
  })); // Execute `onChildDeleted` if defined

  var plugins = getPlugins("pb-editor-page-element");
  var plugin = plugins.find(function (pl) {
    return pl.elementType === parent.type;
  });

  if (!plugin) {
    return;
  }

  if (typeof plugin.onChildDeleted === "function") {
    plugin.onChildDeleted({
      element: parent,
      child: element
    });
  }
});
export var dropElement = createAction(ELEMENT_DROPPED);
addMiddleware([ELEMENT_DROPPED], function (_ref3) {
  var store = _ref3.store,
      next = _ref3.next,
      action = _ref3.action;
  next(action);
  var state = store.getState();
  var target = getElementWithChildren(state, action.payload.target.id);

  if (!target) {
    return;
  }

  var plugins = getPlugins("pb-editor-page-element");
  var plugin = plugins.find(function (pl) {
    return pl.elementType === target.type;
  });

  if (!plugin) {
    return;
  }

  invariant(plugin.onReceived, "To accept drops, element plugin must implement `onReceived` function");
  var source = action.payload.source;

  if (source.path) {
    source = getElementWithChildren(state, source.id);
  }

  if (!plugin) {
    return;
  }

  plugin.onReceived({
    source: source,
    target: target,
    position: action.payload.target.position
  });
});
export var updateRevision = createAction(UPDATE_REVISION);
addMiddleware([UPDATE_REVISION], function (_ref4) {
  var store = _ref4.store,
      next = _ref4.next,
      action = _ref4.action;
  next(action);

  if (action.payload.history === false) {
    return;
  }

  var onFinish = action.meta.onFinish;
  store.dispatch(saveRevision(null, {
    onFinish: onFinish
  }));
});
addReducer([UPDATE_REVISION], "page", function (state, action) {
  return _objectSpread(_objectSpread({}, state), action.payload);
}); // Flatten page content

var flattenContent = function flattenContent(el) {
  var els = {};
  el.elements = Array.isArray(el.elements) && el.elements.map(function (child) {
    els = _objectSpread(_objectSpread({}, els), flattenContent(child));
    return child.id;
  });
  els[el.id] = el;
  return els;
};

addReducer([FLATTEN_ELEMENTS], "elements", function (state, action) {
  return action.payload;
});
addMiddleware([UPDATE_ELEMENT, DELETE_ELEMENT, "@@redux-undo/UNDO", "@@redux-undo/REDO", "@@redux-undo/INIT"], function (_ref5) {
  var store = _ref5.store,
      next = _ref5.next,
      action = _ref5.action;
  var result = next(action);
  var state = store.getState();

  if (state.page.content) {
    var content = dotProp.get(state, "page.content.present") || null;

    if (!content) {
      return result;
    }

    var elements = flattenContent(_cloneDeep(content));
    store.dispatch({
      type: FLATTEN_ELEMENTS,
      payload: elements,
      meta: {
        log: true
      }
    });
  }

  return result;
});
/************************* SAVE REVISION *************************/

var lastSavedRevision = null;

var dataChanged = function dataChanged(revision) {
  if (!lastSavedRevision) {
    return true;
  }

  var content = revision.content,
      other = _objectWithoutProperties(revision, ["content"]);

  var _lastSavedRevision = lastSavedRevision,
      lastContent = _lastSavedRevision.content,
      lastOther = _objectWithoutProperties(_lastSavedRevision, ["content"]);

  return !_isEqual(content, lastContent) || !_isEqual(other, lastOther);
};

export var saveRevision = createAction(SAVING_REVISION);
var debouncedSave = null;
addMiddleware([UPDATE_REVISION, UPDATE_ELEMENT, DELETE_ELEMENT, "@@redux-undo/UNDO", "@@redux-undo/REDO"], function (_ref6) {
  var store = _ref6.store,
      next = _ref6.next,
      action = _ref6.action;
  next(action);

  var _ref7 = action.meta || {},
      onFinish = _ref7.onFinish;

  if (action.type === UPDATE_ELEMENT && action.payload.history === false) {
    return;
  }

  var page = getPage(store.getState());

  if (page.locked) {
    return;
  }

  if (debouncedSave) {
    debouncedSave.cancel();
  }

  debouncedSave = _debounce(function () {
    return store.dispatch(saveRevision(null, {
      onFinish: onFinish
    }));
  }, 1000);
  debouncedSave();
});
var startSaving = {
  type: START_SAVING,
  payload: {
    progress: true
  }
};
var finishSaving = {
  type: FINISH_SAVING,
  payload: {
    progress: false
  }
};
addReducer([START_SAVING, FINISH_SAVING], "ui.saving", function (state, action) {
  return action.payload.progress;
});
addMiddleware([SAVING_REVISION], function (_ref8) {
  var store = _ref8.store,
      next = _ref8.next,
      action = _ref8.action;
  next(action);
  var data = getPage(store.getState());

  if (data.locked) {
    return;
  } // Construct page payload


  var revision = _pick(data, ["title", "snippet", "url", "settings"]);

  revision.content = data.content.present;
  revision.category = data.category.id; // Check if API call is necessary

  if (!dataChanged(revision)) {
    return;
  }

  lastSavedRevision = revision;
  var updateRevision = gql(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n        mutation UpdateRevision($id: ID!, $data: PbUpdatePageInput!) {\n            pageBuilder {\n                updateRevision(id: $id, data: $data) {\n                    data {\n                        id\n                        content\n                        title\n                        published\n                        savedOn\n                    }\n                    error {\n                        code\n                        message\n                        data\n                    }\n                }\n            }\n        }\n    "])));
  store.dispatch(startSaving);
  action.meta.client.mutate({
    mutation: updateRevision,
    variables: {
      id: data.id,
      data: revision
    }
  }).then(function (data) {
    store.dispatch(finishSaving);
    action.meta.onFinish && action.meta.onFinish();
    return data;
  }).catch(function (err) {
    store.dispatch(finishSaving);
    console.log(err); // eslint-disable-line
  });
});
//# sourceMappingURL=actions.js.map