'use strict';

var vue = require('vue');
var _interface = require('./interface.js');
var qrcodegen = require('./qrcodegen.js');

const ERROR_LEVEL_MAP = {
  L: qrcodegen.default.QrCode.Ecc.LOW,
  M: qrcodegen.default.QrCode.Ecc.MEDIUM,
  Q: qrcodegen.default.QrCode.Ecc.QUARTILE,
  H: qrcodegen.default.QrCode.Ecc.HIGH
};
const DEFAULT_SIZE = 128;
const DEFAULT_LEVEL = "L";
const DEFAULT_BGCOLOR = "#FFFFFF";
const DEFAULT_FGCOLOR = "#000000";
const DEFAULT_INCLUDEMARGIN = false;
const SPEC_MARGIN_SIZE = 4;
const DEFAULT_MARGIN_SIZE = 0;
const DEFAULT_IMG_SCALE = 0.1;
function generatePath(modules, margin = 0) {
  const ops = [];
  modules.forEach((row, y) => {
    let start = null;
    row.forEach((cell, x) => {
      if (!cell && start !== null) {
        ops.push(`M${start + margin} ${y + margin}h${x - start}v1H${start + margin}z`);
        start = null;
        return;
      }
      if (x === row.length - 1) {
        if (!cell) {
          return;
        }
        if (start === null) {
          ops.push(`M${x + margin},${y + margin} h1v1H${x + margin}z`);
        } else {
          ops.push(`M${start + margin},${y + margin} h${x + 1 - start}v1H${start + margin}z`);
        }
        return;
      }
      if (cell && start === null)
        start = x;
    });
  });
  return ops.join("");
}
function excavateModules(modules, excavation) {
  return modules.slice().map((row, y) => {
    if (y < excavation.y || y >= excavation.y + excavation.h)
      return row;
    return row.map((cell, x) => {
      if (x < excavation.x || x >= excavation.x + excavation.w)
        return cell;
      return false;
    });
  });
}
function getImageSettings(cells, size, margin, imageSettings) {
  if (imageSettings == null)
    return null;
  const numCells = cells.length + margin * 2;
  const defaultSize = Math.floor(size * DEFAULT_IMG_SCALE);
  const scale = numCells / size;
  const w = (imageSettings.width || defaultSize) * scale;
  const h = (imageSettings.height || defaultSize) * scale;
  const x = imageSettings.x == null ? cells.length / 2 - w / 2 : imageSettings.x * scale;
  const y = imageSettings.y == null ? cells.length / 2 - h / 2 : imageSettings.y * scale;
  let excavation = null;
  if (imageSettings.excavate) {
    const floorX = Math.floor(x);
    const floorY = Math.floor(y);
    const ceilW = Math.ceil(w + x - floorX);
    const ceilH = Math.ceil(h + y - floorY);
    excavation = {
      x: floorX,
      y: floorY,
      w: ceilW,
      h: ceilH
    };
  }
  return {
    x,
    y,
    h,
    w,
    excavation
  };
}
function getMarginSize(includeMargin, marginSize) {
  if (marginSize != null)
    return Math.floor(marginSize);
  return includeMargin ? SPEC_MARGIN_SIZE : DEFAULT_MARGIN_SIZE;
}
const SUPPORTS_PATH2D = function() {
  try {
    new Path2D().addPath(new Path2D());
  } catch (e) {
    return false;
  }
  return true;
}();
const QRCodeCanvas = /* @__PURE__ */ vue.defineComponent({
  name: "QRCodeCanvas",
  inheritAttrs: false,
  props: {
    ..._interface.qrProps(),
    level: String,
    bgColor: String,
    fgColor: String,
    marginSize: Number
  },
  setup(props, {
    attrs,
    expose
  }) {
    const imgSrc = vue.computed(() => {
      var _a;
      return (_a = props.imageSettings) == null ? void 0 : _a.src;
    });
    const _canvas = vue.shallowRef(null);
    const _image = vue.shallowRef(null);
    const isImgLoaded = vue.shallowRef(false);
    expose({
      toDataURL: (type, quality) => {
        var _a;
        return (_a = _canvas.value) == null ? void 0 : _a.toDataURL(type, quality);
      }
    });
    vue.watchEffect(() => {
      const {
        value,
        size = DEFAULT_SIZE,
        level = DEFAULT_LEVEL,
        bgColor = DEFAULT_BGCOLOR,
        fgColor = DEFAULT_FGCOLOR,
        includeMargin = DEFAULT_INCLUDEMARGIN,
        marginSize,
        imageSettings
      } = props;
      if (_canvas.value != null) {
        const canvas = _canvas.value;
        const ctx = canvas.getContext("2d");
        if (!ctx)
          return;
        let cells = qrcodegen.default.QrCode.encodeText(value, ERROR_LEVEL_MAP[level]).getModules();
        const margin = getMarginSize(includeMargin, marginSize);
        const numCells = cells.length + margin * 2;
        const calculatedImageSettings = getImageSettings(cells, size, margin, imageSettings);
        const image = _image.value;
        const haveImageToRender = isImgLoaded.value && calculatedImageSettings != null && image !== null && image.complete && image.naturalHeight !== 0 && image.naturalWidth !== 0;
        if (haveImageToRender) {
          if (calculatedImageSettings.excavation != null)
            cells = excavateModules(cells, calculatedImageSettings.excavation);
        }
        const pixelRatio = window.devicePixelRatio || 1;
        canvas.height = canvas.width = size * pixelRatio;
        const scale = size / numCells * pixelRatio;
        ctx.scale(scale, scale);
        ctx.fillStyle = bgColor;
        ctx.fillRect(0, 0, numCells, numCells);
        ctx.fillStyle = fgColor;
        if (SUPPORTS_PATH2D) {
          ctx.fill(new Path2D(generatePath(cells, margin)));
        } else {
          cells.forEach((row, rdx) => {
            row.forEach((cell, cdx) => {
              if (cell)
                ctx.fillRect(cdx + margin, rdx + margin, 1, 1);
            });
          });
        }
        if (haveImageToRender) {
          ctx.drawImage(image, calculatedImageSettings.x + margin, calculatedImageSettings.y + margin, calculatedImageSettings.w, calculatedImageSettings.h);
        }
      }
    }, {
      flush: "post"
    });
    vue.watch(imgSrc, () => {
      isImgLoaded.value = false;
    });
    return () => {
      var _a;
      const size = (_a = props.size) != null ? _a : DEFAULT_SIZE;
      const canvasStyle = {
        height: `${size}px`,
        width: `${size}px`
      };
      let img = null;
      if (imgSrc.value != null) {
        img = vue.createVNode("img", {
          "src": imgSrc.value,
          "key": imgSrc.value,
          "style": {
            display: "none"
          },
          "onLoad": () => {
            isImgLoaded.value = true;
          },
          "ref": _image
        }, null);
      }
      return vue.createVNode(vue.Fragment, null, [vue.createVNode("canvas", vue.mergeProps(attrs, {
        "style": [canvasStyle, attrs.style],
        "ref": _canvas
      }), null), img]);
    };
  }
});

exports.QRCodeCanvas = QRCodeCanvas;
//# sourceMappingURL=QRCodeCanvas.js.map
