"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const index_esm = require("../../min-dash/dist/index.esm.js");
function N() {
}
N.prototype.get = function(e) {
  return this.$model.properties.get(this, e);
};
N.prototype.set = function(e, t) {
  this.$model.properties.set(this, e, t);
};
function P(e, t) {
  this.model = e, this.properties = t;
}
P.prototype.createType = function(e) {
  var t = this.model, r = this.properties, i = Object.create(N.prototype);
  index_esm.forEach(e.properties, function(o) {
    !o.isMany && o.default !== void 0 && (i[o.name] = o.default);
  }), r.defineModel(i, t), r.defineDescriptor(i, e);
  var s = e.ns.name;
  function n(o) {
    r.define(this, "$type", { value: s, enumerable: true }), r.define(this, "$attrs", { value: {} }), r.define(this, "$parent", { writable: true }), index_esm.forEach(o, index_esm.bind(function(a, c) {
      this.set(c, a);
    }, this));
  }
  return n.prototype = i, n.hasType = i.$instanceOf = this.model.hasType, r.defineModel(n, t), r.defineDescriptor(n, e), n;
};
var D = {
  String: true,
  Boolean: true,
  Integer: true,
  Real: true,
  Element: true
}, T = {
  String: function(e) {
    return e;
  },
  Boolean: function(e) {
    return e === "true";
  },
  Integer: function(e) {
    return parseInt(e, 10);
  },
  Real: function(e) {
    return parseFloat(e);
  }
};
function S(e, t) {
  var r = T[e];
  return r ? r(t) : t;
}
function v(e) {
  return !!D[e];
}
function C(e) {
  return !!T[e];
}
function u(e, t) {
  var r = e.split(/:/), i, s;
  if (r.length === 1)
    i = e, s = t;
  else if (r.length === 2)
    i = r[1], s = r[0];
  else
    throw new Error("expected <prefix:localName> or <localName>, got " + e);
  return e = (s ? s + ":" : "") + i, {
    name: e,
    prefix: s,
    localName: i
  };
}
function p(e) {
  this.ns = e, this.name = e.name, this.allTypes = [], this.allTypesByName = {}, this.properties = [], this.propertiesByName = {};
}
p.prototype.build = function() {
  return index_esm.pick(this, [
    "ns",
    "name",
    "allTypes",
    "allTypesByName",
    "properties",
    "propertiesByName",
    "bodyProperty",
    "idProperty"
  ]);
};
p.prototype.addProperty = function(e, t, r) {
  typeof t == "boolean" && (r = t, t = void 0), this.addNamedProperty(e, r !== false);
  var i = this.properties;
  t !== void 0 ? i.splice(t, 0, e) : i.push(e);
};
p.prototype.replaceProperty = function(e, t, r) {
  var i = e.ns, s = this.properties, n = this.propertiesByName, o = e.name !== t.name;
  if (e.isId) {
    if (!t.isId)
      throw new Error(
        "property <" + t.ns.name + "> must be id property to refine <" + e.ns.name + ">"
      );
    this.setIdProperty(t, false);
  }
  if (e.isBody) {
    if (!t.isBody)
      throw new Error(
        "property <" + t.ns.name + "> must be body property to refine <" + e.ns.name + ">"
      );
    this.setBodyProperty(t, false);
  }
  var a = s.indexOf(e);
  if (a === -1)
    throw new Error("property <" + i.name + "> not found in property list");
  s.splice(a, 1), this.addProperty(t, r ? void 0 : a, o), n[i.name] = n[i.localName] = t;
};
p.prototype.redefineProperty = function(e, t, r) {
  var i = e.ns.prefix, s = t.split("#"), n = u(s[0], i), o = u(s[1], n.prefix).name, a = this.propertiesByName[o];
  if (a)
    this.replaceProperty(a, e, r);
  else
    throw new Error("refined property <" + o + "> not found");
  delete e.redefines;
};
p.prototype.addNamedProperty = function(e, t) {
  var r = e.ns, i = this.propertiesByName;
  t && (this.assertNotDefined(e, r.name), this.assertNotDefined(e, r.localName)), i[r.name] = i[r.localName] = e;
};
p.prototype.removeNamedProperty = function(e) {
  var t = e.ns, r = this.propertiesByName;
  delete r[t.name], delete r[t.localName];
};
p.prototype.setBodyProperty = function(e, t) {
  if (t && this.bodyProperty)
    throw new Error(
      "body property defined multiple times (<" + this.bodyProperty.ns.name + ">, <" + e.ns.name + ">)"
    );
  this.bodyProperty = e;
};
p.prototype.setIdProperty = function(e, t) {
  if (t && this.idProperty)
    throw new Error(
      "id property defined multiple times (<" + this.idProperty.ns.name + ">, <" + e.ns.name + ">)"
    );
  this.idProperty = e;
};
p.prototype.assertNotTrait = function(e) {
  if ((e.extends || []).length)
    throw new Error(
      `cannot create <${e.name}> extending <${e.extends}>`
    );
};
p.prototype.assertNotDefined = function(e, t) {
  var r = e.name, i = this.propertiesByName[r];
  if (i)
    throw new Error(
      "property <" + r + "> already defined; override of <" + i.definedBy.ns.name + "#" + i.ns.name + "> by <" + e.definedBy.ns.name + "#" + e.ns.name + "> not allowed without redefines"
    );
};
p.prototype.hasProperty = function(e) {
  return this.propertiesByName[e];
};
p.prototype.addTrait = function(e, t) {
  t && this.assertNotTrait(e);
  var r = this.allTypesByName, i = this.allTypes, s = e.name;
  s in r || (index_esm.forEach(e.properties, index_esm.bind(function(n) {
    n = index_esm.assign({}, n, {
      name: n.ns.localName,
      inherited: t
    }), Object.defineProperty(n, "definedBy", {
      value: e
    });
    var o = n.replaces, a = n.redefines;
    o || a ? this.redefineProperty(n, o || a, o) : (n.isBody && this.setBodyProperty(n), n.isId && this.setIdProperty(n), this.addProperty(n));
  }, this)), i.push(e), r[s] = e);
};
function l(e, t) {
  this.packageMap = {}, this.typeMap = {}, this.packages = [], this.properties = t, index_esm.forEach(e, index_esm.bind(this.registerPackage, this));
}
l.prototype.getPackage = function(e) {
  return this.packageMap[e];
};
l.prototype.getPackages = function() {
  return this.packages;
};
l.prototype.registerPackage = function(e) {
  e = index_esm.assign({}, e);
  var t = this.packageMap;
  w(t, e, "prefix"), w(t, e, "uri"), index_esm.forEach(e.types, index_esm.bind(function(r) {
    this.registerType(r, e);
  }, this)), t[e.uri] = t[e.prefix] = e, this.packages.push(e);
};
l.prototype.registerType = function(e, t) {
  e = index_esm.assign({}, e, {
    superClass: (e.superClass || []).slice(),
    extends: (e.extends || []).slice(),
    properties: (e.properties || []).slice(),
    meta: index_esm.assign(e.meta || {})
  });
  var r = u(e.name, t.prefix), i = r.name, s = {};
  index_esm.forEach(e.properties, index_esm.bind(function(n) {
    var o = u(n.name, r.prefix), a = o.name;
    v(n.type) || (n.type = u(n.type, o.prefix).name), index_esm.assign(n, {
      ns: o,
      name: a
    }), s[a] = n;
  }, this)), index_esm.assign(e, {
    ns: r,
    name: i,
    propertiesByName: s
  }), index_esm.forEach(e.extends, index_esm.bind(function(n) {
    var o = u(n, r.prefix), a = this.typeMap[o.name];
    a.traits = a.traits || [], a.traits.push(i);
  }, this)), this.definePackage(e, t), this.typeMap[i] = e;
};
l.prototype.mapTypes = function(e, t, r) {
  var i = v(e.name) ? { name: e.name } : this.typeMap[e.name], s = this;
  function n(c, x) {
    var E = u(c, v(c) ? "" : e.prefix);
    s.mapTypes(E, t, x);
  }
  function o(c) {
    return n(c, true);
  }
  function a(c) {
    return n(c, false);
  }
  if (!i)
    throw new Error("unknown type <" + e.name + ">");
  index_esm.forEach(i.superClass, r ? o : a), t(i, !r), index_esm.forEach(i.traits, o);
};
l.prototype.getEffectiveDescriptor = function(e) {
  var t = u(e), r = new p(t);
  this.mapTypes(t, function(s, n) {
    r.addTrait(s, n);
  });
  var i = r.build();
  return this.definePackage(i, i.allTypes[i.allTypes.length - 1].$pkg), i;
};
l.prototype.definePackage = function(e, t) {
  this.properties.define(e, "$pkg", { value: t });
};
function w(e, t, r) {
  var i = t[r];
  if (i in e)
    throw new Error("package with " + r + " <" + i + "> already defined");
}
function h(e) {
  this.model = e;
}
h.prototype.set = function(e, t, r) {
  if (!index_esm.isString(t) || !t.length)
    throw new TypeError("property name must be a non-empty string");
  var i = this.getProperty(e, t), s = i && i.name;
  I(r) ? i ? delete e[s] : delete e.$attrs[g(t)] : i ? s in e ? e[s] = r : B(e, i, r) : e.$attrs[g(t)] = r;
};
h.prototype.get = function(e, t) {
  var r = this.getProperty(e, t);
  if (!r)
    return e.$attrs[g(t)];
  var i = r.name;
  return !e[i] && r.isMany && B(e, r, []), e[i];
};
h.prototype.define = function(e, t, r) {
  if (!r.writable) {
    var i = r.value;
    r = index_esm.assign({}, r, {
      get: function() {
        return i;
      }
    }), delete r.value;
  }
  Object.defineProperty(e, t, r);
};
h.prototype.defineDescriptor = function(e, t) {
  this.define(e, "$descriptor", { value: t });
};
h.prototype.defineModel = function(e, t) {
  this.define(e, "$model", { value: t });
};
h.prototype.getProperty = function(e, t) {
  var r = this.model, i = r.getPropertyDescriptor(e, t);
  if (i)
    return i;
  if (t.includes(":"))
    return null;
  const s = r.config.strict;
  if (typeof s < "u") {
    const n = new TypeError(`unknown property <${t}> on <${e.$type}>`);
    if (s)
      throw n;
    typeof console < "u" && console.warn(n);
  }
  return null;
};
function I(e) {
  return typeof e > "u";
}
function B(e, t, r) {
  Object.defineProperty(e, t.name, {
    enumerable: !t.isReference,
    writable: true,
    value: r,
    configurable: true
  });
}
function g(e) {
  return e.replace(/^:/, "");
}
function y(e, t = {}) {
  this.properties = new h(this), this.factory = new P(this, this.properties), this.registry = new l(e, this.properties), this.typeCache = {}, this.config = t;
}
y.prototype.create = function(e, t) {
  var r = this.getType(e);
  if (!r)
    throw new Error("unknown type <" + e + ">");
  return new r(t);
};
y.prototype.getType = function(e) {
  var t = this.typeCache, r = index_esm.isString(e) ? e : e.ns.name, i = t[r];
  return i || (e = this.registry.getEffectiveDescriptor(r), i = t[r] = this.factory.createType(e)), i;
};
y.prototype.createAny = function(e, t, r) {
  var i = u(e), s = {
    $type: e,
    $instanceOf: function(o) {
      return o === this.$type;
    },
    get: function(o) {
      return this[o];
    },
    set: function(o, a) {
      index_esm.set(this, [o], a);
    }
  }, n = {
    name: e,
    isGeneric: true,
    ns: {
      prefix: i.prefix,
      localName: i.localName,
      uri: t
    }
  };
  return this.properties.defineDescriptor(s, n), this.properties.defineModel(s, this), this.properties.define(s, "get", { enumerable: false, writable: true }), this.properties.define(s, "set", { enumerable: false, writable: true }), this.properties.define(s, "$parent", { enumerable: false, writable: true }), this.properties.define(s, "$instanceOf", { enumerable: false, writable: true }), index_esm.forEach(r, function(o, a) {
    index_esm.isObject(o) && o.value !== void 0 ? s[o.name] = o.value : s[a] = o;
  }), s;
};
y.prototype.getPackage = function(e) {
  return this.registry.getPackage(e);
};
y.prototype.getPackages = function() {
  return this.registry.getPackages();
};
y.prototype.getElementDescriptor = function(e) {
  return e.$descriptor;
};
y.prototype.hasType = function(e, t) {
  t === void 0 && (t = e, e = this);
  var r = e.$model.getElementDescriptor(e);
  return t in r.allTypesByName;
};
y.prototype.getPropertyDescriptor = function(e, t) {
  return this.getElementDescriptor(e).propertiesByName[t];
};
y.prototype.getTypeDescriptor = function(e) {
  return this.registry.typeMap[e];
};
exports.Moddle = y;
exports.coerceType = S;
exports.isBuiltInType = v;
exports.isSimpleType = C;
exports.parseNameNS = u;
