System.register(['src/client/graphics.js', 'src/components/halo/lively-halo.js', 'utils', 'src/client/persistence.js'], function (_export, _context) {
  "use strict";

  var pt, Halo, generateUUID, persistence;
  return {
    setters: [function (_srcClientGraphicsJs) {
      pt = _srcClientGraphicsJs.pt;
    }, function (_srcComponentsHaloLivelyHaloJs) {
      Halo = _srcComponentsHaloLivelyHaloJs.default;
    }, function (_utils) {
      generateUUID = _utils.uuid;
    }, function (_srcClientPersistenceJs) {
      persistence = _srcClientPersistenceJs.default;
    }],
    execute: function () {
      _recorder_._src_client_clipboard_js = _recorder_._src_client_clipboard_js || {};
      _recorder_._src_client_clipboard_js.pt = pt;
      _recorder_._src_client_clipboard_js.Halo = Halo;
      _recorder_._src_client_clipboard_js.generateUUID = generateUUID;
      _recorder_._src_client_clipboard_js.persistence = persistence;
      class Clipboard {

        static load() {
          lively.removeEventListener("Clipboard", document);
          lively.removeEventListener("Clipboard", document.body);

          lively.addEventListener("Clipboard", document, "mousedown", evt => this.onBodyMouseDown(evt), true);
          lively.addEventListener("Clipboard", document.body, "paste", evt => this.onPaste(evt), true);
          lively.addEventListener("Clipboard", document.body, "cut", evt => this.onCut(evt));
          lively.addEventListener("Clipboard", document.body, "copy", evt => this.onCopy(evt));

          document.body.setAttribute("tabindex", 0 // just ensure focusabiltity

          );lively.clipboard = _recorder_._src_client_clipboard_js.Clipboard; // #TODO make cyclic dependencies work
        }

        static onCut(evt) {
          if (!HaloService.areHalosActive() || !that) {
            return;
          }
          this.onCopy(evt);
          if (lively.selection.nodes.length > 0) {
            lively.selection.nodes.forEach(ea => {
              ea.remove();
            });
            lively.selection.remove();
          } else {
            that.remove();
          }
          _recorder_._src_client_clipboard_js.Halo.hideHalos();
        }

        static nodesToHTML(nodes) {
          // prepare for serialization
          nodes.forEach(node => {
            node.querySelectorAll("*").forEach(ea => {
              if (ea.livelyPrepareSave) ea.livelyPrepareSave();
            });
          });

          return nodes.map(ea => ea.outerHTML).join("\n");
        }

        static onCopy(evt) {
          if (!HaloService.areHalosActive() || !that) {
            return;
          }
          evt.preventDefault();
          evt.stopPropagation();
          var nodes = [];
          if (lively.selection.nodes.length > 0) {
            nodes = lively.selection.nodes;
          } else if (that !== undefined) {
            nodes = [that];
          }
          var html = this.nodesToHTML(nodes);
          evt.clipboardData.setData('text/plain', html);
          evt.clipboardData.setData('text/html', html);
        }

        static initializeElements(all) {
          all.forEach(child => {
            _recorder_._src_client_clipboard_js.persistence.initLivelyObject(child);
            var id = child.getAttribute("data-lively-id"
            // if we have an ID, some other me might be lying around somewhere...
            );if (id) {
              var otherMe = lively.elementByID(id);
              if (otherMe) {
                // so there is an identiy crysis... so we have to become somebody new...
                var newId = _recorder_._src_client_clipboard_js.generateUUID();
                // ... and I have to notify my buddies that I am no longer myself
                all.forEach(other => {
                  for (var i = 0; i < other.attributes.length; i++) {
                    var attr = other.attributes[i];
                    if (attr.value == id) {
                      // lively.notify("found a reference to me: " + other + "." + attr.name)
                      attr.value = newId;
                    }
                  }
                });
              }
            }
          });
        }

        static getTopLeft(elements) {
          var topLeft;
          elements.forEach(ea => {
            if (!topLeft) topLeft = lively.getGlobalPosition(ea);else topLeft = topLeft.minPt(lively.getGlobalPosition(ea));
          });
          return topLeft || _recorder_._src_client_clipboard_js.pt(0, 0);
        }

        static pasteHTMLDataInto(data, container, flat, pos = this.lastClickPos) {
          // add everthing into a container 
          var div = document.createElement("div");
          div.classList.add("lively-content");
          lively.setExtent(div, _recorder_._src_client_clipboard_js.pt(800, 10));
          div.innerHTML = data;
          container.appendChild(div);
          lively.setPosition(div, _recorder_._src_client_clipboard_js.pt(0, 0)

          // paste oriented at a shared topLeft
          );var topLevel = Array.from(div.querySelectorAll(":scope > *"));
          var all = Array.from(div.querySelectorAll("*"));

          this.initializeElements(all

          // somehow zIndex gets lost...
          );var zIndexMap = new Map();
          topLevel.forEach(ea => {
            zIndexMap.set(ea, ea.style.zIndex);
          }

          // topLevel = _.sortBy(topLevel, ea => ea.style && ea.style.zIndex).reverse()
          // topLevel.forEach(ea => ea.remove())
          // topLevel.forEach(ea => ea.style.zIndex = "")
          );topLevel.forEach(ea => div.appendChild(ea));
          var offset = (pos || _recorder_._src_client_clipboard_js.pt(0, 0)).subPt(this.getTopLeft(topLevel));
          var result = div;

          // #TODO #CleanUp

          topLevel.forEach(child => {
            if (child.classList.contains("lively-content") || child.tagName == "LIVELY-WINDOW") {
              container.appendChild(child);
              lively.moveBy(child, offset);
              result = child; // return last result?
            }
          }

          // restore zIndex in an Async way... it seems focus is responsible for it #Hack
          );lively.sleep(0).then(() => {
            topLevel.forEach(ea => {
              ea.style.zIndex = zIndexMap.get(ea);
            });
          }

          // clean up if neccesary

          );if (div.childElementCount == 0) {
            div.remove // and get rid of the tmp container
            ();
          } else {
            // ajust position and content size
            lively.setGlobalPosition(div, pos || _recorder_._src_client_clipboard_js.pt(0, 0));
            div.style.height = "max-content";
          }
          if (flat) {
            return topLevel;
          }
          lively.components.loadUnresolved(result, true, "pasteHTMLDataInto", true);

          return result;
        }

        static pasteTextDataInto(data, container) {
          var div = document.createElement("div");
          div.innerHTML = data;
          div.classList.add("lively-content");
          container.appendChild(div);
          lively.setGlobalPosition(div, this.lastClickPos);
        }

        static pasteFileInto(fileItem, container) {
          var blob = fileItem.getAsFile();
          var reader = new FileReader();
          reader.onload = event => {
            var img = document.createElement("img");
            img.src = event.target.result;
            img.classList.add("lively-content");
            container.appendChild(img);
            lively.setGlobalPosition(img, this.lastClickPos);
          }; // data url!
          reader.readAsDataURL(blob);
        }

        static onPaste(evt) {
          if (!this.lastClickPos) return; // we don't know where to paste it...this.lastClickPos
          // lively.notify("onPaste in " + this.lastTarget)

          if (!lively.hasGlobalFocus()) return;

          evt.stopPropagation();
          evt.preventDefault();
          lively.notify("paste");
          var data = evt.clipboardData.getData('text/html');
          if (data) {
            this.pasteHTMLDataInto(data, this.lastTarget);
            return;
          }

          data = evt.clipboardData.getData('text/plain');
          if (data) {
            this.pasteTextDataInto(data, this.lastTarget);
            return;
          }

          var items = (event.clipboardData || evt.clipboardData).items;
          if (items.length > 0) {
            for (var index in items) {
              var item = items[index];
              if (item.kind === 'file') {
                this.pasteFileInto(item, this.lastTarget);
              }
            }
            evt.stopPropagation();
            evt.preventDefault();
            return;
          }
        }

        static highlight(element) {
          if (this._highlight) this._highlight.remove();
          this._highlight = lively.showElement(element);
          this._highlight.innerHTML = "" + element.id;
          this._highlight.style.border = "1px solid blue";
        }

        static onBodyMouseDown(evt) {
          var target = evt.composedPath()[0];
          if (target == document.body.parentElement) target = document.body;

          if (target && target.classList) {
            if (target.classList.contains("lively-no-paste")) {
              target = evt.composedPath().find(ea => ea.tagName == "LIVELY-CONTAINER");
            } else {
              var container = evt.composedPath().find(ea => ea.tagName == "LIVELY-CONTAINER");
              if (container && !container.isEditing()) {
                target = container;
                var activeElement = container.shadowRoot.activeElement;
                if (activeElement && (activeElement.tagName == "INPUT" || activeElement.contentEditable)) {
                  // the element itself will handle the paste
                  this.lastTarget = null;
                  this.lastClickPos = null;
                  return;
                }
              } else {
                // this.lastTarget = container
                // } else {
                if (evt.composedPath().find(ea => ea.constructor.name == "ShadowRoot")) {
                  // #TODO is there a better test for the shadow root?
                  // lively.notify("shadow")
                  this.lastTarget = null;
                  this.lastClickPos = null;
                  return; // we are in the shadows
                }
              }
            }
            // this.highlight(target)
            lively.globalFocus();
            this.lastTarget = target;
            if (this.lastTarget.livelyTarget) {
              this.lastTarget = this.lastTarget.livelyTarget
              // lively.showElement(this.lastTarget)
              ();
            }
            this.lastClickPos = _recorder_._src_client_clipboard_js.pt(evt.clientX, evt.clientY);
          }
        }
      }

      _export('default', Clipboard);

      _recorder_._src_client_clipboard_js.Clipboard = Clipboard;
      _recorder_._src_client_clipboard_js.Clipboard.load();
    }
  };
});