"use strict";

exports.__esModule = true;
exports.builtinHotkey = void 0;
var _lowcodeUtils = require("@alilc/lowcode-utils");
var _lowcodeTypes = require("@alilc/lowcode-types");
/* eslint-disable max-len */

function insertChild(container, originalChild, at) {
  var child = originalChild;
  if ((0, _lowcodeUtils.isNode)(child) && child.isSlotNode) {
    child = child.exportSchema(_lowcodeTypes.IPublicEnumTransformStage.Clone);
  }
  var node = null;
  if ((0, _lowcodeUtils.isNode)(child)) {
    var _container$children;
    node = child;
    (_container$children = container.children) === null || _container$children === void 0 ? void 0 : _container$children.insert(node, at);
  } else {
    var _container$document;
    node = ((_container$document = container.document) === null || _container$document === void 0 ? void 0 : _container$document.createNode(child)) || null;
    if (node) {
      var _container$children2;
      (_container$children2 = container.children) === null || _container$children2 === void 0 ? void 0 : _container$children2.insert(node, at);
    }
  }
  return node || null;
}
function insertChildren(container, nodes, at) {
  var index = at;
  var node;
  var results = [];
  // eslint-disable-next-line no-cond-assign
  while (node = nodes.pop()) {
    node = insertChild(container, node, index);
    results.push(node);
    index = node.index;
  }
  return results;
}

/**
 * 获得合适的插入位置
 */
function getSuitableInsertion(pluginContext, insertNode) {
  var _material$getComponen, _refNode$componentMet, _target$componentMeta;
  var project = pluginContext.project,
    material = pluginContext.material;
  var activeDoc = project.currentDocument;
  if (!activeDoc) {
    return null;
  }
  if (Array.isArray(insertNode) && (0, _lowcodeUtils.isNodeSchema)(insertNode[0]) && (_material$getComponen = material.getComponentMeta(insertNode[0].componentName)) !== null && _material$getComponen !== void 0 && _material$getComponen.isModal) {
    if (!activeDoc.root) {
      return null;
    }
    return {
      target: activeDoc.root
    };
  }
  var focusNode = activeDoc.focusNode;
  var nodes = activeDoc.selection.getNodes();
  var refNode = nodes.find(function (item) {
    return focusNode.contains(item);
  });
  var target;
  var index;
  if (!refNode || refNode === focusNode) {
    target = focusNode;
  } else if ((_refNode$componentMet = refNode.componentMeta) !== null && _refNode$componentMet !== void 0 && _refNode$componentMet.isContainer) {
    target = refNode;
  } else {
    // FIXME!!, parent maybe null
    target = refNode.parent;
    index = refNode.index + 1;
  }
  if (target && insertNode && !((_target$componentMeta = target.componentMeta) !== null && _target$componentMeta !== void 0 && _target$componentMeta.checkNestingDown(target, insertNode))) {
    return null;
  }
  return {
    target: target,
    index: index
  };
}

/* istanbul ignore next */
function getNextForSelect(next, head, parent) {
  if (next) {
    if (!head) {
      return next;
    }
    var ret;
    if (next.isContainerNode) {
      var children = next.children;
      if (children && !children.isEmptyNode) {
        ret = getNextForSelect(children.get(0));
        if (ret) {
          return ret;
        }
      }
    }
    ret = getNextForSelect(next.nextSibling);
    if (ret) {
      return ret;
    }
  }
  if (parent) {
    return getNextForSelect(parent.nextSibling, false, parent === null || parent === void 0 ? void 0 : parent.parent);
  }
  return null;
}

/* istanbul ignore next */
function getPrevForSelect(prev, head, parent) {
  if (prev) {
    var ret;
    if (!head && prev.isContainerNode) {
      var children = prev.children;
      var lastChild = children && !children.isEmptyNode ? children.get(children.size - 1) : null;
      ret = getPrevForSelect(lastChild);
      if (ret) {
        return ret;
      }
    }
    if (!head) {
      return prev;
    }
    ret = getPrevForSelect(prev.prevSibling);
    if (ret) {
      return ret;
    }
  }
  if (parent) {
    return parent;
  }
  return null;
}
function getSuitablePlaceForNode(targetNode, node, ref) {
  var _node$componentMeta;
  var document = targetNode.document;
  if (!document) {
    return null;
  }
  var dragNodeObject = {
    type: _lowcodeTypes.IPublicEnumDragObjectType.Node,
    nodes: [node]
  };
  var focusNode = document === null || document === void 0 ? void 0 : document.focusNode;
  // 如果节点是模态框，插入到根节点下
  if (node !== null && node !== void 0 && (_node$componentMeta = node.componentMeta) !== null && _node$componentMeta !== void 0 && _node$componentMeta.isModal) {
    return {
      container: focusNode,
      ref: ref
    };
  }
  if (!ref && focusNode && targetNode.contains(focusNode)) {
    if (document.checkNesting(focusNode, dragNodeObject)) {
      return {
        container: focusNode
      };
    }
    return null;
  }
  if (targetNode.isRootNode && targetNode.children) {
    var dropElement = targetNode.children.filter(function (c) {
      if (!c.isContainerNode) {
        return false;
      }
      if (document.checkNesting(c, dragNodeObject)) {
        return true;
      }
      return false;
    })[0];
    if (dropElement) {
      return {
        container: dropElement,
        ref: ref
      };
    }
    if (document.checkNesting(targetNode, dragNodeObject)) {
      return {
        container: targetNode,
        ref: ref
      };
    }
    return null;
  }
  if (targetNode.isContainerNode) {
    if (document.checkNesting(targetNode, dragNodeObject)) {
      return {
        container: targetNode,
        ref: ref
      };
    }
  }
  if (targetNode.parent) {
    return getSuitablePlaceForNode(targetNode.parent, node, {
      index: targetNode.index
    });
  }
  return null;
}

// 注册默认的 setters
var builtinHotkey = function builtinHotkey(ctx) {
  return {
    init: function init() {
      var hotkey = ctx.hotkey,
        project = ctx.project,
        logger = ctx.logger,
        canvas = ctx.canvas;
      var clipboard = canvas.clipboard;
      // hotkey binding
      hotkey.bind(['backspace', 'del'], function (e, action) {
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        // TODO: use focus-tracker
        var doc = project.currentDocument;
        if ((0, _lowcodeUtils.isFormEvent)(e) || !doc) {
          return;
        }
        e.preventDefault();
        var sel = doc.selection;
        var topItems = sel.getTopNodes();
        // TODO: check can remove
        topItems.forEach(function (node) {
          if (node !== null && node !== void 0 && node.canPerformAction('remove')) {
            node && doc.removeNode(node);
          }
        });
        sel.clear();
      });
      hotkey.bind('escape', function (e, action) {
        var _project$currentDocum;
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        var sel = (_project$currentDocum = project.currentDocument) === null || _project$currentDocum === void 0 ? void 0 : _project$currentDocum.selection;
        if ((0, _lowcodeUtils.isFormEvent)(e) || !sel) {
          return;
        }
        e.preventDefault();
        sel.clear();
        // currentFocus.esc();
      });

      // command + c copy  command + x cut
      hotkey.bind(['command+c', 'ctrl+c', 'command+x', 'ctrl+x'], function (e, action) {
        var _document$getSelectio, _document$getSelectio2;
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        var doc = project.currentDocument;
        if ((0, _lowcodeUtils.isFormEvent)(e) || !doc) {
          return;
        }
        var anchorValue = (_document$getSelectio = document.getSelection()) === null || _document$getSelectio === void 0 ? void 0 : (_document$getSelectio2 = _document$getSelectio.anchorNode) === null || _document$getSelectio2 === void 0 ? void 0 : _document$getSelectio2.nodeValue;
        if (anchorValue && typeof anchorValue === 'string') {
          return;
        }
        e.preventDefault();
        var selected = doc.selection.getTopNodes(true);
        selected = selected.filter(function (node) {
          return node === null || node === void 0 ? void 0 : node.canPerformAction('copy');
        });
        if (!selected || selected.length < 1) {
          return;
        }
        var componentsMap = {};
        var componentsTree = selected.map(function (item) {
          return item === null || item === void 0 ? void 0 : item.exportSchema(_lowcodeTypes.IPublicEnumTransformStage.Clone);
        });

        // FIXME: clear node.id

        var data = {
          type: 'nodeSchema',
          componentsMap: componentsMap,
          componentsTree: componentsTree
        };
        clipboard.setData(data);
        var cutMode = action && action.indexOf('x') > 0;
        if (cutMode) {
          selected.forEach(function (node) {
            var parentNode = node === null || node === void 0 ? void 0 : node.parent;
            parentNode === null || parentNode === void 0 ? void 0 : parentNode.select();
            node === null || node === void 0 ? void 0 : node.remove();
          });
        }
      });

      // command + v paste
      hotkey.bind(['command+v', 'ctrl+v'], function (e, action) {
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        // TODO
        var doc = project === null || project === void 0 ? void 0 : project.currentDocument;
        if ((0, _lowcodeUtils.isFormEvent)(e) || !doc) {
          return;
        }
        /* istanbul ignore next */
        clipboard.waitPasteData(e, function (_ref) {
          var componentsTree = _ref.componentsTree;
          if (componentsTree) {
            var _ref2 = getSuitableInsertion(ctx, componentsTree) || {},
              target = _ref2.target,
              index = _ref2.index;
            if (!target) {
              return;
            }
            var canAddComponentsTree = componentsTree.filter(function (node) {
              var dragNodeObject = {
                type: _lowcodeTypes.IPublicEnumDragObjectType.Node,
                nodes: [node]
              };
              return doc.checkNesting(target, dragNodeObject);
            });
            if (canAddComponentsTree.length === 0) {
              return;
            }
            var nodes = insertChildren(target, canAddComponentsTree, index);
            if (nodes) {
              doc.selection.selectAll(nodes.map(function (o) {
                return o.id;
              }));
              setTimeout(function () {
                var _canvas$activeTracker;
                return (_canvas$activeTracker = canvas.activeTracker) === null || _canvas$activeTracker === void 0 ? void 0 : _canvas$activeTracker.track(nodes[0]);
              }, 10);
            }
          }
        });
      });

      // command + z undo
      hotkey.bind(['command+z', 'ctrl+z'], function (e, action) {
        var _project$currentDocum2, _project$currentDocum3;
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        var history = (_project$currentDocum2 = project.currentDocument) === null || _project$currentDocum2 === void 0 ? void 0 : _project$currentDocum2.history;
        if ((0, _lowcodeUtils.isFormEvent)(e) || !history) {
          return;
        }
        e.preventDefault();
        var selection = (_project$currentDocum3 = project.currentDocument) === null || _project$currentDocum3 === void 0 ? void 0 : _project$currentDocum3.selection;
        var curSelected = (selection === null || selection === void 0 ? void 0 : selection.selected) && Array.from(selection === null || selection === void 0 ? void 0 : selection.selected);
        history.back();
        selection === null || selection === void 0 ? void 0 : selection.selectAll(curSelected);
      });

      // command + shift + z redo
      hotkey.bind(['command+y', 'ctrl+y', 'command+shift+z'], function (e, action) {
        var _project$currentDocum4, _project$currentDocum5;
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        var history = (_project$currentDocum4 = project.currentDocument) === null || _project$currentDocum4 === void 0 ? void 0 : _project$currentDocum4.history;
        if ((0, _lowcodeUtils.isFormEvent)(e) || !history) {
          return;
        }
        e.preventDefault();
        var selection = (_project$currentDocum5 = project.currentDocument) === null || _project$currentDocum5 === void 0 ? void 0 : _project$currentDocum5.selection;
        var curSelected = (selection === null || selection === void 0 ? void 0 : selection.selected) && Array.from(selection === null || selection === void 0 ? void 0 : selection.selected);
        history.forward();
        selection === null || selection === void 0 ? void 0 : selection.selectAll(curSelected);
      });

      // sibling selection
      hotkey.bind(['left', 'right'], function (e, action) {
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        var doc = project.currentDocument;
        if ((0, _lowcodeUtils.isFormEvent)(e) || !doc) {
          return;
        }
        e.preventDefault();
        var selected = doc.selection.getTopNodes(true);
        if (!selected || selected.length < 1) {
          return;
        }
        var firstNode = selected[0];
        var silbing = action === 'left' ? firstNode === null || firstNode === void 0 ? void 0 : firstNode.prevSibling : firstNode === null || firstNode === void 0 ? void 0 : firstNode.nextSibling;
        silbing === null || silbing === void 0 ? void 0 : silbing.select();
      });
      hotkey.bind(['up', 'down'], function (e, action) {
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        var doc = project.currentDocument;
        if ((0, _lowcodeUtils.isFormEvent)(e) || !doc) {
          return;
        }
        e.preventDefault();
        var selected = doc.selection.getTopNodes(true);
        if (!selected || selected.length < 1) {
          return;
        }
        var firstNode = selected[0];
        if (action === 'down') {
          var next = getNextForSelect(firstNode, true, firstNode === null || firstNode === void 0 ? void 0 : firstNode.parent);
          next === null || next === void 0 ? void 0 : next.select();
        } else if (action === 'up') {
          var prev = getPrevForSelect(firstNode, true, firstNode === null || firstNode === void 0 ? void 0 : firstNode.parent);
          prev === null || prev === void 0 ? void 0 : prev.select();
        }
      });
      hotkey.bind(['option+left', 'option+right'], function (e, action) {
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        var doc = project.currentDocument;
        if ((0, _lowcodeUtils.isFormEvent)(e) || !doc) {
          return;
        }
        e.preventDefault();
        var selected = doc.selection.getTopNodes(true);
        if (!selected || selected.length < 1) {
          return;
        }
        // TODO: 此处需要增加判断当前节点是否可被操作移动，原ve里是用 node.canOperating()来判断
        // TODO: 移动逻辑也需要重新梳理，对于移动目标位置的选择，是否可以移入，需要增加判断

        var firstNode = selected[0];
        var parent = firstNode === null || firstNode === void 0 ? void 0 : firstNode.parent;
        if (!parent) return;
        var isPrev = action && /(left)$/.test(action);
        var silbing = isPrev ? firstNode.prevSibling : firstNode.nextSibling;
        if (silbing) {
          if (isPrev) {
            parent.insertBefore(firstNode, silbing, true);
          } else {
            parent.insertAfter(firstNode, silbing, true);
          }
          firstNode === null || firstNode === void 0 ? void 0 : firstNode.select();
        }
      });
      hotkey.bind(['option+up'], function (e, action) {
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        var doc = project.currentDocument;
        if ((0, _lowcodeUtils.isFormEvent)(e) || !doc) {
          return;
        }
        e.preventDefault();
        var selected = doc.selection.getTopNodes(true);
        if (!selected || selected.length < 1) {
          return;
        }
        // TODO: 此处需要增加判断当前节点是否可被操作移动，原ve里是用 node.canOperating()来判断
        // TODO: 移动逻辑也需要重新梳理，对于移动目标位置的选择，是否可以移入，需要增加判断

        var firstNode = selected[0];
        var parent = firstNode === null || firstNode === void 0 ? void 0 : firstNode.parent;
        if (!parent) {
          return;
        }
        var silbing = firstNode.prevSibling;
        if (silbing) {
          if (silbing.isContainerNode) {
            var place = getSuitablePlaceForNode(silbing, firstNode, null);
            silbing.insertAfter(firstNode, place.ref, true);
          } else {
            parent.insertBefore(firstNode, silbing, true);
          }
          firstNode === null || firstNode === void 0 ? void 0 : firstNode.select();
        } else {
          var _place = getSuitablePlaceForNode(parent, firstNode, null); // upwards
          if (_place) {
            var container = _place.container.internalToShellNode();
            container.insertBefore(firstNode, _place.ref);
            firstNode === null || firstNode === void 0 ? void 0 : firstNode.select();
          }
        }
      });
      hotkey.bind(['option+down'], function (e, action) {
        logger.info("action " + action + " is triggered");
        if (canvas.isInLiveEditing) {
          return;
        }
        var doc = project.getCurrentDocument();
        if ((0, _lowcodeUtils.isFormEvent)(e) || !doc) {
          return;
        }
        e.preventDefault();
        var selected = doc.selection.getTopNodes(true);
        if (!selected || selected.length < 1) {
          return;
        }
        // TODO: 此处需要增加判断当前节点是否可被操作移动，原 ve 里是用 node.canOperating() 来判断
        // TODO: 移动逻辑也需要重新梳理，对于移动目标位置的选择，是否可以移入，需要增加判断

        var firstNode = selected[0];
        var parent = firstNode === null || firstNode === void 0 ? void 0 : firstNode.parent;
        if (!parent) {
          return;
        }
        var silbing = firstNode.nextSibling;
        if (silbing) {
          if (silbing.isContainerNode) {
            silbing.insertBefore(firstNode, undefined);
          } else {
            parent.insertAfter(firstNode, silbing, true);
          }
          firstNode === null || firstNode === void 0 ? void 0 : firstNode.select();
        } else {
          var place = getSuitablePlaceForNode(parent, firstNode, null); // upwards
          if (place) {
            var container = place.container.internalToShellNode();
            container.insertAfter(firstNode, place.ref, true);
            firstNode === null || firstNode === void 0 ? void 0 : firstNode.select();
          }
        }
      });
    }
  };
};
exports.builtinHotkey = builtinHotkey;
builtinHotkey.pluginName = '___builtin_hotkey___';