import { assign, reduce, forEach, isObject } from "../../../min-dash/dist/index.esm.mjs";
import { create, attr, append, remove } from "../../../tiny-svg/dist/index.esm.mjs";
import { assignStyle as assign$1 } from "../../../min-dom/dist/index.esm.mjs";
var DEFAULT_BOX_PADDING = 0;
var DEFAULT_LABEL_SIZE = {
  width: 150,
  height: 50
};
function parseAlign(align) {
  var parts = align.split("-");
  return {
    horizontal: parts[0] || "center",
    vertical: parts[1] || "top"
  };
}
function parsePadding(padding) {
  if (isObject(padding)) {
    return assign({ top: 0, left: 0, right: 0, bottom: 0 }, padding);
  } else {
    return {
      top: padding,
      left: padding,
      right: padding,
      bottom: padding
    };
  }
}
function getTextBBox(text, fakeText) {
  fakeText.textContent = text;
  var textBBox;
  try {
    var bbox, emptyLine = text === "";
    fakeText.textContent = emptyLine ? "dummy" : text;
    textBBox = fakeText.getBBox();
    bbox = {
      width: textBBox.width + textBBox.x * 2,
      height: textBBox.height
    };
    if (emptyLine) {
      bbox.width = 0;
    }
    return bbox;
  } catch (e) {
    return { width: 0, height: 0 };
  }
}
function layoutNext(lines, maxWidth, fakeText) {
  var originalLine = lines.shift(), fitLine = originalLine;
  var textBBox;
  for (; ; ) {
    textBBox = getTextBBox(fitLine, fakeText);
    textBBox.width = fitLine ? textBBox.width : 0;
    if (fitLine === " " || fitLine === "" || textBBox.width < Math.round(maxWidth) || fitLine.length < 2) {
      return fit(lines, fitLine, originalLine, textBBox);
    }
    fitLine = shortenLine(fitLine, textBBox.width, maxWidth);
  }
}
function fit(lines, fitLine, originalLine, textBBox) {
  if (fitLine.length < originalLine.length) {
    var remainder = originalLine.slice(fitLine.length).trim();
    lines.unshift(remainder);
  }
  return {
    width: textBBox.width,
    height: textBBox.height,
    text: fitLine
  };
}
var SOFT_BREAK = "­";
function semanticShorten(line, maxLength) {
  var parts = line.split(/(\s|-|\u00AD)/g), part, shortenedParts = [], length = 0;
  if (parts.length > 1) {
    while (part = parts.shift()) {
      if (part.length + length < maxLength) {
        shortenedParts.push(part);
        length += part.length;
      } else {
        if (part === "-" || part === SOFT_BREAK) {
          shortenedParts.pop();
        }
        break;
      }
    }
  }
  var last = shortenedParts[shortenedParts.length - 1];
  if (last && last === SOFT_BREAK) {
    shortenedParts[shortenedParts.length - 1] = "-";
  }
  return shortenedParts.join("");
}
function shortenLine(line, width, maxWidth) {
  var length = Math.max(line.length * (maxWidth / width), 1);
  var shortenedLine = semanticShorten(line, length);
  if (!shortenedLine) {
    shortenedLine = line.slice(0, Math.max(Math.round(length - 1), 1));
  }
  return shortenedLine;
}
function getHelperSvg() {
  var helperSvg = document.getElementById("helper-svg");
  if (!helperSvg) {
    helperSvg = create("svg");
    attr(helperSvg, {
      id: "helper-svg"
    });
    assign$1(helperSvg, {
      visibility: "hidden",
      position: "fixed",
      width: 0,
      height: 0
    });
    document.body.appendChild(helperSvg);
  }
  return helperSvg;
}
function Text(config) {
  this._config = assign({}, {
    size: DEFAULT_LABEL_SIZE,
    padding: DEFAULT_BOX_PADDING,
    style: {},
    align: "center-top"
  }, config || {});
}
Text.prototype.createText = function(text, options) {
  return this.layoutText(text, options).element;
};
Text.prototype.getDimensions = function(text, options) {
  return this.layoutText(text, options).dimensions;
};
Text.prototype.layoutText = function(text, options) {
  var box = assign({}, this._config.size, options.box), style = assign({}, this._config.style, options.style), align = parseAlign(options.align || this._config.align), padding = parsePadding(options.padding !== void 0 ? options.padding : this._config.padding), fitBox = options.fitBox || false;
  var lineHeight = getLineHeight(style);
  var lines = text.split(/\u00AD?\r?\n/), layouted = [];
  var maxWidth = box.width - padding.left - padding.right;
  var helperText = create("text");
  attr(helperText, { x: 0, y: 0 });
  attr(helperText, style);
  var helperSvg = getHelperSvg();
  append(helperSvg, helperText);
  while (lines.length) {
    layouted.push(layoutNext(lines, maxWidth, helperText));
  }
  if (align.vertical === "middle") {
    padding.top = padding.bottom = 0;
  }
  var totalHeight = reduce(layouted, function(sum, line, idx) {
    return sum + (lineHeight || line.height);
  }, 0) + padding.top + padding.bottom;
  var maxLineWidth = reduce(layouted, function(sum, line, idx) {
    return line.width > sum ? line.width : sum;
  }, 0);
  var y = padding.top;
  if (align.vertical === "middle") {
    y += (box.height - totalHeight) / 2;
  }
  y -= (lineHeight || layouted[0].height) / 4;
  var textElement = create("text");
  attr(textElement, style);
  forEach(layouted, function(line) {
    var x;
    y += lineHeight || line.height;
    switch (align.horizontal) {
      case "left":
        x = padding.left;
        break;
      case "right":
        x = (fitBox ? maxLineWidth : maxWidth) - padding.right - line.width;
        break;
      default:
        x = Math.max(((fitBox ? maxLineWidth : maxWidth) - line.width) / 2 + padding.left, 0);
    }
    var tspan = create("tspan");
    attr(tspan, { x, y });
    tspan.textContent = line.text;
    append(textElement, tspan);
  });
  remove(helperText);
  var dimensions = {
    width: maxLineWidth,
    height: totalHeight
  };
  return {
    dimensions,
    element: textElement
  };
};
function getLineHeight(style) {
  if ("fontSize" in style && "lineHeight" in style) {
    return style.lineHeight * parseInt(style.fontSize, 10);
  }
}
export {
  Text as default
};
