"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports["default"] = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _shell = require("../shell");
var _eventType = require("../eventType");
var _utils = require("../utils");
var _dragon = require("./dragon");
var _types = require("../types");
function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
var Host = exports["default"] = function Host(_project) {
  var _this = this;
  this.frameDocument = void 0;
  this.frameWindow = void 0;
  this.project = void 0;
  this.renderer = void 0;
  this.onAssetUpdated = /*#__PURE__*/function () {
    var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(additionalPackageNames) {
      var materialMap, assetBundles;
      return _regenerator["default"].wrap(function _callee$(_context) {
        while (1) switch (_context.prev = _context.next) {
          case 0:
            materialMap = new Map();
            additionalPackageNames.forEach(function (name) {
              if (_shell.material.has(name)) {
                materialMap.set(name, _shell.material.get(name));
              }
            });
            assetBundles = _this.getSimulatorComponentAssets(materialMap);
            _context.next = 5;
            return Promise.allSettled(assetBundles.map(function (asset) {
              return new Promise(function (res, rej) {
                if (_this.frameDocument) {
                  var script = _this.frameDocument.createElement('script');
                  script.onload = function () {
                    script.onload = null;
                    script.onerror = null;
                    res();
                  };
                  script.onerror = function () {
                    script.onload = null;
                    script.onerror = null;
                    rej();
                  };
                  _this.frameDocument.body.append(script);
                  script.src = asset.url;
                } else {
                  res();
                }
              });
            }));
          case 5:
            _this.registerComponentSetters(assetBundles);
            _this.collectComponentImpl(assetBundles);
            _this.rerender();
          case 8:
          case "end":
            return _context.stop();
        }
      }, _callee);
    }));
    return function (_x) {
      return _ref.apply(this, arguments);
    };
  }();
  this.mountContentFrame = /*#__PURE__*/function () {
    var _ref2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(frame) {
      return _regenerator["default"].wrap(function _callee2$(_context2) {
        while (1) switch (_context2.prev = _context2.next) {
          case 0:
            if (frame) {
              _context2.next = 2;
              break;
            }
            return _context2.abrupt("return");
          case 2:
            _this.frameDocument = frame.contentDocument;
            _this.frameWindow = frame.contentWindow;
            _context2.next = 6;
            return _this.createSimulator();
          case 6:
            _this.renderer = _context2.sent;
            _shell.material.off(_eventType.ASSET_UPDATED, _this.onAssetUpdated).on(_eventType.ASSET_UPDATED, _this.onAssetUpdated);
            _this.setupEvent();
            _this.renderer.run();
          case 10:
          case "end":
            return _context2.stop();
        }
      }, _callee2);
    }));
    return function (_x2) {
      return _ref2.apply(this, arguments);
    };
  }();
  this.setupEvent = function () {
    var _this$frameDocument, _this$frameDocument2, _this$frameDocument3, _this$frameDocument4, _this$frameDocument5, _this$frameDocument6;
    (_this$frameDocument = _this.frameDocument) === null || _this$frameDocument === void 0 ? void 0 : _this$frameDocument.addEventListener('dragover', function (e) {
      e.preventDefault();
      _shell.project.emit(_eventType.DRAG_OVER);
      _this.project.designer.dragon.onDragOver(e);
    });
    (_this$frameDocument2 = _this.frameDocument) === null || _this$frameDocument2 === void 0 ? void 0 : _this$frameDocument2.addEventListener('dragstart', function (e) {
      var node = _this.getNodeByDOMElem(e.target);
      if (node) {
        _this.project.designer.dragon.onDragStart({
          type: _types.DragObjectType.Node,
          node: node
        });
      }
    });
    (_this$frameDocument3 = _this.frameDocument) === null || _this$frameDocument3 === void 0 ? void 0 : _this$frameDocument3.addEventListener('mousemove', function (e) {
      var node = _this.project.designer.host.getClosestNodeByLocation(e);
      _this.project.documentModel.hoverNode(node === null || node === void 0 ? void 0 : node.id);
      _this.project.designer.detection.computeHoveredPosition(node === null || node === void 0 ? void 0 : node.id);
    });
    (_this$frameDocument4 = _this.frameDocument) === null || _this$frameDocument4 === void 0 ? void 0 : _this$frameDocument4.addEventListener('mouseleave', function (e) {
      _this.project.designer.detection.computeHoveredPosition();
    }, false);
    (_this$frameDocument5 = _this.frameDocument) === null || _this$frameDocument5 === void 0 ? void 0 : _this$frameDocument5.addEventListener('drop', /*#__PURE__*/function () {
      var _ref3 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(e) {
        var _this$project$designe, dragObject, dropLocation, schema, start, lastNodeId, _dragObject$node$pare;
        return _regenerator["default"].wrap(function _callee3$(_context3) {
          while (1) switch (_context3.prev = _context3.next) {
            case 0:
              _this$project$designe = _this.project.designer.dragon, dragObject = _this$project$designe.dragObject, dropLocation = _this$project$designe.dropLocation;
              if (!(dragObject && dropLocation)) {
                _context3.next = 19;
                break;
              }
              if (!(0, _dragon.isDragDataNode)(dragObject)) {
                _context3.next = 14;
                break;
              }
              schema = dragObject.data.schema;
              console.log(schema, 'schema');
              if (!Array.isArray(schema)) {
                schema = [schema];
              }
              start = dropLocation.index;
              schema.forEach(function (item) {
                var node = _this.project.documentModel.createNode(item, dropLocation.containerNode);
                dropLocation.containerNode.inertChildAtIndex(node, start);
                start++;
                lastNodeId = node.id;
              });
              if (!lastNodeId) {
                _context3.next = 12;
                break;
              }
              _context3.next = 11;
              return _this.rerender();
            case 11:
              _this.project.designer.selectNode(lastNodeId);
            case 12:
              _context3.next = 19;
              break;
            case 14:
              (_dragObject$node$pare = dragObject.node.parent) === null || _dragObject$node$pare === void 0 ? void 0 : _dragObject$node$pare.delChild(dragObject.node);
              dropLocation.containerNode.inertChildAtIndex(dragObject.node, dropLocation.index);
              _context3.next = 18;
              return _this.rerender();
            case 18:
              _this.project.designer.selectNode(dragObject.node.id);
            case 19:
              _this.project.designer.dragon.onDragEnd(e);
            case 20:
            case "end":
              return _context3.stop();
          }
        }, _callee3);
      }));
      return function (_x3) {
        return _ref3.apply(this, arguments);
      };
    }());
    (_this$frameDocument6 = _this.frameDocument) === null || _this$frameDocument6 === void 0 ? void 0 : _this$frameDocument6.addEventListener('mouseup', function (e) {
      var _this$getClosestNodeB;
      var nodeId = (_this$getClosestNodeB = _this.getClosestNodeByLocation(e)) === null || _this$getClosestNodeB === void 0 ? void 0 : _this$getClosestNodeB.id;
      _this.project.designer.selectNode(nodeId);
    });
  };
  this.getNodeByDOMElem = function (domElem) {
    if (domElem) {
      var noId = _this.renderer.getNodeIdByDOMElem(domElem);
      return noId ? _this.project.documentModel.getNode(noId) : undefined;
    }
  };
  this.getSimulatorComponentAssets = function (assetMap) {
    var result = [];
    for (var _iterator = _createForOfIteratorHelperLoose(assetMap), _step; !(_step = _iterator()).done;) {
      var _step$value = _step.value,
        key = _step$value[0],
        spec = _step$value[1];
      // 模板没有组件实现，只有组件规格
      if (spec.group !== 'template') {
        result.push({
          packageName: spec.packageName,
          componentName: spec.componentName,
          url: (0, _utils.getComponentImplUrl)({
            npm: spec.packageName,
            version: spec.version
          })
        });
      }
    }
    return result;
  };
  /**
   * 注册组件包自带的设置器
   */
  this.registerComponentSetters = function (assetBundles) {
    assetBundles.forEach(function (bundle) {
      var innerSetterMap = (0, _utils.getComponentSetterMap)(_this.frameWindow, bundle);
      for (var _i = 0, _Object$keys = Object.keys(innerSetterMap); _i < _Object$keys.length; _i++) {
        var key = _Object$keys[_i];
        _shell.setters.register({
          name: bundle.packageName + "/" + key,
          view: innerSetterMap[key]
        });
      }
    });
  };
  /**
   * 收集低代码组件的实现
   * @param assetBundles 
   */
  this.collectComponentImpl = function (assetBundles) {
    var componentMap = new Map();
    assetBundles.forEach(function (bundle) {
      var impl = (0, _utils.getComponentImplFromWin)(_this.frameWindow, bundle);
      if (impl) {
        componentMap.set(bundle.componentName, impl);
      }
    });
    _this.project.designer.addComponentsImpl(componentMap);
  };
  this.createSimulator = /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4() {
    var assetBundles, baseAssets, styleTags, scriptTags;
    return _regenerator["default"].wrap(function _callee4$(_context4) {
      while (1) switch (_context4.prev = _context4.next) {
        case 0:
          assetBundles = _this.getSimulatorComponentAssets(_shell.material.getAll());
          baseAssets = (0, _utils.getBaseAssets)(); // 这个属性在渲染器环境内部访问
          _this.frameWindow.LCSimulatorHost = _this;
          styleTags = '';
          scriptTags = '';
          baseAssets.css.forEach(function (url) {
            styleTags += "<link href=\"" + url + "\" rel=\"stylesheet\" />";
          });
          baseAssets.js.forEach(function (url) {
            scriptTags += "<script src=\"" + url + "\"></script>";
          });
          assetBundles.forEach(function (bundle) {
            scriptTags += "<script src=\"" + bundle.url + "\"></script>";
          });
          _this.frameDocument.open();
          _this.frameDocument.write("<!doctype html>\n            <html class=\"engine-design-mode\">\n            <head><meta charset=\"utf-8\"/>\n                " + styleTags + "\n            </head>\n            <body>\n                " + scriptTags + "\n            </body>\n            </html>");
          _this.frameDocument.close();
          return _context4.abrupt("return", new Promise(function (resolve, rejected) {
            var loaded = function loaded() {
              _this.registerComponentSetters(assetBundles);
              _this.collectComponentImpl(assetBundles);
              resolve(_this.frameWindow.SimulatorRenderer);
              _this.frameWindow.removeEventListener('load', loaded);
            };
            var errored = function errored() {
              rejected();
              _this.frameWindow.removeEventListener('error', errored);
            };
            _this.frameWindow.addEventListener('load', loaded);
            _this.frameWindow.addEventListener('error', errored);
          }));
        case 12:
        case "end":
          return _context4.stop();
      }
    }, _callee4);
  }));
  this.getClosestNodeByLocation = function (point) {
    var id = _this.renderer.getClosestNodeIdByLocation(point);
    return id ? _this.project.documentModel.getNode(id) : undefined;
  };
  this.getNodeRect = function (nodeId) {
    return _this.renderer.getNodeRect(nodeId);
  };
  this.rerender = /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5() {
    return _regenerator["default"].wrap(function _callee5$(_context5) {
      while (1) switch (_context5.prev = _context5.next) {
        case 0:
          _context5.next = 2;
          return _this.renderer.rerender();
        case 2:
        case "end":
          return _context5.stop();
      }
    }, _callee5);
  }));
  this.project = _project;
};