import { u as utils, e as editorDefaults, i as inherit, K as resizeElement, B as BaseElement, L as FlexModel } from "./install-editor.js";
import { a3 as merge, aa as pick, a9 as cloneDeep, aB as throttle } from "./index.js";
import "vue";
import "./base-element.js";
import "./watermark.js";
import "./v4.js";
import "./defaults.js";
import "./index15.js";
import "./asyncToGenerator.js";
import "./pixel-helper.js";
import "./index16.js";
import "./uniq.js";
import "./video.js";
import "./get-lines.js";
import "./gif-apng.worker.js";
import "./vue-slider-component.umd.min.js";
var methods = {
  createFlex(elements, options) {
    if (!elements) {
      elements = this.getSelectedElements();
    }
    elements = (elements || []).filter((el) => el.groupable);
    const bbox = utils.getBBoxByElements(elements);
    let flex = this.createElement({
      type: "flex",
      height: bbox.height,
      width: bbox.width,
      left: bbox.left,
      top: bbox.top,
      elements: []
    });
    merge(flex, options);
    let mainAx = flex.flexDirection.includes("row") ? "width" : "height";
    let subAx = flex.flexDirection.includes("row") ? "height" : "width";
    let maxSubSize = -Infinity;
    let mainSize = 0;
    elements.forEach((element) => {
      element = this.addElement(element, flex, false);
      element.flex = merge({}, editorDefaults.flex, element.flex);
      element.disableEditable();
      element.$selected = false;
      mainSize += element[mainAx];
      if (maxSubSize < element[subAx]) {
        maxSubSize = element[subAx];
      }
    });
    flex[mainAx] = mainSize;
    flex[subAx] = maxSubSize;
    return flex;
  },
  addFlexByElements(elements, options) {
    if (!elements) {
      elements = this.getSelectedElements();
    }
    elements = (elements || []).filter((el) => el.groupable);
    if (elements.length <= 1) {
      return;
    }
    const flex = this.createFlex(elements, options);
    this.addElement(flex);
    this.focusElement(flex);
    elements.forEach((element) => {
      this.removeElement(element);
    });
    this.makeSnapshot("add_flex", null, true);
  },
  flatFlex(element) {
    element = this.getElement(element);
    if (element.type === "flex") {
      const elements = this.flatGroup(element);
      elements.forEach((element2) => {
        element2.flex = null;
      });
      return elements;
    }
    return [];
  },
  changeElementFlex(flex, element) {
    flex = merge({}, editorDefaults.flex, element.flex, flex);
    this.changeElement({ flex }, element);
  }
};
function setFlexStyleToElement(flexModel, element) {
  const { autoAdaptive, flexDirection, justifyContent, alignItems, alignContent, flexWrap, width, height, padding } = flexModel;
  const style = element.style;
  style.position = "absolute";
  style.visibility = "hidden";
  style.pointerEvents = "none";
  style.left = 0;
  style.top = 0;
  style.zIndex = -100;
  style.display = autoAdaptive === 0 ? "flex" : "inline-flex";
  style.width = autoAdaptive & 2 ? "" : `${width}px`;
  style.height = autoAdaptive & 1 ? "" : `${height}px`;
  style.flexDirection = flexDirection;
  style.justifyContent = justifyContent;
  style.alignItems = alignItems;
  style.alignContent = alignContent;
  style.flexWrap = flexWrap;
  style.padding = padding.map((padding2) => `${padding2}px`).join(" ");
  style.boxSizing = "border-box";
}
function setNodeStyleToElement(nodeModel, element) {
  const { width, height, type, alignSelf, flexGrow, flexShrink, flexBasis, margin, hidden } = nodeModel;
  const style = element.style;
  style.width = `${width}px`;
  style.height = `${height}px`;
  style.alignSelf = alignSelf;
  style.flexGrow = flexGrow;
  style.flexShrink = type === "text" ? 1 : flexShrink;
  style.flexBasis = flexBasis < 0 ? "auto" : flexBasis;
  style.margin = margin.map((margin2) => `${margin2}px`).join(" ");
  style.display = hidden ? "none" : "";
}
class FlexShadow {
  constructor(container) {
    this.map = /* @__PURE__ */ new Map();
    this.container = container;
    this.root = document.createElement("div");
    container.appendChild(this.root);
  }
  destory() {
    this.map = null;
    this.container = null;
    this.root = null;
  }
  setRoot(model) {
    setFlexStyleToElement(model, this.root);
  }
  setNodes(models) {
    const ids = {};
    models.forEach((model) => {
      const { $id } = model;
      if (!this.map.has($id)) {
        const element = document.createElement("div");
        this.root.appendChild(element);
        this.map.set($id, element);
      }
      const domElement = this.map.get($id);
      ids[$id] = true;
      setNodeStyleToElement(model, domElement);
    });
    Array.from(this.map.keys()).forEach((key) => {
      if (!ids[key]) {
        const element = this.map.get(key);
        element.remove();
        this.map.delete(key);
      }
    });
  }
  getRootSize() {
    const { offsetWidth, offsetHeight } = this.root;
    return {
      width: offsetWidth,
      height: offsetHeight
    };
  }
  getNodeSize(id) {
    const element = this.map.get(id);
    if (!element) {
      throw new Error("flex shadow element is not exist!");
    }
    const { offsetLeft, offsetTop, offsetWidth, offsetHeight } = element;
    return {
      left: offsetLeft,
      top: offsetTop,
      width: offsetWidth,
      height: offsetHeight
    };
  }
}
var template = `<div
    class="editor-element"
    :class="[
        'editor-element-' + model.type,
        model.lock ? 'editor-element-lock' : '',
        model.hidden ? 'editor-element-hidden' : '',
        model.frozen ? 'editor-element-frozen' : '',
        model.$loaded ? '' : 'editor-element-loading',
        model.$selected ? 'editor-element-selected' : '',
        model.$editing ? 'editor-element-editing' : ''
    ]"
    :style="[baseStyle]"
>
    <div
        class="editor-element-flex__container" >
        <!-- elements -->
        <template
            v-for="(element, index) in model.elements">
            <component
                ref="elements"
                v-if="editor.supportTypesMap[element.type]"
                :data-id="element.$id"
                :key='element.$id'
                :is="element.type + '-element'"
                :options="options"
                :global="global"
                :model="element"
                :editor="editor"
                :class="element.$className"
            >
                <template v-slot="{ hideBlink, isShowBlink, bgNinePatch }">
                    <slot
                        name="children"
                        :bgNinePatch="bgNinePatch"
                        :subElement="element"
                        :isShowBlink="isShowBlink"
                        :hideBlink="hideBlink"></slot>
                </template>

                <!-- \u7EC4\u5D4C\u5957 -->
                <template
                    v-if="elementIsGroup(element)"
                    v-slot:children="{ subElement, hideBlink, isShowBlink, bgNinePatch }">
                    <div
                        class="element-blink"
                        @animationend="hideBlink"
                        v-if="isShowBlink"></div>

                    <i class="border-before"></i>

                    <watermark
                        v-if="subElement.watermarkEnable"
                        :global="global"
                        :options="options"
                        :model="subElement" />

                    <background
                        v-if="subElement.backgroundColor || (subElement.backgroundEffect && subElement.backgroundEffect.enable && subElement.backgroundEffect.type)"
                        :element="subElement"
                        :mode="options.mode"
                        :global="global"
                        :options="options"
                        :layout="editor.currentLayout" />

                    <ninePatch-element
                        v-if="subElement.backgroundEffect && subElement.backgroundEffect.enable && subElement.backgroundEffect.type === 'ninePatch' && editor.supportTypesMap.ninePatch"
                        class="is-background"
                        :editor="editor"
                        :model="bgNinePatch"
                        :global="global"
                        :options="options" />

                    <border
                        v-if="subElement.border && subElement.border.enable"
                        :global="global"
                        :options="options"
                        :mode="options.mode"
                        :element="subElement"
                        :layout="editor.currentLayout" />
                </template>
            </component>
            <common-element
                v-else
                :key='element.$id'
                :model="element"
                :global="global"
                :options="options"
                :editor="editor"
            />
        </template>
    </div>
    <div ref="shadowContainer" />
    <slot :hideBlink="hideBlink" :isShowBlink="isShowBlink" :bgNinePatch="bgNinePatch"></slot>
</div>
`;
var FlexElement = inherit(BaseElement, {
  name: "flex-element",
  template,
  data() {
    return {
      resizing: false,
      widthRatio: 1,
      heightRatio: 1,
      $innerUpdate: false
    };
  },
  computed: {
    shadowRoot() {
      const { autoAdaptive, flexDirection, justifyContent, alignItems, alignContent, flexWrap, width, height, padding } = this.model;
      return {
        autoAdaptive,
        flexDirection,
        justifyContent,
        alignItems,
        alignContent,
        flexWrap,
        width,
        height,
        padding
      };
    },
    shadowModels() {
      const { elements } = this.model;
      return elements.map((element) => {
        const { flex = editorDefaults.flex, width, height, type, $id, hidden } = element;
        const { alignSelf, flexGrow, flexShrink, flexBasis, margin } = flex;
        return {
          $id,
          width,
          height,
          type,
          alignSelf,
          flexGrow,
          flexShrink,
          flexBasis,
          margin,
          hidden
        };
      });
    },
    calcMargin() {
      let { visibleElements, model } = this;
      const { width, height } = model;
      const length = visibleElements.length;
      let subWidthSum = 0;
      let subHeightSum = 0;
      visibleElements.map((element) => {
        const { width: width2, height: height2 } = element;
        subWidthSum += width2;
        subHeightSum += height2;
      });
      const rowMargin = (width - subWidthSum) / (length - 1);
      const columnMargin = (height - subHeightSum) / (length - 1);
      if (this.isRow && rowMargin < 0 || !this.isRow && columnMargin < 0)
        return [0, 0, 0, 0];
      return this.isRow ? [0, rowMargin, 0, 0] : [0, 0, columnMargin, 0];
    },
    isRow() {
      return this.model.flexDirection === "row";
    }
  },
  methods: {
    load() {
      const { model } = this;
      if (!this.loadDfd) {
        const loadDfd = this.loadDfd = {
          loadCount: 0,
          check(element) {
            if (model.elements.includes(element)) {
              loadDfd.loadCount += 1;
            }
            if (loadDfd.loadCount >= model.elements.length) {
              loadDfd.resolve();
            }
          }
        };
        loadDfd.promise = new Promise((resolve, reject) => {
          loadDfd.resolve = resolve;
          loadDfd.reject = reject;
          if (!model.elements.length) {
            resolve();
          }
        }).then(() => {
          return this.syncRect();
        });
      }
      return this.loadDfd.promise;
    },
    resizeInit(data) {
      const { dir } = data;
      if (["sw", "nw", "ne", "se"].includes(dir)) {
        this.resizing = true;
        this.$childModelsCache = /* @__PURE__ */ new Map();
        this.editor.walkTemplet((element) => {
          const cache = pick(element, [
            "left",
            "top",
            "width",
            "height",
            "fontSize",
            "contents",
            "letterSpacing",
            "strokeWidth",
            "effectScale",
            "radius",
            "$originalScale"
          ]);
          cache.padding = cloneDeep(element.padding);
          cache.flex = cloneDeep(element.flex);
          if (element.$paths) {
            cache.$paths = cloneDeep(element.$paths);
          }
          if (element.contents) {
            cache.contents = cloneDeep(element.contents);
          }
          if (element.imageTransform) {
            cache.imageTransform = cloneDeep(element.imageTransform);
          }
          if (element.imageEffects) {
            cache.imageEffects = cloneDeep(element.imageEffects);
          }
          if (element.backgroundEffect && element.backgroundEffect.enable) {
            cache.backgroundEffect = cloneDeep(element.backgroundEffect);
          }
          if (element.border && element.border.enable) {
            cache.border = cloneDeep(element.border);
          }
          this.$childModelsCache.set(element.$id, cache);
        }, true, [this.model]);
        this.$elementCache = {
          dir,
          width: this.model.width,
          height: this.model.height
        };
        this.widthRatio = 1;
        this.heightRatio = 1;
      }
    },
    resize(drag) {
      if (this.resizing) {
        this.updateSubElements();
      }
    },
    resizeEnd() {
      if (this.resize) {
        delete this.$childModelsCache;
        delete this.$elementCache;
        this.resizing = false;
        this.updateSubElements();
      } else {
        this.syncFlexRect();
      }
    },
    setSubElementsRatio(widthRatio, heightRatio, dw, dh) {
      const { $childModelsCache, model } = this;
      const { dir = "" } = this.$elementCache;
      this.editor.walkTemplet((element) => {
        const cache = $childModelsCache.get(element.$id);
        if (!cache)
          return;
        if (dir.length === 2) {
          resizeElement(element, widthRatio, { cache, sync: true, deep: false });
        }
      }, true, [model]);
    },
    updateSubElements() {
      const { model } = this;
      const childModelsCache = this.$childModelsCache;
      if (!childModelsCache) {
        return;
      }
      const widthRatio = model.width / this.$elementCache.width;
      const heightRatio = model.height / this.$elementCache.height;
      this.setSubElementsRatio(widthRatio, heightRatio, model.width - this.$elementCache.width, model.height - this.$elementCache.height);
    },
    elementIsGroup(element) {
      return this.editor.isGroup(element);
    },
    syncMargin() {
      if (!this.model.autoAdaptive)
        return;
      const margin = this.calcMargin;
      const { elements } = this.model;
      const modelMargin = elements[0].flex.margin;
      const length = elements.length;
      const isSynced = this.isRow ? modelMargin[1] === margin[1] : modelMargin[2] === margin[2];
      if (isSynced)
        return;
      elements.map((element, index2) => {
        if (index2 === length - 1) {
          element.flex.margin = [0, 0, 0, 0];
          return;
        }
        element.flex.margin = [...margin];
      });
    },
    resetBounding(width, height) {
      const getCenterVec = (width2, height2, rotation2) => {
        const x = width2 / 2;
        const y = height2 / 2;
        const k1 = Math.cos(rotation2);
        const k2 = Math.sin(rotation2);
        return [x * k1 - y * k2, x * k2 + y * k1];
      };
      const model = this.model;
      const { rotation } = model;
      const left = 0;
      const top = 0;
      const centerVec = getCenterVec(model.width, model.height, rotation);
      const centerVecNew = getCenterVec(width, height, rotation);
      const leftAfterRotate = left * Math.cos(rotation) - top * Math.sin(rotation);
      const topAfterRotate = left * Math.sin(rotation) + top * Math.cos(rotation);
      const centerOffset = [leftAfterRotate + centerVecNew[0] - centerVec[0], topAfterRotate + centerVecNew[1] - centerVec[1]];
      model.left += centerOffset[0] + (model.width - width) / 2;
      model.top += centerOffset[1] + (model.height - height) / 2;
      model.width = width;
      model.height = height;
    },
    calculateLayout(delta) {
      if (!this.isDesignMode) {
        return;
      }
      let { shadowModels, shadowRoot, autoAdaptive } = this;
      const { alignItems } = this.model;
      if (delta) {
        const { width: width2, height: height2 } = delta;
        if ((autoAdaptive & 2) !== 0 && width2 !== 0) {
          shadowRoot.width += width2;
        }
        if ((autoAdaptive & 1) !== 0 && height2 !== 0) {
          shadowRoot.height += height2;
        }
      }
      this.shadow.setRoot(shadowRoot);
      this.shadow.setNodes(shadowModels);
      const { width, height, elements } = this.model;
      const shadowContainer = this.shadow.getRootSize();
      if (shadowContainer.width === 0 || shadowContainer.height === 0)
        return;
      let subWidthSum = 0;
      let subHeightSum = 0;
      elements.forEach((element) => {
        const { $id, autoAdaptive: autoAdaptive2, fontSize, type, hidden } = element;
        const shadowElement = this.shadow.getNodeSize($id);
        let { left, top, width: width2, height: height2 } = shadowElement;
        element.left = left;
        element.top = top;
        if ((autoAdaptive2 & 2) === 0 && width2 !== 0) {
          if (type === "text" && width2 < fontSize)
            width2 = fontSize;
          element.width = width2;
        }
        if ((autoAdaptive2 & 1) === 0 && height2 !== 0) {
          if (type === "text" && height2 < fontSize)
            height2 = fontSize;
          element.height = height2;
        }
        if (!hidden) {
          subWidthSum += element.width;
          subHeightSum += element.height;
        }
        this.$events.$emit("element.syncRect", element);
      });
      if (Math.abs(width - shadowContainer.width) > 0.1 || Math.abs(height - shadowContainer.height) > 0.1) {
        this.resetBounding(shadowContainer.width, shadowContainer.height);
        this.$innerUpdate = true;
        this.$events.$emit("element.rectUpdate", this.model, {
          width: this.model.width - width,
          height: this.model.height - height
        });
      }
      if (delta) {
        const offsetNum = this.isRow ? this.model.height - height : this.model.width - width;
        if (alignItems === "center" && offsetNum !== 0)
          this.model[this.isRow ? "top" : "left"] -= offsetNum / 2;
        if (alignItems === "flex-end" && offsetNum !== 0)
          this.model[this.isRow ? "top" : "left"] -= offsetNum;
      }
    },
    lazyCalculateLayout() {
      if (!this._lazyCalculateLayout) {
        this._lazyCalculateLayout = throttle(() => {
          this.calculateLayout();
        }, 50, { leading: false, trailing: true });
      }
      this._lazyCalculateLayout();
    },
    syncRect() {
      this.calculateLayout();
    }
  },
  events: {
    "element.loaded"(model) {
      if (this.loadDfd) {
        this.loadDfd.check(model);
      }
    },
    "element.loadError"(ex, model) {
      if (this.loadDfd) {
        this.loadDfd.check(model);
      }
      return true;
    },
    "element.rectUpdate"(currModel, delta = { width: 0, height: 0 }) {
      const { model, resizing } = this;
      const { elements } = model;
      if (resizing)
        return;
      if (elements.indexOf(currModel) >= 0) {
        this.calculateLayout(delta);
      }
    },
    "group.contentScale"(model, ratio) {
      if (model === this.model) {
        this.scaleGroup(ratio, ratio);
      }
    },
    "element.transformStart"(model, data) {
      this.transforming = true;
      if (model !== this.model) {
        return;
      }
      this.resizeInit(data);
    },
    "element.transformResize"(drag, model) {
      if (model !== this.model) {
        return;
      }
      this.syncMargin();
      this.lazyCalculateLayout();
      this.resize(drag);
    },
    "element.transformEnd"(model) {
      if (model === this.model) {
        this.transforming = false;
        this.resizeEnd();
        this.syncMargin();
        this.lazyCalculateLayout();
      }
    }
  },
  mounted() {
    this.shadow = new FlexShadow(this.$refs.shadowContainer);
    this.model.$getResizeLimit = () => ({
      maxWidth: Infinity,
      minWidth: 20,
      maxHeight: Infinity,
      minHeight: 20
    });
    this.$watch(function() {
      return [this.shadowRoot, this.shadowModels];
    }, function() {
      if (!this.editor.global.$draging) {
        this.calculateLayout();
      }
    });
  }
});
var index = {
  model: FlexModel,
  methods,
  layoutComponent: FlexElement
};
export { index as default };
