System.register(['reactive-jsx', 'src/components/widgets/lively-morph.js', 'src/client/morphic/node-helpers.js', 'src/client/morphic/event-helpers.js', 'src/client/graphics.js', 'src/components/halo/lively-halo.js'], function (_export, _context) {
  "use strict";

  var _childText, _childElement, _children, _attributeStringLiteral, _attributes, _element, _addSourceLocation, Morph, nodes, events, pt, rect, HaloService;

  return {
    setters: [function (_reactiveJsx) {
      _childText = _reactiveJsx.childText;
      _childElement = _reactiveJsx.childElement;
      _children = _reactiveJsx.children;
      _attributeStringLiteral = _reactiveJsx.attributeStringLiteral;
      _attributes = _reactiveJsx.attributes;
      _element = _reactiveJsx.element;
      _addSourceLocation = _reactiveJsx.addSourceLocation;
    }, function (_srcComponentsWidgetsLivelyMorphJs) {
      Morph = _srcComponentsWidgetsLivelyMorphJs.default;
    }, function (_srcClientMorphicNodeHelpersJs) {
      nodes = _srcClientMorphicNodeHelpersJs;
    }, function (_srcClientMorphicEventHelpersJs) {
      events = _srcClientMorphicEventHelpersJs;
    }, function (_srcClientGraphicsJs) {
      pt = _srcClientGraphicsJs.pt;
      rect = _srcClientGraphicsJs.rect;
    }, function (_srcComponentsHaloLivelyHaloJs) {
      HaloService = _srcComponentsHaloLivelyHaloJs.default;
    }],
    execute: function () {
      const __SystemJSRewritingHack = {};
      _recorder_._src_components_halo_lively_selection_js = _recorder_._src_components_halo_lively_selection_js || {};
      Object.defineProperty(_recorder_._src_components_halo_lively_selection_js, 'Morph', {
        get() {
          return Morph;
        },

        set(thisIsVererySecretVariableName) {
          Morph = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_components_halo_lively_selection_js, 'nodes', {
        get() {
          return nodes;
        },

        set(thisIsVererySecretVariableName) {
          nodes = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_components_halo_lively_selection_js, 'events', {
        get() {
          return events;
        },

        set(thisIsVererySecretVariableName) {
          events = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_components_halo_lively_selection_js, 'rect', {
        get() {
          return rect;
        },

        set(thisIsVererySecretVariableName) {
          rect = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_components_halo_lively_selection_js, 'pt', {
        get() {
          return pt;
        },

        set(thisIsVererySecretVariableName) {
          pt = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_components_halo_lively_selection_js, 'HaloService', {
        get() {
          return HaloService;
        },

        set(thisIsVererySecretVariableName) {
          HaloService = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });


      // import Clipboard from 'src/client/clipboard.js'; // #TODO Problems with cyclic dependencies...

      // document.querySelectorAll("lively-selection").forEach(ea => ea.remove())
      /*MD 
      
      # Lively Selection 
      
      - allows to drag a rectangle around elements and interact with them as a group
      - registers itself in load()
      
      MD*/

      class Selection extends Morph {

        get isMetaNode() {
          return true;
        }
        get isSelection() {
          return true;
        }

        static async load() {
          if (!window.lively) {
            return setTimeout(() => {
              Selection.load();
            }, 100 // defere
            );
          }

          if (!this.current) {
            this.current = _addSourceLocation(document.createElement("lively-selection"), {
              file: 'https://lively-kernel.org/lively4/composed-offset/src/components/halo/lively-selection.js',
              end: {
                column: 63,
                line: 33
              },
              start: {
                column: 21,
                line: 33
              }
            });
            await lively.components.openInBody(this.current);
            this.current.remove();
          }
          this.current.registerOn(document.documentElement);
        }

        registerOn(target) {
          lively.removeEventListener("Selection", target);
          lively.addEventListener("Selection", target, "pointerdown", e => Selection.current.onPointerDown(e) // select in bubling phase ...
          );lively.addEventListener("Selection", target, "pointerdown", e => Selection.current.onPointerDownPre(e), true // pre select in capturing phase ...
          );
        }

        initialize() {
          // super.initialize()
          this.nodes = [];
          this.startPositions = new Map();
          this.originalExtents = new Map();
          this.originalOffset = new Map();
        }

        allowsSelection(element, evt) {
          // the "evt" is important, because an element might be picky about it...
          return element.classList && element.classList.contains("lively-group") || element.livelyAllowsSelection && element.livelyAllowsSelection(evt);
          // ||(element.tagName == "LIVELY-CONTAINER")
        }

        onPointerDownPre(evt) {
          // lively.showEvent(evt)

          if (evt.ctrlKey || evt.altKey) return;
          var target = evt.composedPath().find(ea => this.allowsSelection(ea, evt)); // start with the innermost
          // console.log('evt path:' + evt.composedPath().map(ea => ea.classList).join("|")+ ": " + target)

          if (evt.composedPath()[0] !== document.body && evt.composedPath()[0] !== document.documentElement && !target) return;
          if (evt.pointerType == "touch") return; // no selection via touch

          lively.showEvent(evt).style.display = "none"; // #HACK, weired event shit.. without it the world scrolls #TODO
          document.documentElement.style.touchAction = "none";

          if (target) {
            // we won't be called in the bubbling, so we do it now
            this.startSelection(target, evt);
          }
        }

        onPointerDown(evt) {
          var target;
          if (evt.ctrlKey || evt.altKey) return;
          if (evt.button === 1 || evt.button === 2) {
            // middle mouse or riught mouse button
            return;
          }

          if (evt.composedPath()[0] === document.body || evt.composedPath()[0] === document.documentElement) {
            target = document.body;
          }
          if (evt.pointerType == "touch") return; // no selection via touch

          if (!target) target = evt.composedPath().find(ea => ea.classList && ea.classList.contains("lively-group")
          // if (target) lively.showElement(target)
          );if (!target) return;

          document.documentElement.style.touchAction = "none";
          // document.documentElement.setPointerCapture(evt.pointerId)

          if (lively.hand && lively.hand.childNodes.length > 0) return; // in drag
          if (this.disabled) return;

          // don't select with touch 
          if (evt.sourceCapabilities && evt.sourceCapabilities.firesTouchEvents) {
            lively.showPoint(pt(evt.clientX, evt.clientY));
            return;
          }
          this.startSelection(target, evt);
        }

        startSelection(target, evt) {
          lively.addEventListener("Selection", document.documentElement, "pointermove", e => this.onPointerMove(e));
          lively.addEventListener("Selection", document.documentElement, "pointerup", e => this.onPointerUp(e));

          this.selectionOffset = pt(evt.clientX, evt.clientY);
          this.context = target;
          this.nodes = [];
        }

        onPointerMove(evt) {
          var evtPos = pt(evt.clientX, evt.clientY);

          if (!this.parentElement) {
            document.body.appendChild(this);
            lively.setGlobalPosition(this, this.selectionOffset);
          }

          var topLeft = this.selectionOffset.minPt(evtPos);
          var bottomRight = this.selectionOffset.maxPt(evtPos);

          this.selectionBounds = rect(topLeft, bottomRight);
          lively.setGlobalPosition(this, topLeft);
          lively.setExtent(this, bottomRight.subPt(topLeft));

          this.nodes = Array.from(this.context.childNodes).filter(ea => !ea.isMetaNode).filter(ea => {
            if (!ea.getBoundingClientRect || ea.isMetaNode) return false;
            var r = ea.getBoundingClientRect();
            var eaRect = rect(r.left, r.top, r.width, r.height);
            return this.selectionBounds.containsRect(eaRect);
          });
        }

        onPointerUp(evt) {
          lively.removeEventListener("Selection", document.documentElement, "pointermove");
          lively.removeEventListener("Selection", document.documentElement, "pointerup");

          document.documentElement.style.touchAction = "";
          document.documentElement.releasePointerCapture(evt.pointerId);

          if (this.nodes.length > 0) {
            var minP = this.selectionBounds.bottomRight();
            var maxP = this.selectionBounds.topLeft();

            this.nodes.forEach(ea => {
              var r = ea.getBoundingClientRect();
              var eaRect = rect(r.left, r.top, r.width, r.height);
              minP = eaRect.topLeft().minPt(minP);
              maxP = eaRect.bottomRight().maxPt(maxP);
            });
            lively.setGlobalPosition(this, minP);
            lively.setExtent(this, maxP.subPt(minP));

            window.that = this;
            setTimeout(() => {
              HaloService.showHalos(this);
            }, 0);
          } else {
            this.remove();
          }
          // console.log("drag end")
        }

        haloRemove() {
          this.nodes.forEach(ea => {
            console.log("selection.remove " + ea);
            ea.remove();
          });
          this.remove();
        }

        haloCopyObject(haloItem) {

          // this.nodes = this.nodes.map(ea => {
          //   var copy = haloItem.cloneObject(ea);
          //   ea.parentNode.appendChild(copy); 
          //   return copy;
          // }).filter( ea => ea);

          var html = lively.clipboard.nodesToHTML(this.nodes);
          lively.clipboard.lastClickPos = lively.getGlobalPosition(this // used in pasted as offset
          );var result = lively.clipboard.pasteHTMLDataInto(html, this.parentElement, true);

          this.nodes = result;
          return this;
        }

        haloDragStart(fromPos) {
          this.startPositions = new Map();
          this.nodes.concat([this]).forEach(ea => {
            this.startPositions.set(ea, lively.getPosition(ea));
          });
        }

        haloDragTo(toPos, fromPos) {
          var delta = toPos.subPt(fromPos);
          this.nodes.concat([this]).forEach(ea => {
            nodes.setPosition(ea, this.startPositions.get(ea).addPt(delta));
          });
          window.that = this;
          HaloService.showHalos(this);
        }

        // cleanup:
        haloGrabStart(evt, haloItem, startPos) {
          if (haloItem.isCopyItem) {
            console.log("copy items...");
            this.haloCopyObject(haloItem);
          }
          this.startEventPos = startPos;

          this.startPositions.set(this, lively.getPosition(this)); // #BUG this is to late, because drag is detacted later...
          this.nodes.forEach(ea => {
            ea.classList.add("lively4-grabbed");
            var pos = lively.getPosition(ea);
            this.startPositions.set(ea, pos);
          });
        }

        haloGrabMove(evt, grabHaloItem) {

          this.haloDragTo(events.globalPosition(evt), this.startEventPos);
        }

        haloGrabStop(evt, grabHaloItem) {
          var positions = new Map();
          // first add temorarily to selection ... so that we do not drop into each other
          this.nodes.forEach(ea => {
            ea.classList.remove("lively4-grabbed");
            positions.set(ea, nodes.globalPosition(ea));
            this.appendChild(ea);
          });

          var dropTarget = grabHaloItem.droptargetAtEvent(this, evt);

          // then drop into the real target
          dropTarget = dropTarget || document.body; // we have to drop somewhere
          var i = 0;
          var offset = nodes.globalPosition(dropTarget);
          this.nodes.forEach(ea => {
            dropTarget.appendChild(ea);
            ea.style.position = "absolute";

            var pos = positions.get(ea);
            if (dropTarget.localizePosition) {
              s;
              pos = dropTarget.localizePosition(pos);
            } else {
              pos = pos.subPt(offset);
            }
            nodes.setPosition(ea, pos);
          });
          HaloService.showHalos(this);
        }

        haloResizeStart(evt, haloItem) {
          this.eventOffset = events.globalPosition(evt);
          this.nodes.concat([this]).forEach(ea => {
            this.startPositions.set(ea, nodes.globalPosition(ea));
            this.originalExtents.set(ea, nodes.getExtent(ea));
            this.originalOffset.set(ea, nodes.globalPosition(this).subPt(nodes.globalPosition(ea.parentNode)));
          });
        }

        haloResizeMove(evt, haloItem) {
          var delta = events.globalPosition(evt).subPt(this.eventOffset);
          var newExtent = this.originalExtents.get(this).addPt(delta);

          var oldExtent = this.originalExtents.get(this);
          var scale = newExtent.scaleBy(1 / oldExtent.x, 1 / oldExtent.y

          //nodes.setExtent(ea, this.originalExtents.get(ea).scaleByPt(scale))
          );nodes.setExtent(this, newExtent);

          this.nodes.forEach(ea => {
            var oldRelativePos = this.startPositions.get(ea).subPt(this.startPositions.get(this));

            lively.showPoint(this.originalOffset.get(ea));

            nodes.setPosition(ea, this.originalOffset.get(ea).addPt(oldRelativePos.scaleByPt(scale)));
            nodes.setExtent(ea, this.originalExtents.get(ea).scaleByPt(scale));
          });
        }

        haloResizeStop(evt, haloItem) {}

        livelyInspect(contentNode, inspector) {
          var selection = _element('div', _attributes(_attributeStringLiteral('class', 'element')), _children(_childElement(_element('i', _attributes(), _children(_childText('selection')), {
            file: 'https://lively-kernel.org/lively4/composed-offset/src/components/halo/lively-selection.js',
            end: {
              column: 57,
              line: 310
            },
            start: {
              column: 41,
              line: 310
            }
          }))), {
            file: 'https://lively-kernel.org/lively4/composed-offset/src/components/halo/lively-selection.js',
            end: {
              column: 63,
              line: 310
            },
            start: {
              column: 20,
              line: 310
            }
          });
          contentNode.appendChild(selection);
          this.nodes.forEach(ea => {
            selection.appendChild(inspector.display(ea, false, null, this));
          });
        }

      }

      _export('default', Selection);

      Object.defineProperty(_recorder_._src_components_halo_lively_selection_js, 'Selection', {
        get() {
          return Selection;
        },

        set(thisIsVererySecretVariableName) {
          _export('default', Selection = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Selection.load();
    }
  };
});