import {
  Subject
} from "./chunk-VAMMRICA.js";
import {
  __async,
  __commonJS,
  __require,
  __toESM
} from "./chunk-RVA4KI76.js";

// (disabled):crypto
var require_crypto = __commonJS({
  "(disabled):crypto"() {
    "use strict";
  }
});

// node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/core.js
var require_core = __commonJS({
  "node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/core.js"(exports, module) {
    "use strict";
    (function(root, factory) {
      if (typeof exports === "object") {
        module.exports = exports = factory();
      } else if (typeof define === "function" && define.amd) {
        define([], factory);
      } else {
        root.CryptoJS = factory();
      }
    })(exports, function() {
      var CryptoJS = CryptoJS || (function(Math2, undefined2) {
        var crypto;
        if (typeof window !== "undefined" && window.crypto) {
          crypto = window.crypto;
        }
        if (typeof self !== "undefined" && self.crypto) {
          crypto = self.crypto;
        }
        if (typeof globalThis !== "undefined" && globalThis.crypto) {
          crypto = globalThis.crypto;
        }
        if (!crypto && typeof window !== "undefined" && window.msCrypto) {
          crypto = window.msCrypto;
        }
        if (!crypto && typeof global !== "undefined" && global.crypto) {
          crypto = global.crypto;
        }
        if (!crypto && typeof __require === "function") {
          try {
            crypto = require_crypto();
          } catch (err) {
          }
        }
        var cryptoSecureRandomInt = function() {
          if (crypto) {
            if (typeof crypto.getRandomValues === "function") {
              try {
                return crypto.getRandomValues(new Uint32Array(1))[0];
              } catch (err) {
              }
            }
            if (typeof crypto.randomBytes === "function") {
              try {
                return crypto.randomBytes(4).readInt32LE();
              } catch (err) {
              }
            }
          }
          throw new Error("Native crypto module could not be used to get secure random number.");
        };
        var create = Object.create || /* @__PURE__ */ (function() {
          function F() {
          }
          return function(obj) {
            var subtype;
            F.prototype = obj;
            subtype = new F();
            F.prototype = null;
            return subtype;
          };
        })();
        var C = {};
        var C_lib = C.lib = {};
        var Base = C_lib.Base = /* @__PURE__ */ (function() {
          return {
            /**
             * Creates a new object that inherits from this object.
             *
             * @param {Object} overrides Properties to copy into the new object.
             *
             * @return {Object} The new object.
             *
             * @static
             *
             * @example
             *
             *     var MyType = CryptoJS.lib.Base.extend({
             *         field: 'value',
             *
             *         method: function () {
             *         }
             *     });
             */
            extend: function(overrides) {
              var subtype = create(this);
              if (overrides) {
                subtype.mixIn(overrides);
              }
              if (!subtype.hasOwnProperty("init") || this.init === subtype.init) {
                subtype.init = function() {
                  subtype.$super.init.apply(this, arguments);
                };
              }
              subtype.init.prototype = subtype;
              subtype.$super = this;
              return subtype;
            },
            /**
             * Extends this object and runs the init method.
             * Arguments to create() will be passed to init().
             *
             * @return {Object} The new object.
             *
             * @static
             *
             * @example
             *
             *     var instance = MyType.create();
             */
            create: function() {
              var instance = this.extend();
              instance.init.apply(instance, arguments);
              return instance;
            },
            /**
             * Initializes a newly created object.
             * Override this method to add some logic when your objects are created.
             *
             * @example
             *
             *     var MyType = CryptoJS.lib.Base.extend({
             *         init: function () {
             *             // ...
             *         }
             *     });
             */
            init: function() {
            },
            /**
             * Copies properties into this object.
             *
             * @param {Object} properties The properties to mix in.
             *
             * @example
             *
             *     MyType.mixIn({
             *         field: 'value'
             *     });
             */
            mixIn: function(properties) {
              for (var propertyName in properties) {
                if (properties.hasOwnProperty(propertyName)) {
                  this[propertyName] = properties[propertyName];
                }
              }
              if (properties.hasOwnProperty("toString")) {
                this.toString = properties.toString;
              }
            },
            /**
             * Creates a copy of this object.
             *
             * @return {Object} The clone.
             *
             * @example
             *
             *     var clone = instance.clone();
             */
            clone: function() {
              return this.init.prototype.extend(this);
            }
          };
        })();
        var WordArray = C_lib.WordArray = Base.extend({
          /**
           * Initializes a newly created word array.
           *
           * @param {Array} words (Optional) An array of 32-bit words.
           * @param {number} sigBytes (Optional) The number of significant bytes in the words.
           *
           * @example
           *
           *     var wordArray = CryptoJS.lib.WordArray.create();
           *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
           *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
           */
          init: function(words, sigBytes) {
            words = this.words = words || [];
            if (sigBytes != undefined2) {
              this.sigBytes = sigBytes;
            } else {
              this.sigBytes = words.length * 4;
            }
          },
          /**
           * Converts this word array to a string.
           *
           * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
           *
           * @return {string} The stringified word array.
           *
           * @example
           *
           *     var string = wordArray + '';
           *     var string = wordArray.toString();
           *     var string = wordArray.toString(CryptoJS.enc.Utf8);
           */
          toString: function(encoder) {
            return (encoder || Hex).stringify(this);
          },
          /**
           * Concatenates a word array to this word array.
           *
           * @param {WordArray} wordArray The word array to append.
           *
           * @return {WordArray} This word array.
           *
           * @example
           *
           *     wordArray1.concat(wordArray2);
           */
          concat: function(wordArray) {
            var thisWords = this.words;
            var thatWords = wordArray.words;
            var thisSigBytes = this.sigBytes;
            var thatSigBytes = wordArray.sigBytes;
            this.clamp();
            if (thisSigBytes % 4) {
              for (var i = 0; i < thatSigBytes; i++) {
                var thatByte = thatWords[i >>> 2] >>> 24 - i % 4 * 8 & 255;
                thisWords[thisSigBytes + i >>> 2] |= thatByte << 24 - (thisSigBytes + i) % 4 * 8;
              }
            } else {
              for (var j = 0; j < thatSigBytes; j += 4) {
                thisWords[thisSigBytes + j >>> 2] = thatWords[j >>> 2];
              }
            }
            this.sigBytes += thatSigBytes;
            return this;
          },
          /**
           * Removes insignificant bits.
           *
           * @example
           *
           *     wordArray.clamp();
           */
          clamp: function() {
            var words = this.words;
            var sigBytes = this.sigBytes;
            words[sigBytes >>> 2] &= 4294967295 << 32 - sigBytes % 4 * 8;
            words.length = Math2.ceil(sigBytes / 4);
          },
          /**
           * Creates a copy of this word array.
           *
           * @return {WordArray} The clone.
           *
           * @example
           *
           *     var clone = wordArray.clone();
           */
          clone: function() {
            var clone = Base.clone.call(this);
            clone.words = this.words.slice(0);
            return clone;
          },
          /**
           * Creates a word array filled with random bytes.
           *
           * @param {number} nBytes The number of random bytes to generate.
           *
           * @return {WordArray} The random word array.
           *
           * @static
           *
           * @example
           *
           *     var wordArray = CryptoJS.lib.WordArray.random(16);
           */
          random: function(nBytes) {
            var words = [];
            for (var i = 0; i < nBytes; i += 4) {
              words.push(cryptoSecureRandomInt());
            }
            return new WordArray.init(words, nBytes);
          }
        });
        var C_enc = C.enc = {};
        var Hex = C_enc.Hex = {
          /**
           * Converts a word array to a hex string.
           *
           * @param {WordArray} wordArray The word array.
           *
           * @return {string} The hex string.
           *
           * @static
           *
           * @example
           *
           *     var hexString = CryptoJS.enc.Hex.stringify(wordArray);
           */
          stringify: function(wordArray) {
            var words = wordArray.words;
            var sigBytes = wordArray.sigBytes;
            var hexChars = [];
            for (var i = 0; i < sigBytes; i++) {
              var bite = words[i >>> 2] >>> 24 - i % 4 * 8 & 255;
              hexChars.push((bite >>> 4).toString(16));
              hexChars.push((bite & 15).toString(16));
            }
            return hexChars.join("");
          },
          /**
           * Converts a hex string to a word array.
           *
           * @param {string} hexStr The hex string.
           *
           * @return {WordArray} The word array.
           *
           * @static
           *
           * @example
           *
           *     var wordArray = CryptoJS.enc.Hex.parse(hexString);
           */
          parse: function(hexStr) {
            var hexStrLength = hexStr.length;
            var words = [];
            for (var i = 0; i < hexStrLength; i += 2) {
              words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << 24 - i % 8 * 4;
            }
            return new WordArray.init(words, hexStrLength / 2);
          }
        };
        var Latin1 = C_enc.Latin1 = {
          /**
           * Converts a word array to a Latin1 string.
           *
           * @param {WordArray} wordArray The word array.
           *
           * @return {string} The Latin1 string.
           *
           * @static
           *
           * @example
           *
           *     var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
           */
          stringify: function(wordArray) {
            var words = wordArray.words;
            var sigBytes = wordArray.sigBytes;
            var latin1Chars = [];
            for (var i = 0; i < sigBytes; i++) {
              var bite = words[i >>> 2] >>> 24 - i % 4 * 8 & 255;
              latin1Chars.push(String.fromCharCode(bite));
            }
            return latin1Chars.join("");
          },
          /**
           * Converts a Latin1 string to a word array.
           *
           * @param {string} latin1Str The Latin1 string.
           *
           * @return {WordArray} The word array.
           *
           * @static
           *
           * @example
           *
           *     var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
           */
          parse: function(latin1Str) {
            var latin1StrLength = latin1Str.length;
            var words = [];
            for (var i = 0; i < latin1StrLength; i++) {
              words[i >>> 2] |= (latin1Str.charCodeAt(i) & 255) << 24 - i % 4 * 8;
            }
            return new WordArray.init(words, latin1StrLength);
          }
        };
        var Utf8 = C_enc.Utf8 = {
          /**
           * Converts a word array to a UTF-8 string.
           *
           * @param {WordArray} wordArray The word array.
           *
           * @return {string} The UTF-8 string.
           *
           * @static
           *
           * @example
           *
           *     var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
           */
          stringify: function(wordArray) {
            try {
              return decodeURIComponent(escape(Latin1.stringify(wordArray)));
            } catch (e) {
              throw new Error("Malformed UTF-8 data");
            }
          },
          /**
           * Converts a UTF-8 string to a word array.
           *
           * @param {string} utf8Str The UTF-8 string.
           *
           * @return {WordArray} The word array.
           *
           * @static
           *
           * @example
           *
           *     var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
           */
          parse: function(utf8Str) {
            return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
          }
        };
        var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
          /**
           * Resets this block algorithm's data buffer to its initial state.
           *
           * @example
           *
           *     bufferedBlockAlgorithm.reset();
           */
          reset: function() {
            this._data = new WordArray.init();
            this._nDataBytes = 0;
          },
          /**
           * Adds new data to this block algorithm's buffer.
           *
           * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
           *
           * @example
           *
           *     bufferedBlockAlgorithm._append('data');
           *     bufferedBlockAlgorithm._append(wordArray);
           */
          _append: function(data) {
            if (typeof data == "string") {
              data = Utf8.parse(data);
            }
            this._data.concat(data);
            this._nDataBytes += data.sigBytes;
          },
          /**
           * Processes available data blocks.
           *
           * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
           *
           * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
           *
           * @return {WordArray} The processed data.
           *
           * @example
           *
           *     var processedData = bufferedBlockAlgorithm._process();
           *     var processedData = bufferedBlockAlgorithm._process(!!'flush');
           */
          _process: function(doFlush) {
            var processedWords;
            var data = this._data;
            var dataWords = data.words;
            var dataSigBytes = data.sigBytes;
            var blockSize = this.blockSize;
            var blockSizeBytes = blockSize * 4;
            var nBlocksReady = dataSigBytes / blockSizeBytes;
            if (doFlush) {
              nBlocksReady = Math2.ceil(nBlocksReady);
            } else {
              nBlocksReady = Math2.max((nBlocksReady | 0) - this._minBufferSize, 0);
            }
            var nWordsReady = nBlocksReady * blockSize;
            var nBytesReady = Math2.min(nWordsReady * 4, dataSigBytes);
            if (nWordsReady) {
              for (var offset = 0; offset < nWordsReady; offset += blockSize) {
                this._doProcessBlock(dataWords, offset);
              }
              processedWords = dataWords.splice(0, nWordsReady);
              data.sigBytes -= nBytesReady;
            }
            return new WordArray.init(processedWords, nBytesReady);
          },
          /**
           * Creates a copy of this object.
           *
           * @return {Object} The clone.
           *
           * @example
           *
           *     var clone = bufferedBlockAlgorithm.clone();
           */
          clone: function() {
            var clone = Base.clone.call(this);
            clone._data = this._data.clone();
            return clone;
          },
          _minBufferSize: 0
        });
        var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
          /**
           * Configuration options.
           */
          cfg: Base.extend(),
          /**
           * Initializes a newly created hasher.
           *
           * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
           *
           * @example
           *
           *     var hasher = CryptoJS.algo.SHA256.create();
           */
          init: function(cfg) {
            this.cfg = this.cfg.extend(cfg);
            this.reset();
          },
          /**
           * Resets this hasher to its initial state.
           *
           * @example
           *
           *     hasher.reset();
           */
          reset: function() {
            BufferedBlockAlgorithm.reset.call(this);
            this._doReset();
          },
          /**
           * Updates this hasher with a message.
           *
           * @param {WordArray|string} messageUpdate The message to append.
           *
           * @return {Hasher} This hasher.
           *
           * @example
           *
           *     hasher.update('message');
           *     hasher.update(wordArray);
           */
          update: function(messageUpdate) {
            this._append(messageUpdate);
            this._process();
            return this;
          },
          /**
           * Finalizes the hash computation.
           * Note that the finalize operation is effectively a destructive, read-once operation.
           *
           * @param {WordArray|string} messageUpdate (Optional) A final message update.
           *
           * @return {WordArray} The hash.
           *
           * @example
           *
           *     var hash = hasher.finalize();
           *     var hash = hasher.finalize('message');
           *     var hash = hasher.finalize(wordArray);
           */
          finalize: function(messageUpdate) {
            if (messageUpdate) {
              this._append(messageUpdate);
            }
            var hash = this._doFinalize();
            return hash;
          },
          blockSize: 512 / 32,
          /**
           * Creates a shortcut function to a hasher's object interface.
           *
           * @param {Hasher} hasher The hasher to create a helper for.
           *
           * @return {Function} The shortcut function.
           *
           * @static
           *
           * @example
           *
           *     var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
           */
          _createHelper: function(hasher) {
            return function(message, cfg) {
              return new hasher.init(cfg).finalize(message);
            };
          },
          /**
           * Creates a shortcut function to the HMAC's object interface.
           *
           * @param {Hasher} hasher The hasher to use in this HMAC helper.
           *
           * @return {Function} The shortcut function.
           *
           * @static
           *
           * @example
           *
           *     var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
           */
          _createHmacHelper: function(hasher) {
            return function(message, key) {
              return new C_algo.HMAC.init(hasher, key).finalize(message);
            };
          }
        });
        var C_algo = C.algo = {};
        return C;
      })(Math);
      return CryptoJS;
    });
  }
});

// node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha256.js
var require_sha256 = __commonJS({
  "node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha256.js"(exports, module) {
    "use strict";
    (function(root, factory) {
      if (typeof exports === "object") {
        module.exports = exports = factory(require_core());
      } else if (typeof define === "function" && define.amd) {
        define(["./core"], factory);
      } else {
        factory(root.CryptoJS);
      }
    })(exports, function(CryptoJS) {
      (function(Math2) {
        var C = CryptoJS;
        var C_lib = C.lib;
        var WordArray = C_lib.WordArray;
        var Hasher = C_lib.Hasher;
        var C_algo = C.algo;
        var H = [];
        var K = [];
        (function() {
          function isPrime(n2) {
            var sqrtN = Math2.sqrt(n2);
            for (var factor = 2; factor <= sqrtN; factor++) {
              if (!(n2 % factor)) {
                return false;
              }
            }
            return true;
          }
          function getFractionalBits(n2) {
            return (n2 - (n2 | 0)) * 4294967296 | 0;
          }
          var n = 2;
          var nPrime = 0;
          while (nPrime < 64) {
            if (isPrime(n)) {
              if (nPrime < 8) {
                H[nPrime] = getFractionalBits(Math2.pow(n, 1 / 2));
              }
              K[nPrime] = getFractionalBits(Math2.pow(n, 1 / 3));
              nPrime++;
            }
            n++;
          }
        })();
        var W = [];
        var SHA256 = C_algo.SHA256 = Hasher.extend({
          _doReset: function() {
            this._hash = new WordArray.init(H.slice(0));
          },
          _doProcessBlock: function(M, offset) {
            var H2 = this._hash.words;
            var a = H2[0];
            var b = H2[1];
            var c = H2[2];
            var d = H2[3];
            var e = H2[4];
            var f = H2[5];
            var g = H2[6];
            var h = H2[7];
            for (var i = 0; i < 64; i++) {
              if (i < 16) {
                W[i] = M[offset + i] | 0;
              } else {
                var gamma0x = W[i - 15];
                var gamma0 = (gamma0x << 25 | gamma0x >>> 7) ^ (gamma0x << 14 | gamma0x >>> 18) ^ gamma0x >>> 3;
                var gamma1x = W[i - 2];
                var gamma1 = (gamma1x << 15 | gamma1x >>> 17) ^ (gamma1x << 13 | gamma1x >>> 19) ^ gamma1x >>> 10;
                W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
              }
              var ch = e & f ^ ~e & g;
              var maj = a & b ^ a & c ^ b & c;
              var sigma0 = (a << 30 | a >>> 2) ^ (a << 19 | a >>> 13) ^ (a << 10 | a >>> 22);
              var sigma1 = (e << 26 | e >>> 6) ^ (e << 21 | e >>> 11) ^ (e << 7 | e >>> 25);
              var t1 = h + sigma1 + ch + K[i] + W[i];
              var t2 = sigma0 + maj;
              h = g;
              g = f;
              f = e;
              e = d + t1 | 0;
              d = c;
              c = b;
              b = a;
              a = t1 + t2 | 0;
            }
            H2[0] = H2[0] + a | 0;
            H2[1] = H2[1] + b | 0;
            H2[2] = H2[2] + c | 0;
            H2[3] = H2[3] + d | 0;
            H2[4] = H2[4] + e | 0;
            H2[5] = H2[5] + f | 0;
            H2[6] = H2[6] + g | 0;
            H2[7] = H2[7] + h | 0;
          },
          _doFinalize: function() {
            var data = this._data;
            var dataWords = data.words;
            var nBitsTotal = this._nDataBytes * 8;
            var nBitsLeft = data.sigBytes * 8;
            dataWords[nBitsLeft >>> 5] |= 128 << 24 - nBitsLeft % 32;
            dataWords[(nBitsLeft + 64 >>> 9 << 4) + 14] = Math2.floor(nBitsTotal / 4294967296);
            dataWords[(nBitsLeft + 64 >>> 9 << 4) + 15] = nBitsTotal;
            data.sigBytes = dataWords.length * 4;
            this._process();
            return this._hash;
          },
          clone: function() {
            var clone = Hasher.clone.call(this);
            clone._hash = this._hash.clone();
            return clone;
          }
        });
        C.SHA256 = Hasher._createHelper(SHA256);
        C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
      })(Math);
      return CryptoJS.SHA256;
    });
  }
});

// node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/hmac.js
var require_hmac = __commonJS({
  "node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/hmac.js"(exports, module) {
    "use strict";
    (function(root, factory) {
      if (typeof exports === "object") {
        module.exports = exports = factory(require_core());
      } else if (typeof define === "function" && define.amd) {
        define(["./core"], factory);
      } else {
        factory(root.CryptoJS);
      }
    })(exports, function(CryptoJS) {
      (function() {
        var C = CryptoJS;
        var C_lib = C.lib;
        var Base = C_lib.Base;
        var C_enc = C.enc;
        var Utf8 = C_enc.Utf8;
        var C_algo = C.algo;
        var HMAC = C_algo.HMAC = Base.extend({
          /**
           * Initializes a newly created HMAC.
           *
           * @param {Hasher} hasher The hash algorithm to use.
           * @param {WordArray|string} key The secret key.
           *
           * @example
           *
           *     var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
           */
          init: function(hasher, key) {
            hasher = this._hasher = new hasher.init();
            if (typeof key == "string") {
              key = Utf8.parse(key);
            }
            var hasherBlockSize = hasher.blockSize;
            var hasherBlockSizeBytes = hasherBlockSize * 4;
            if (key.sigBytes > hasherBlockSizeBytes) {
              key = hasher.finalize(key);
            }
            key.clamp();
            var oKey = this._oKey = key.clone();
            var iKey = this._iKey = key.clone();
            var oKeyWords = oKey.words;
            var iKeyWords = iKey.words;
            for (var i = 0; i < hasherBlockSize; i++) {
              oKeyWords[i] ^= 1549556828;
              iKeyWords[i] ^= 909522486;
            }
            oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes;
            this.reset();
          },
          /**
           * Resets this HMAC to its initial state.
           *
           * @example
           *
           *     hmacHasher.reset();
           */
          reset: function() {
            var hasher = this._hasher;
            hasher.reset();
            hasher.update(this._iKey);
          },
          /**
           * Updates this HMAC with a message.
           *
           * @param {WordArray|string} messageUpdate The message to append.
           *
           * @return {HMAC} This HMAC instance.
           *
           * @example
           *
           *     hmacHasher.update('message');
           *     hmacHasher.update(wordArray);
           */
          update: function(messageUpdate) {
            this._hasher.update(messageUpdate);
            return this;
          },
          /**
           * Finalizes the HMAC computation.
           * Note that the finalize operation is effectively a destructive, read-once operation.
           *
           * @param {WordArray|string} messageUpdate (Optional) A final message update.
           *
           * @return {WordArray} The HMAC.
           *
           * @example
           *
           *     var hmac = hmacHasher.finalize();
           *     var hmac = hmacHasher.finalize('message');
           *     var hmac = hmacHasher.finalize(wordArray);
           */
          finalize: function(messageUpdate) {
            var hasher = this._hasher;
            var innerHash = hasher.finalize(messageUpdate);
            hasher.reset();
            var hmac = hasher.finalize(this._oKey.clone().concat(innerHash));
            return hmac;
          }
        });
      })();
    });
  }
});

// node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/hmac-sha256.js
var require_hmac_sha256 = __commonJS({
  "node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/hmac-sha256.js"(exports, module) {
    "use strict";
    (function(root, factory, undef) {
      if (typeof exports === "object") {
        module.exports = exports = factory(require_core(), require_sha256(), require_hmac());
      } else if (typeof define === "function" && define.amd) {
        define(["./core", "./sha256", "./hmac"], factory);
      } else {
        factory(root.CryptoJS);
      }
    })(exports, function(CryptoJS) {
      return CryptoJS.HmacSHA256;
    });
  }
});

// src/app/shared/helpers/methods/methods.ts
var import_hmac_sha256 = __toESM(require_hmac_sha256());
function generateId() {
  const guid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
    const r = Math.random() * 16 | 0;
    const v = c === "x" ? r : r & 3 | 8;
    return v.toString(16);
  });
  return guid;
}
function generateDeterministicId(input) {
  let hash = 5381;
  for (let i = 0; i < input.length; i++) {
    const char = input.charCodeAt(i);
    hash = (hash << 5) + hash + char & 4294967295;
  }
  const seed = hash >>> 0;
  let state = seed % 2147483647;
  if (state <= 0)
    state += 2147483646;
  const nextInt = (bound) => {
    state = state * 16807 % 2147483647;
    return Math.floor((state - 1) / 2147483646 * bound);
  };
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
    let r;
    if (c === "x") {
      r = nextInt(16);
    } else {
      r = nextInt(16) & 3 | 8;
    }
    return r.toString(16);
  });
}
function hashString(str) {
  const payloadString = JSON.stringify(str);
  const hmac = (0, import_hmac_sha256.default)("sha256", payloadString).toString();
  return hmac;
}
function deepClone(obj, seen = /* @__PURE__ */ new WeakMap()) {
  if (obj === null || typeof obj !== "object" || obj instanceof Blob) {
    return obj;
  }
  if (Array.isArray(obj) && obj.every((item) => typeof item !== "object" && typeof item !== "function")) {
    return [...obj];
  }
  if (seen.has(obj)) {
    const rawObj = obj;
    if (rawObj._finalizers == null && rawObj.observers == null) {
      return seen.get(obj);
    } else {
      return void 0;
    }
  }
  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }
  if (obj instanceof Map) {
    const clone2 = /* @__PURE__ */ new Map();
    seen.set(obj, clone2);
    obj.forEach((value, key) => {
      if (typeof value !== "function") {
        clone2.set(deepClone(key, seen), deepClone(value, seen));
      }
    });
    return clone2;
  }
  if (obj instanceof Set) {
    const clone2 = /* @__PURE__ */ new Set();
    seen.set(obj, clone2);
    obj.forEach((value) => {
      if (typeof value !== "function") {
        clone2.add(deepClone(value, seen));
      }
    });
    return clone2;
  }
  if (Array.isArray(obj)) {
    const clone2 = [];
    seen.set(obj, clone2);
    for (let i = 0; i < obj.length; i++) {
      if (typeof obj[i] !== "function") {
        clone2[i] = deepClone(obj[i], seen);
      }
    }
    return clone2;
  }
  const clone = {};
  seen.set(obj, clone);
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      const value = obj[key];
      if (typeof value !== "function") {
        clone[key] = deepClone(value, seen);
      }
    }
  }
  return clone;
}
function getDateOnly(date, local = true) {
  if (local) {
    return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
  } else {
    return date.toISOString().slice(0, 16);
  }
}
function safePrice(price) {
  return Math.round(price * 100) / 100;
}
function safeEquivalentPrice(price) {
  return Math.ceil(price * 100) / 100;
}

// src/app/shared/entities/models/attributes.ts
var EntityAttribute = class {
  /* Local */
  get valid() {
    return this.values.length > 0 || this.disabled;
  }
  get shouldHide() {
    return this.hidden || this.hiddenByRule;
  }
  constructor(id, name, customerFacing, possibleValues, type, displayOrder = 0, defaultValue = void 0, hidden = false, rules = [], values = void 0, functionName = void 0) {
    this.id = "";
    this.name = "";
    this.possibleValues = [];
    this.customerFacing = true;
    this.type = EntityAttributeType.Select;
    this.displayOrder = 0;
    this.rules = [];
    this.values = [];
    this.disabled = false;
    this.hidden = false;
    this.hiddenByRule = false;
    this.touched = false;
    this.storing = false;
    this.appliedRules = [];
    this.valueChanged$ = new Subject();
    this.id = id;
    this.name = name;
    this.possibleValues = possibleValues;
    this.defaultValue = defaultValue;
    this.hidden = hidden;
    this.type = type;
    this.displayOrder = displayOrder;
    this.rules = rules;
    this.customerFacing = customerFacing;
    this.functionName = functionName;
    this.valueChanged$ = new Subject();
    if (values != null && values.length > 0) {
      this.values = values;
    } else if (defaultValue != null) {
      if (defaultValue.toLocaleLowerCase() == "yes") {
        this.values[0] = "true";
      } else if (defaultValue.toLocaleLowerCase() == "no") {
        this.values[0] = "false";
      } else if (this.defaultValue != null) {
        this.values[0] = this.defaultValue;
      }
    }
  }
  toJSON() {
    var values = [];
    this.values.forEach((value) => {
      if (value != null) {
        const strValue = value.toString();
        values.push(strValue);
      }
    });
    return {
      id: this.id,
      name: this.name,
      customerFacing: this.customerFacing,
      possibleValues: this.possibleValues,
      defaultValue: this.defaultValue,
      functionName: this.functionName,
      type: this.type,
      displayOrder: this.displayOrder,
      lastUpdated_Utc: this.lastUpdated_Utc,
      rules: this.rules,
      values,
      disabled: this.disabled,
      hidden: this.hidden
    };
  }
};
var EntityAttributeType;
(function(EntityAttributeType2) {
  EntityAttributeType2["Boolean"] = "Boolean";
  EntityAttributeType2["Select"] = "Select";
  EntityAttributeType2["MultiSelect"] = "MultiSelect";
  EntityAttributeType2["Number"] = "Number";
  EntityAttributeType2["Input"] = "Input";
})(EntityAttributeType || (EntityAttributeType = {}));

// src/app/shared/properties/models/property.ts
var Property = class {
  constructor() {
    this.id = "";
    this.yearBuilt = 1900;
    this.existingPipeTypes = [];
    this.foundationTypes = [];
    this.listedBathrooms = 0;
    this.listedStories = 0;
    this.listedSquareDimensions = 0;
    this.dimensionsMeasurementType = MeasurementUnitType.Feet;
  }
};
var MeasurementUnitType;
(function(MeasurementUnitType2) {
  MeasurementUnitType2["Feet"] = "Feet";
  MeasurementUnitType2["Meters"] = "Meters";
})(MeasurementUnitType || (MeasurementUnitType = {}));
var PropertyEntityRenderDimensions = class {
  get transform() {
    return `translate3d(${this.x}px,${this.y}px,0)`;
  }
  get widthCss() {
    return `${this.width}px`;
  }
  get heightCss() {
    return `${this.height}px`;
  }
  constructor(x, y, width, height, rotation) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.rotation = rotation;
  }
};
var PropertyEntity = class {
  constructor(id, entityId, type, name, attributes = [], fixtures = []) {
    this.id = "";
    this.entityId = "";
    this.type = PropertyEntityType.Property;
    this.attributes = [];
    this.entities = [];
    this.fixtures = [];
    this.rules = [];
    this.id = id;
    this.entityId = entityId;
    this.type = type;
    this.name = name;
    const newAttributes = [];
    attributes.forEach((attribute) => {
      const newAttribute = new EntityAttribute(attribute.id, attribute.name, attribute.customerFacing, attribute.possibleValues, attribute.type, attribute.displayOrder, attribute.defaultValue, attribute.hidden, attribute.rules, attribute.values, attribute.functionName);
      newAttributes.push(newAttribute);
    });
    this.attributes = newAttributes;
    this.fixtures = fixtures;
  }
};
var WallType;
(function(WallType2) {
  WallType2["Interior"] = "Interior";
  WallType2["Exterior"] = "Exterior";
  WallType2["Absent"] = "Absent";
  WallType2["Missing"] = "Missing";
})(WallType || (WallType = {}));
var PropertyEntityType;
(function(PropertyEntityType2) {
  PropertyEntityType2["Property"] = "Property";
  PropertyEntityType2["Unit"] = "Unit";
  PropertyEntityType2["Structure"] = "Structure";
  PropertyEntityType2["Floor"] = "Floor";
  PropertyEntityType2["Room"] = "Room";
  PropertyEntityType2["Job"] = "Job";
})(PropertyEntityType || (PropertyEntityType = {}));

// src/app/shared/appointments/models/rendering.ts
var RenderDimensions = class {
  get transform() {
    return `translate3d(${this.x}px,${this.y}px,0)`;
  }
  get widthCss() {
    return `${this.width}px`;
  }
  get heightCss() {
    return `${this.height}px`;
  }
  constructor(x, y, width, height, rotation) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.rotation = rotation;
  }
};

// src/app/shared/payments/models/payment.ts
var PaymentSetting = class {
  constructor() {
    this.id = "";
    this.defaultNumberOfPayments = 1;
    this.minimumPayments = 1;
    this.details = [];
    this.methods = [];
  }
};
var PaymentDetail = class {
  constructor(detail, amount = 0) {
    this.id = "";
    this.name = "";
    this.priority = 0;
    this.minimumAmount = 0;
    this.lenderAmounts = [];
    this.defaultPercent = 0;
    this.amount = 0;
    this.canEditAmount = false;
    this.updatedAmount$ = new Subject();
    this.id = detail.id;
    this.name = detail.name;
    this.priority = detail.priority;
    this.minimumAmount = detail.minimumAmount;
    this.maximumAmount = detail.maximumAmount;
    this.defaultPercent = detail.defaultPercent;
    this.amount = amount;
  }
  toJSON() {
    return {
      id: this.id,
      name: this.name,
      priority: this.priority,
      minimumAmount: this.minimumAmount,
      maximumAmount: this.maximumAmount,
      defaultPercent: this.defaultPercent,
      amount: this.amount
    };
  }
};
var PaymentMethod = class {
  constructor() {
    this.id = "";
    this.name = "";
    this.type = PaymentMethodType.None;
    this.added = false;
  }
};
var PaymentMethodType;
(function(PaymentMethodType2) {
  PaymentMethodType2["None"] = "None";
  PaymentMethodType2["Cash"] = "Cash";
  PaymentMethodType2["Debit"] = "Debit";
  PaymentMethodType2["Credit"] = "Credit";
  PaymentMethodType2["EPayment"] = "EPayment";
  PaymentMethodType2["ACH"] = "ACH";
  PaymentMethodType2["EFT"] = "EFT";
  PaymentMethodType2["Check"] = "Check";
  PaymentMethodType2["Financing"] = "Financing";
})(PaymentMethodType || (PaymentMethodType = {}));
var Payment = class {
  constructor(id, method, status = PaymentStatus.Initiated, amount = 0, iso4217 = "USD", appliedManually = false) {
    this.id = "";
    this.appliedManually = false;
    this.iso4217 = "USD";
    this.status = PaymentStatus.Initiated;
    this.id = id;
    this.paymentMethodId = method.id;
    this.status = status;
    this.amount = amount;
    this.iso4217 = iso4217;
    this.appliedManually = appliedManually;
    this.timeStamp_Utc = new Date(Date.UTC((/* @__PURE__ */ new Date()).getUTCFullYear(), (/* @__PURE__ */ new Date()).getUTCMonth(), (/* @__PURE__ */ new Date()).getUTCDate(), (/* @__PURE__ */ new Date()).getUTCHours(), (/* @__PURE__ */ new Date()).getUTCMinutes(), (/* @__PURE__ */ new Date()).getUTCSeconds()));
  }
};
var PaymentStatus;
(function(PaymentStatus2) {
  PaymentStatus2["Initiated"] = "Initiated";
  PaymentStatus2["Completed"] = "Completed";
})(PaymentStatus || (PaymentStatus = {}));

// node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/util.js
function resolveUrl(url, baseUrl) {
  if (url.match(/^[a-z]+:\/\//i)) {
    return url;
  }
  if (url.match(/^\/\//)) {
    return window.location.protocol + url;
  }
  if (url.match(/^[a-z]+:/i)) {
    return url;
  }
  const doc = document.implementation.createHTMLDocument();
  const base = doc.createElement("base");
  const a = doc.createElement("a");
  doc.head.appendChild(base);
  doc.body.appendChild(a);
  if (baseUrl) {
    base.href = baseUrl;
  }
  a.href = url;
  return a.href;
}
var uuid = /* @__PURE__ */ (() => {
  let counter = 0;
  const random = () => (
    // eslint-disable-next-line no-bitwise
    `0000${(Math.random() * 36 ** 4 << 0).toString(36)}`.slice(-4)
  );
  return () => {
    counter += 1;
    return `u${random()}${counter}`;
  };
})();
function toArray(arrayLike) {
  const arr = [];
  for (let i = 0, l = arrayLike.length; i < l; i++) {
    arr.push(arrayLike[i]);
  }
  return arr;
}
var styleProps = null;
function getStyleProperties(options = {}) {
  if (styleProps) {
    return styleProps;
  }
  if (options.includeStyleProperties) {
    styleProps = options.includeStyleProperties;
    return styleProps;
  }
  styleProps = toArray(window.getComputedStyle(document.documentElement));
  return styleProps;
}
function px(node, styleProperty) {
  const win = node.ownerDocument.defaultView || window;
  const val = win.getComputedStyle(node).getPropertyValue(styleProperty);
  return val ? parseFloat(val.replace("px", "")) : 0;
}
function getNodeWidth(node) {
  const leftBorder = px(node, "border-left-width");
  const rightBorder = px(node, "border-right-width");
  return node.clientWidth + leftBorder + rightBorder;
}
function getNodeHeight(node) {
  const topBorder = px(node, "border-top-width");
  const bottomBorder = px(node, "border-bottom-width");
  return node.clientHeight + topBorder + bottomBorder;
}
function getImageSize(targetNode, options = {}) {
  const width = options.width || getNodeWidth(targetNode);
  const height = options.height || getNodeHeight(targetNode);
  return { width, height };
}
function getPixelRatio() {
  let ratio;
  let FINAL_PROCESS;
  try {
    FINAL_PROCESS = process;
  } catch (e) {
  }
  const val = FINAL_PROCESS && FINAL_PROCESS.env ? FINAL_PROCESS.env.devicePixelRatio : null;
  if (val) {
    ratio = parseInt(val, 10);
    if (Number.isNaN(ratio)) {
      ratio = 1;
    }
  }
  return ratio || window.devicePixelRatio || 1;
}
var canvasDimensionLimit = 16384;
function checkCanvasDimensions(canvas) {
  if (canvas.width > canvasDimensionLimit || canvas.height > canvasDimensionLimit) {
    if (canvas.width > canvasDimensionLimit && canvas.height > canvasDimensionLimit) {
      if (canvas.width > canvas.height) {
        canvas.height *= canvasDimensionLimit / canvas.width;
        canvas.width = canvasDimensionLimit;
      } else {
        canvas.width *= canvasDimensionLimit / canvas.height;
        canvas.height = canvasDimensionLimit;
      }
    } else if (canvas.width > canvasDimensionLimit) {
      canvas.height *= canvasDimensionLimit / canvas.width;
      canvas.width = canvasDimensionLimit;
    } else {
      canvas.width *= canvasDimensionLimit / canvas.height;
      canvas.height = canvasDimensionLimit;
    }
  }
}
function canvasToBlob(canvas, options = {}) {
  if (canvas.toBlob) {
    return new Promise((resolve) => {
      canvas.toBlob(resolve, options.type ? options.type : "image/png", options.quality ? options.quality : 1);
    });
  }
  return new Promise((resolve) => {
    const binaryString = window.atob(canvas.toDataURL(options.type ? options.type : void 0, options.quality ? options.quality : void 0).split(",")[1]);
    const len = binaryString.length;
    const binaryArray = new Uint8Array(len);
    for (let i = 0; i < len; i += 1) {
      binaryArray[i] = binaryString.charCodeAt(i);
    }
    resolve(new Blob([binaryArray], {
      type: options.type ? options.type : "image/png"
    }));
  });
}
function createImage(url) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => {
      img.decode().then(() => {
        requestAnimationFrame(() => resolve(img));
      });
    };
    img.onerror = reject;
    img.crossOrigin = "anonymous";
    img.decoding = "async";
    img.src = url;
  });
}
function svgToDataURL(svg) {
  return __async(this, null, function* () {
    return Promise.resolve().then(() => new XMLSerializer().serializeToString(svg)).then(encodeURIComponent).then((html) => `data:image/svg+xml;charset=utf-8,${html}`);
  });
}
function nodeToDataURL(node, width, height) {
  return __async(this, null, function* () {
    const xmlns = "http://www.w3.org/2000/svg";
    const svg = document.createElementNS(xmlns, "svg");
    const foreignObject = document.createElementNS(xmlns, "foreignObject");
    svg.setAttribute("width", `${width}`);
    svg.setAttribute("height", `${height}`);
    svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
    foreignObject.setAttribute("width", "100%");
    foreignObject.setAttribute("height", "100%");
    foreignObject.setAttribute("x", "0");
    foreignObject.setAttribute("y", "0");
    foreignObject.setAttribute("externalResourcesRequired", "true");
    svg.appendChild(foreignObject);
    foreignObject.appendChild(node);
    return svgToDataURL(svg);
  });
}
var isInstanceOfElement = (node, instance) => {
  if (node instanceof instance)
    return true;
  const nodePrototype = Object.getPrototypeOf(node);
  if (nodePrototype === null)
    return false;
  return nodePrototype.constructor.name === instance.name || isInstanceOfElement(nodePrototype, instance);
};

// node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/clone-pseudos.js
function formatCSSText(style) {
  const content = style.getPropertyValue("content");
  return `${style.cssText} content: '${content.replace(/'|"/g, "")}';`;
}
function formatCSSProperties(style, options) {
  return getStyleProperties(options).map((name) => {
    const value = style.getPropertyValue(name);
    const priority = style.getPropertyPriority(name);
    return `${name}: ${value}${priority ? " !important" : ""};`;
  }).join(" ");
}
function getPseudoElementStyle(className, pseudo, style, options) {
  const selector = `.${className}:${pseudo}`;
  const cssText = style.cssText ? formatCSSText(style) : formatCSSProperties(style, options);
  return document.createTextNode(`${selector}{${cssText}}`);
}
function clonePseudoElement(nativeNode, clonedNode, pseudo, options) {
  const style = window.getComputedStyle(nativeNode, pseudo);
  const content = style.getPropertyValue("content");
  if (content === "" || content === "none") {
    return;
  }
  const className = uuid();
  try {
    clonedNode.className = `${clonedNode.className} ${className}`;
  } catch (err) {
    return;
  }
  const styleElement = document.createElement("style");
  styleElement.appendChild(getPseudoElementStyle(className, pseudo, style, options));
  clonedNode.appendChild(styleElement);
}
function clonePseudoElements(nativeNode, clonedNode, options) {
  clonePseudoElement(nativeNode, clonedNode, ":before", options);
  clonePseudoElement(nativeNode, clonedNode, ":after", options);
}

// node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/mimes.js
var WOFF = "application/font-woff";
var JPEG = "image/jpeg";
var mimes = {
  woff: WOFF,
  woff2: WOFF,
  ttf: "application/font-truetype",
  eot: "application/vnd.ms-fontobject",
  png: "image/png",
  jpg: JPEG,
  jpeg: JPEG,
  gif: "image/gif",
  tiff: "image/tiff",
  svg: "image/svg+xml",
  webp: "image/webp"
};
function getExtension(url) {
  const match = /\.([^./]*?)$/g.exec(url);
  return match ? match[1] : "";
}
function getMimeType(url) {
  const extension = getExtension(url).toLowerCase();
  return mimes[extension] || "";
}

// node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/dataurl.js
function getContentFromDataUrl(dataURL) {
  return dataURL.split(/,/)[1];
}
function isDataUrl(url) {
  return url.search(/^(data:)/) !== -1;
}
function makeDataUrl(content, mimeType) {
  return `data:${mimeType};base64,${content}`;
}
function fetchAsDataURL(url, init, process2) {
  return __async(this, null, function* () {
    const res = yield fetch(url, init);
    if (res.status === 404) {
      throw new Error(`Resource "${res.url}" not found`);
    }
    const blob = yield res.blob();
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onerror = reject;
      reader.onloadend = () => {
        try {
          resolve(process2({ res, result: reader.result }));
        } catch (error) {
          reject(error);
        }
      };
      reader.readAsDataURL(blob);
    });
  });
}
var cache = {};
function getCacheKey(url, contentType, includeQueryParams) {
  let key = url.replace(/\?.*/, "");
  if (includeQueryParams) {
    key = url;
  }
  if (/ttf|otf|eot|woff2?/i.test(key)) {
    key = key.replace(/.*\//, "");
  }
  return contentType ? `[${contentType}]${key}` : key;
}
function resourceToDataURL(resourceUrl, contentType, options) {
  return __async(this, null, function* () {
    const cacheKey = getCacheKey(resourceUrl, contentType, options.includeQueryParams);
    if (cache[cacheKey] != null) {
      return cache[cacheKey];
    }
    if (options.cacheBust) {
      resourceUrl += (/\?/.test(resourceUrl) ? "&" : "?") + (/* @__PURE__ */ new Date()).getTime();
    }
    let dataURL;
    try {
      const content = yield fetchAsDataURL(resourceUrl, options.fetchRequestInit, ({ res, result }) => {
        if (!contentType) {
          contentType = res.headers.get("Content-Type") || "";
        }
        return getContentFromDataUrl(result);
      });
      dataURL = makeDataUrl(content, contentType);
    } catch (error) {
      dataURL = options.imagePlaceholder || "";
      let msg = `Failed to fetch resource: ${resourceUrl}`;
      if (error) {
        msg = typeof error === "string" ? error : error.message;
      }
      if (msg) {
        console.warn(msg);
      }
    }
    cache[cacheKey] = dataURL;
    return dataURL;
  });
}

// node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/clone-node.js
function cloneCanvasElement(canvas) {
  return __async(this, null, function* () {
    const dataURL = canvas.toDataURL();
    if (dataURL === "data:,") {
      return canvas.cloneNode(false);
    }
    return createImage(dataURL);
  });
}
function cloneVideoElement(video, options) {
  return __async(this, null, function* () {
    if (video.currentSrc) {
      const canvas = document.createElement("canvas");
      const ctx = canvas.getContext("2d");
      canvas.width = video.clientWidth;
      canvas.height = video.clientHeight;
      ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      const dataURL2 = canvas.toDataURL();
      return createImage(dataURL2);
    }
    const poster = video.poster;
    const contentType = getMimeType(poster);
    const dataURL = yield resourceToDataURL(poster, contentType, options);
    return createImage(dataURL);
  });
}
function cloneIFrameElement(iframe, options) {
  return __async(this, null, function* () {
    var _a;
    try {
      if ((_a = iframe === null || iframe === void 0 ? void 0 : iframe.contentDocument) === null || _a === void 0 ? void 0 : _a.body) {
        return yield cloneNode(iframe.contentDocument.body, options, true);
      }
    } catch (_b) {
    }
    return iframe.cloneNode(false);
  });
}
function cloneSingleNode(node, options) {
  return __async(this, null, function* () {
    if (isInstanceOfElement(node, HTMLCanvasElement)) {
      return cloneCanvasElement(node);
    }
    if (isInstanceOfElement(node, HTMLVideoElement)) {
      return cloneVideoElement(node, options);
    }
    if (isInstanceOfElement(node, HTMLIFrameElement)) {
      return cloneIFrameElement(node, options);
    }
    return node.cloneNode(isSVGElement(node));
  });
}
var isSlotElement = (node) => node.tagName != null && node.tagName.toUpperCase() === "SLOT";
var isSVGElement = (node) => node.tagName != null && node.tagName.toUpperCase() === "SVG";
function cloneChildren(nativeNode, clonedNode, options) {
  return __async(this, null, function* () {
    var _a, _b;
    if (isSVGElement(clonedNode)) {
      return clonedNode;
    }
    let children = [];
    if (isSlotElement(nativeNode) && nativeNode.assignedNodes) {
      children = toArray(nativeNode.assignedNodes());
    } else if (isInstanceOfElement(nativeNode, HTMLIFrameElement) && ((_a = nativeNode.contentDocument) === null || _a === void 0 ? void 0 : _a.body)) {
      children = toArray(nativeNode.contentDocument.body.childNodes);
    } else {
      children = toArray(((_b = nativeNode.shadowRoot) !== null && _b !== void 0 ? _b : nativeNode).childNodes);
    }
    if (children.length === 0 || isInstanceOfElement(nativeNode, HTMLVideoElement)) {
      return clonedNode;
    }
    yield children.reduce((deferred, child) => deferred.then(() => cloneNode(child, options)).then((clonedChild) => {
      if (clonedChild) {
        clonedNode.appendChild(clonedChild);
      }
    }), Promise.resolve());
    return clonedNode;
  });
}
function cloneCSSStyle(nativeNode, clonedNode, options) {
  const targetStyle = clonedNode.style;
  if (!targetStyle) {
    return;
  }
  const sourceStyle = window.getComputedStyle(nativeNode);
  if (sourceStyle.cssText) {
    targetStyle.cssText = sourceStyle.cssText;
    targetStyle.transformOrigin = sourceStyle.transformOrigin;
  } else {
    getStyleProperties(options).forEach((name) => {
      let value = sourceStyle.getPropertyValue(name);
      if (name === "font-size" && value.endsWith("px")) {
        const reducedFont = Math.floor(parseFloat(value.substring(0, value.length - 2))) - 0.1;
        value = `${reducedFont}px`;
      }
      if (isInstanceOfElement(nativeNode, HTMLIFrameElement) && name === "display" && value === "inline") {
        value = "block";
      }
      if (name === "d" && clonedNode.getAttribute("d")) {
        value = `path(${clonedNode.getAttribute("d")})`;
      }
      targetStyle.setProperty(name, value, sourceStyle.getPropertyPriority(name));
    });
  }
}
function cloneInputValue(nativeNode, clonedNode) {
  if (isInstanceOfElement(nativeNode, HTMLTextAreaElement)) {
    clonedNode.innerHTML = nativeNode.value;
  }
  if (isInstanceOfElement(nativeNode, HTMLInputElement)) {
    clonedNode.setAttribute("value", nativeNode.value);
  }
}
function cloneSelectValue(nativeNode, clonedNode) {
  if (isInstanceOfElement(nativeNode, HTMLSelectElement)) {
    const clonedSelect = clonedNode;
    const selectedOption = Array.from(clonedSelect.children).find((child) => nativeNode.value === child.getAttribute("value"));
    if (selectedOption) {
      selectedOption.setAttribute("selected", "");
    }
  }
}
function decorate(nativeNode, clonedNode, options) {
  if (isInstanceOfElement(clonedNode, Element)) {
    cloneCSSStyle(nativeNode, clonedNode, options);
    clonePseudoElements(nativeNode, clonedNode, options);
    cloneInputValue(nativeNode, clonedNode);
    cloneSelectValue(nativeNode, clonedNode);
  }
  return clonedNode;
}
function ensureSVGSymbols(clone, options) {
  return __async(this, null, function* () {
    const uses = clone.querySelectorAll ? clone.querySelectorAll("use") : [];
    if (uses.length === 0) {
      return clone;
    }
    const processedDefs = {};
    for (let i = 0; i < uses.length; i++) {
      const use = uses[i];
      const id = use.getAttribute("xlink:href");
      if (id) {
        const exist = clone.querySelector(id);
        const definition = document.querySelector(id);
        if (!exist && definition && !processedDefs[id]) {
          processedDefs[id] = yield cloneNode(definition, options, true);
        }
      }
    }
    const nodes = Object.values(processedDefs);
    if (nodes.length) {
      const ns = "http://www.w3.org/1999/xhtml";
      const svg = document.createElementNS(ns, "svg");
      svg.setAttribute("xmlns", ns);
      svg.style.position = "absolute";
      svg.style.width = "0";
      svg.style.height = "0";
      svg.style.overflow = "hidden";
      svg.style.display = "none";
      const defs = document.createElementNS(ns, "defs");
      svg.appendChild(defs);
      for (let i = 0; i < nodes.length; i++) {
        defs.appendChild(nodes[i]);
      }
      clone.appendChild(svg);
    }
    return clone;
  });
}
function cloneNode(node, options, isRoot) {
  return __async(this, null, function* () {
    if (!isRoot && options.filter && !options.filter(node)) {
      return null;
    }
    return Promise.resolve(node).then((clonedNode) => cloneSingleNode(clonedNode, options)).then((clonedNode) => cloneChildren(node, clonedNode, options)).then((clonedNode) => decorate(node, clonedNode, options)).then((clonedNode) => ensureSVGSymbols(clonedNode, options));
  });
}

// node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/embed-resources.js
var URL_REGEX = /url\((['"]?)([^'"]+?)\1\)/g;
var URL_WITH_FORMAT_REGEX = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g;
var FONT_SRC_REGEX = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;
function toRegex(url) {
  const escaped = url.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1");
  return new RegExp(`(url\\(['"]?)(${escaped})(['"]?\\))`, "g");
}
function parseURLs(cssText) {
  const urls = [];
  cssText.replace(URL_REGEX, (raw, quotation, url) => {
    urls.push(url);
    return raw;
  });
  return urls.filter((url) => !isDataUrl(url));
}
function embed(cssText, resourceURL, baseURL, options, getContentFromUrl) {
  return __async(this, null, function* () {
    try {
      const resolvedURL = baseURL ? resolveUrl(resourceURL, baseURL) : resourceURL;
      const contentType = getMimeType(resourceURL);
      let dataURL;
      if (getContentFromUrl) {
        const content = yield getContentFromUrl(resolvedURL);
        dataURL = makeDataUrl(content, contentType);
      } else {
        dataURL = yield resourceToDataURL(resolvedURL, contentType, options);
      }
      return cssText.replace(toRegex(resourceURL), `$1${dataURL}$3`);
    } catch (error) {
    }
    return cssText;
  });
}
function filterPreferredFontFormat(str, { preferredFontFormat }) {
  return !preferredFontFormat ? str : str.replace(FONT_SRC_REGEX, (match) => {
    while (true) {
      const [src, , format] = URL_WITH_FORMAT_REGEX.exec(match) || [];
      if (!format) {
        return "";
      }
      if (format === preferredFontFormat) {
        return `src: ${src};`;
      }
    }
  });
}
function shouldEmbed(url) {
  return url.search(URL_REGEX) !== -1;
}
function embedResources(cssText, baseUrl, options) {
  return __async(this, null, function* () {
    if (!shouldEmbed(cssText)) {
      return cssText;
    }
    const filteredCSSText = filterPreferredFontFormat(cssText, options);
    const urls = parseURLs(filteredCSSText);
    return urls.reduce((deferred, url) => deferred.then((css) => embed(css, url, baseUrl, options)), Promise.resolve(filteredCSSText));
  });
}

// node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/embed-images.js
function embedProp(propName, node, options) {
  return __async(this, null, function* () {
    var _a;
    const propValue = (_a = node.style) === null || _a === void 0 ? void 0 : _a.getPropertyValue(propName);
    if (propValue) {
      const cssString = yield embedResources(propValue, null, options);
      node.style.setProperty(propName, cssString, node.style.getPropertyPriority(propName));
      return true;
    }
    return false;
  });
}
function embedBackground(clonedNode, options) {
  return __async(this, null, function* () {
    ;
    (yield embedProp("background", clonedNode, options)) || (yield embedProp("background-image", clonedNode, options));
    (yield embedProp("mask", clonedNode, options)) || (yield embedProp("-webkit-mask", clonedNode, options)) || (yield embedProp("mask-image", clonedNode, options)) || (yield embedProp("-webkit-mask-image", clonedNode, options));
  });
}
function embedImageNode(clonedNode, options) {
  return __async(this, null, function* () {
    const isImageElement = isInstanceOfElement(clonedNode, HTMLImageElement);
    if (!(isImageElement && !isDataUrl(clonedNode.src)) && !(isInstanceOfElement(clonedNode, SVGImageElement) && !isDataUrl(clonedNode.href.baseVal))) {
      return;
    }
    const url = isImageElement ? clonedNode.src : clonedNode.href.baseVal;
    const dataURL = yield resourceToDataURL(url, getMimeType(url), options);
    yield new Promise((resolve, reject) => {
      clonedNode.onload = resolve;
      clonedNode.onerror = options.onImageErrorHandler ? (...attributes) => {
        try {
          resolve(options.onImageErrorHandler(...attributes));
        } catch (error) {
          reject(error);
        }
      } : reject;
      const image = clonedNode;
      if (image.decode) {
        image.decode = resolve;
      }
      if (image.loading === "lazy") {
        image.loading = "eager";
      }
      if (isImageElement) {
        clonedNode.srcset = "";
        clonedNode.src = dataURL;
      } else {
        clonedNode.href.baseVal = dataURL;
      }
    });
  });
}
function embedChildren(clonedNode, options) {
  return __async(this, null, function* () {
    const children = toArray(clonedNode.childNodes);
    const deferreds = children.map((child) => embedImages(child, options));
    yield Promise.all(deferreds).then(() => clonedNode);
  });
}
function embedImages(clonedNode, options) {
  return __async(this, null, function* () {
    if (isInstanceOfElement(clonedNode, Element)) {
      yield embedBackground(clonedNode, options);
      yield embedImageNode(clonedNode, options);
      yield embedChildren(clonedNode, options);
    }
  });
}

// node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/apply-style.js
function applyStyle(node, options) {
  const { style } = node;
  if (options.backgroundColor) {
    style.backgroundColor = options.backgroundColor;
  }
  if (options.width) {
    style.width = `${options.width}px`;
  }
  if (options.height) {
    style.height = `${options.height}px`;
  }
  const manual = options.style;
  if (manual != null) {
    Object.keys(manual).forEach((key) => {
      style[key] = manual[key];
    });
  }
  return node;
}

// node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/embed-webfonts.js
var cssFetchCache = {};
function fetchCSS(url) {
  return __async(this, null, function* () {
    let cache2 = cssFetchCache[url];
    if (cache2 != null) {
      return cache2;
    }
    const res = yield fetch(url);
    const cssText = yield res.text();
    cache2 = { url, cssText };
    cssFetchCache[url] = cache2;
    return cache2;
  });
}
function embedFonts(data, options) {
  return __async(this, null, function* () {
    let cssText = data.cssText;
    const regexUrl = /url\(["']?([^"')]+)["']?\)/g;
    const fontLocs = cssText.match(/url\([^)]+\)/g) || [];
    const loadFonts = fontLocs.map((loc) => __async(null, null, function* () {
      let url = loc.replace(regexUrl, "$1");
      if (!url.startsWith("https://")) {
        url = new URL(url, data.url).href;
      }
      return fetchAsDataURL(url, options.fetchRequestInit, ({ result }) => {
        cssText = cssText.replace(loc, `url(${result})`);
        return [loc, result];
      });
    }));
    return Promise.all(loadFonts).then(() => cssText);
  });
}
function parseCSS(source) {
  if (source == null) {
    return [];
  }
  const result = [];
  const commentsRegex = /(\/\*[\s\S]*?\*\/)/gi;
  let cssText = source.replace(commentsRegex, "");
  const keyframesRegex = new RegExp("((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})", "gi");
  while (true) {
    const matches = keyframesRegex.exec(cssText);
    if (matches === null) {
      break;
    }
    result.push(matches[0]);
  }
  cssText = cssText.replace(keyframesRegex, "");
  const importRegex = /@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi;
  const combinedCSSRegex = "((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})";
  const unifiedRegex = new RegExp(combinedCSSRegex, "gi");
  while (true) {
    let matches = importRegex.exec(cssText);
    if (matches === null) {
      matches = unifiedRegex.exec(cssText);
      if (matches === null) {
        break;
      } else {
        importRegex.lastIndex = unifiedRegex.lastIndex;
      }
    } else {
      unifiedRegex.lastIndex = importRegex.lastIndex;
    }
    result.push(matches[0]);
  }
  return result;
}
function getCSSRules(styleSheets, options) {
  return __async(this, null, function* () {
    const ret = [];
    const deferreds = [];
    styleSheets.forEach((sheet) => {
      if ("cssRules" in sheet) {
        try {
          toArray(sheet.cssRules || []).forEach((item, index) => {
            if (item.type === CSSRule.IMPORT_RULE) {
              let importIndex = index + 1;
              const url = item.href;
              const deferred = fetchCSS(url).then((metadata) => embedFonts(metadata, options)).then((cssText) => parseCSS(cssText).forEach((rule) => {
                try {
                  sheet.insertRule(rule, rule.startsWith("@import") ? importIndex += 1 : sheet.cssRules.length);
                } catch (error) {
                  console.error("Error inserting rule from remote css", {
                    rule,
                    error
                  });
                }
              })).catch((e) => {
                console.error("Error loading remote css", e.toString());
              });
              deferreds.push(deferred);
            }
          });
        } catch (e) {
          const inline = styleSheets.find((a) => a.href == null) || document.styleSheets[0];
          if (sheet.href != null) {
            deferreds.push(fetchCSS(sheet.href).then((metadata) => embedFonts(metadata, options)).then((cssText) => parseCSS(cssText).forEach((rule) => {
              inline.insertRule(rule, inline.cssRules.length);
            })).catch((err) => {
              console.error("Error loading remote stylesheet", err);
            }));
          }
          console.error("Error inlining remote css file", e);
        }
      }
    });
    return Promise.all(deferreds).then(() => {
      styleSheets.forEach((sheet) => {
        if ("cssRules" in sheet) {
          try {
            toArray(sheet.cssRules || []).forEach((item) => {
              ret.push(item);
            });
          } catch (e) {
            console.error(`Error while reading CSS rules from ${sheet.href}`, e);
          }
        }
      });
      return ret;
    });
  });
}
function getWebFontRules(cssRules) {
  return cssRules.filter((rule) => rule.type === CSSRule.FONT_FACE_RULE).filter((rule) => shouldEmbed(rule.style.getPropertyValue("src")));
}
function parseWebFontRules(node, options) {
  return __async(this, null, function* () {
    if (node.ownerDocument == null) {
      throw new Error("Provided element is not within a Document");
    }
    const styleSheets = toArray(node.ownerDocument.styleSheets);
    const cssRules = yield getCSSRules(styleSheets, options);
    return getWebFontRules(cssRules);
  });
}
function normalizeFontFamily(font) {
  return font.trim().replace(/["']/g, "");
}
function getUsedFonts(node) {
  const fonts = /* @__PURE__ */ new Set();
  function traverse(node2) {
    const fontFamily = node2.style.fontFamily || getComputedStyle(node2).fontFamily;
    fontFamily.split(",").forEach((font) => {
      fonts.add(normalizeFontFamily(font));
    });
    Array.from(node2.children).forEach((child) => {
      if (child instanceof HTMLElement) {
        traverse(child);
      }
    });
  }
  traverse(node);
  return fonts;
}
function getWebFontCSS(node, options) {
  return __async(this, null, function* () {
    const rules = yield parseWebFontRules(node, options);
    const usedFonts = getUsedFonts(node);
    const cssTexts = yield Promise.all(rules.filter((rule) => usedFonts.has(normalizeFontFamily(rule.style.fontFamily))).map((rule) => {
      const baseUrl = rule.parentStyleSheet ? rule.parentStyleSheet.href : null;
      return embedResources(rule.cssText, baseUrl, options);
    }));
    return cssTexts.join("\n");
  });
}
function embedWebFonts(clonedNode, options) {
  return __async(this, null, function* () {
    const cssText = options.fontEmbedCSS != null ? options.fontEmbedCSS : options.skipFonts ? null : yield getWebFontCSS(clonedNode, options);
    if (cssText) {
      const styleNode = document.createElement("style");
      const sytleContent = document.createTextNode(cssText);
      styleNode.appendChild(sytleContent);
      if (clonedNode.firstChild) {
        clonedNode.insertBefore(styleNode, clonedNode.firstChild);
      } else {
        clonedNode.appendChild(styleNode);
      }
    }
  });
}

// node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/index.js
function toSvg(_0) {
  return __async(this, arguments, function* (node, options = {}) {
    const { width, height } = getImageSize(node, options);
    const clonedNode = yield cloneNode(node, options, true);
    yield embedWebFonts(clonedNode, options);
    yield embedImages(clonedNode, options);
    applyStyle(clonedNode, options);
    const datauri = yield nodeToDataURL(clonedNode, width, height);
    return datauri;
  });
}
function toCanvas(_0) {
  return __async(this, arguments, function* (node, options = {}) {
    const { width, height } = getImageSize(node, options);
    const svg = yield toSvg(node, options);
    const img = yield createImage(svg);
    const canvas = document.createElement("canvas");
    const context = canvas.getContext("2d");
    const ratio = options.pixelRatio || getPixelRatio();
    const canvasWidth = options.canvasWidth || width;
    const canvasHeight = options.canvasHeight || height;
    canvas.width = canvasWidth * ratio;
    canvas.height = canvasHeight * ratio;
    if (!options.skipAutoScale) {
      checkCanvasDimensions(canvas);
    }
    canvas.style.width = `${canvasWidth}`;
    canvas.style.height = `${canvasHeight}`;
    if (options.backgroundColor) {
      context.fillStyle = options.backgroundColor;
      context.fillRect(0, 0, canvas.width, canvas.height);
    }
    context.drawImage(img, 0, 0, canvas.width, canvas.height);
    return canvas;
  });
}
function toPng(_0) {
  return __async(this, arguments, function* (node, options = {}) {
    const canvas = yield toCanvas(node, options);
    return canvas.toDataURL();
  });
}
function toBlob(_0) {
  return __async(this, arguments, function* (node, options = {}) {
    const canvas = yield toCanvas(node, options);
    const blob = yield canvasToBlob(canvas);
    return blob;
  });
}

// src/app/shared/fixtures/models/fixture.ts
var Fixture = class {
  constructor(id, entityId, name, imageSrc_Base64, attributes = []) {
    this.id = "";
    this.entityId = "";
    this.name = "";
    this.imageSrc_Base64 = "";
    this.attributes = [];
    this.rules = [];
    this.active = false;
    this.shouldRender = true;
    this.storing = false;
    this.id = id;
    this.entityId = entityId;
    this.name = name;
    this.imageSrc_Base64 = imageSrc_Base64;
    this.attributes = attributes;
  }
};

// src/app/shared/appointments/models/pricing.ts
var AppointmentPrice = class {
  calcTotalDiscount() {
    let totalDiscount = 0;
    this.appliedPromotions.forEach((promotion) => {
      if (promotion.appliedDiscount != null) {
        totalDiscount = totalDiscount + promotion.appliedDiscount;
      }
    });
    this.totalDiscount = totalDiscount;
  }
  constructor(price, details = [], customDetails = void 0, appliedPromotions = [], finalPrice = 0, targetPrice = 0, ablPrice = 0, parPrice = 0, targetPromoPrice = 0) {
    this.iso4217 = "USD";
    this.parPrice = 0;
    this.targetPrice = 0;
    this.targetPromoPrice = 0;
    this.ablPrice = 0;
    this.finalPrice = 0;
    this.appliedPromotions = [];
    this.totalDiscount = 0;
    if (price != null) {
      this.details = price.details;
      this.appliedPromotions = price.appliedPromotions;
      this.customItems = price.customItems ?? [];
      this.finalPrice = price.finalPrice;
      this.targetPrice = price.targetPrice;
      this.ablPrice = price.ablPrice;
      this.parPrice = price.parPrice;
      this.targetPromoPrice = price.targetPromoPrice;
    } else {
      this.details = details;
      this.appliedPromotions = appliedPromotions;
      this.customItems = customDetails ?? [];
      this.finalPrice = finalPrice;
      this.targetPrice = targetPrice;
      this.ablPrice = ablPrice;
      this.parPrice = parPrice;
      this.targetPromoPrice = targetPromoPrice;
    }
    this.calcTotalDiscount();
  }
};

// src/app/shared/entities/models/rules.ts
var EntityRuleResultType;
(function(EntityRuleResultType2) {
  EntityRuleResultType2["Quantity"] = "Quantity";
  EntityRuleResultType2["ReferenceQuantity"] = "ReferenceQuantity";
})(EntityRuleResultType || (EntityRuleResultType = {}));
var EntityCriteriaTriggerType;
(function(EntityCriteriaTriggerType2) {
  EntityCriteriaTriggerType2["Attribute"] = "Attribute";
  EntityCriteriaTriggerType2["ParentRestriction"] = "ParentRestriction";
})(EntityCriteriaTriggerType || (EntityCriteriaTriggerType = {}));
var EntityRuleCriteriaType;
(function(EntityRuleCriteriaType2) {
  EntityRuleCriteriaType2["Exact"] = "Exact";
  EntityRuleCriteriaType2["GreaterThan"] = "GreaterThan";
  EntityRuleCriteriaType2["GreaterThanOrEqual"] = "GreaterThanOrEqual";
  EntityRuleCriteriaType2["LessThan"] = "LessThan";
  EntityRuleCriteriaType2["LessThanOrEqual"] = "LessThanOrEqual";
})(EntityRuleCriteriaType || (EntityRuleCriteriaType = {}));

// src/app/shared/documents/models/document.ts
var Document = class {
  checkSigningValidity() {
    this.checkConsultantValidity();
    this.checkCustomerValidity();
  }
  checkConsultantValidity() {
    let totalSignatures = 0;
    let totalInitials = 0;
    if (this.content != null) {
      totalSignatures = (this.content.match(/{{signature\.consultant\.mandatory}}/g) ?? []).length;
      totalInitials = (this.content.match(/{{initial\.consultant\.mandatory}}/g) ?? []).length;
    } else if (this.mapping?.pages != null) {
      this.mapping.pages.forEach((page) => {
        const pageSignatures = page.fields.filter((x) => x.id == "{{signature.consultant.mandatory}}");
        const pageInitials = page.fields.filter((x) => x.id == "{{initial.consultant.mandatory}}");
        totalSignatures = totalSignatures + pageSignatures.length;
        totalInitials = totalInitials + pageInitials.length;
      });
    } else {
      this.consultantValid = false;
    }
    const consultant = this.signers.find((x) => x.type == DocumentSignerType.Consultant);
    if (consultant != null) {
      if (totalInitials > 0 || totalSignatures > 0) {
        const consultantSignatures = this.signatures.filter((x) => x.signerName == consultant.fullName);
        this.consultantValid = consultantSignatures.length >= totalSignatures + totalInitials;
      } else {
        this.consultantValid = true;
      }
    } else {
      if (totalInitials > 0 || totalSignatures > 0) {
        this.consultantValid = this.signatures.length >= totalSignatures + totalInitials;
      } else {
        this.consultantValid = true;
      }
    }
  }
  checkCustomerValidity() {
    let totalSignatures = 0;
    let totalInitials = 0;
    if (this.content != null) {
      totalSignatures = (this.content.match(/{{signature\.customer\.mandatory}}/g) ?? []).length;
      totalInitials = (this.content.match(/{{initial\.customer\.mandatory}}/g) ?? []).length;
    } else if (this.mapping?.pages != null) {
      this.mapping.pages.forEach((page) => {
        const pageSignatures = page.fields.filter((x) => x.id == "{{signature.customer.mandatory}}");
        const pageInitials = page.fields.filter((x) => x.id == "{{initial.customer.mandatory}}");
        totalSignatures = totalSignatures + pageSignatures.length;
        totalInitials = totalInitials + pageInitials.length;
      });
    } else {
      this.customerValid = false;
    }
    const customer = this.signers.find((x) => x.type == DocumentSignerType.Customer);
    if (customer != null) {
      if (totalInitials > 0 || totalSignatures > 0) {
        const signatures = this.signatures.filter((x) => x.signerName == customer.fullName);
        this.customerValid = signatures.length >= totalSignatures + totalInitials;
      } else {
        this.customerValid = true;
      }
    } else {
      if (totalInitials > 0 || totalSignatures > 0) {
        this.customerValid = this.signatures.length >= totalSignatures + totalInitials;
      } else {
        this.customerValid = true;
      }
    }
  }
  renderBlob(viewerElm, quality = 1, pixelRatio = 1, bgColor = "#ffffff", saveExecuted = false) {
    return new Promise((res, rej) => __async(this, null, function* () {
      toBlob(viewerElm, {
        quality,
        pixelRatio,
        backgroundColor: bgColor
      }).then((blob) => {
        if (blob != null) {
          if (saveExecuted) {
            this.executed_Png = blob;
          }
          res(blob);
        } else {
          rej();
        }
      }).catch((e) => {
        console.warn(`DOCUMENT RENDER: Failed to render document. Message ${JSON.stringify(e)}`);
        rej(e);
      });
    }));
  }
  renderCanvas(viewerElm, quality = 1, pixelRatio = 1, bgColor = "#ffffff", saveExecuted = false) {
    return new Promise((res, rej) => __async(this, null, function* () {
      toCanvas(viewerElm, {
        quality,
        pixelRatio,
        backgroundColor: bgColor,
        skipFonts: true
      }).then((canvasElm) => {
        if (saveExecuted) {
          canvasElm.toBlob((blob) => {
            if (blob != null) {
              this.executed_Png = blob;
            }
            res(canvasElm);
          });
        } else {
          res(canvasElm);
        }
      }).catch((e) => {
        console.warn(`DOCUMENT RENDER: Failed to render document. Message ${JSON.stringify(e)}`);
        rej(e);
      });
    }));
  }
  constructor(id, name, customerFacing, shopFacing, standalone, dynamic, alwaysShow, displayInSigning = true, mapping, displayOrder = 0, content = void 0, executed = false, signers = [], rules = [], documents = [], signatures = [], userContent = [], lastUpdated_Utc = void 0, created_Utc = void 0) {
    this.id = "";
    this.name = "";
    this.customerFacing = false;
    this.shopFacing = false;
    this.standalone = false;
    this.alwaysShow = true;
    this.dynamic = false;
    this.displayInSigning = true;
    this.displayOrder = 0;
    this.rules = [];
    this.executed = false;
    this.signers = [];
    this.signatures = [];
    this.userContent = [];
    this.customerValid = false;
    this.consultantValid = false;
    this.active = false;
    this.documents = [];
    this.id = id;
    this.name = name;
    this.customerFacing = customerFacing;
    this.shopFacing = shopFacing;
    this.standalone = standalone;
    this.dynamic = dynamic;
    this.alwaysShow = alwaysShow;
    this.displayInSigning = displayInSigning;
    this.mapping = mapping;
    this.displayOrder = displayOrder;
    this.content = content;
    this.documents = documents;
    this.signers = signers;
    this.signatures = signatures;
    this.userContent = userContent;
    this.rules = rules;
    this.executed = executed;
    this.lastUpdated_Utc = lastUpdated_Utc, this.created_Utc = created_Utc;
  }
};
var DocumentRuleCriteriaType;
(function(DocumentRuleCriteriaType2) {
  DocumentRuleCriteriaType2["Exact"] = "Exact";
  DocumentRuleCriteriaType2["GreaterThan"] = "GreaterThan";
  DocumentRuleCriteriaType2["GreaterThanOrEqual"] = "GreaterThanOrEqual";
  DocumentRuleCriteriaType2["LessThan"] = "LessThan";
  DocumentRuleCriteriaType2["LessThanOrEqual"] = "LessThanOrEqual";
})(DocumentRuleCriteriaType || (DocumentRuleCriteriaType = {}));
var DocumentRuleCriteriaTriggerType;
(function(DocumentRuleCriteriaTriggerType2) {
  DocumentRuleCriteriaTriggerType2["Attribute"] = "Attribute";
})(DocumentRuleCriteriaTriggerType || (DocumentRuleCriteriaTriggerType = {}));
var DocumentUserContent = class {
  constructor(id, hashedId, fieldId, documentId, signerName, device, ip, latlng, appVersion, timeStamp_Utc) {
    this.id = "";
    this.id = id;
    this.hashedId = hashedId;
    this.fieldId = fieldId;
    this.documentId = documentId;
    this.signerName = signerName;
    this.device = device;
    this.ip = ip;
    this.latlng = latlng;
    this.appVersion = appVersion;
    this.timeStamp_Utc = timeStamp_Utc;
  }
};
var DocumentSignature = class {
  constructor(id, hashedId, fieldId, documentId, signerName, device, ip, latlng, appVersion, timeStamp_Utc) {
    this.id = "";
    this.id = id;
    this.hashedId = hashedId;
    this.fieldId = fieldId;
    this.documentId = documentId;
    this.signerName = signerName;
    this.device = device;
    this.ip = ip;
    this.latlng = latlng;
    this.appVersion = appVersion;
    this.timeStamp_Utc = timeStamp_Utc;
  }
};
var DocumentSigningConsent = class {
  constructor(id, hashedId, device, ip, fullName, latlng, appVersion, timeStamp_Utc) {
    this.id = "";
    this.id = id;
    this.hashedId = hashedId;
    this.fullName = fullName;
    this.device = device;
    this.ip = ip;
    this.latlng = latlng;
    this.appVersion = appVersion;
    this.timeStamp_Utc = timeStamp_Utc;
  }
};
var DocumentFieldMapping = class {
  get displayX() {
    return `${this.x * this.ratio}px`;
  }
  get displayY() {
    return `${this.y * this.ratio}px`;
  }
  get displayWidth() {
    return `${this.width * this.ratio}px`;
  }
  get displayHeight() {
    return `${this.height * this.ratio}px`;
  }
  constructor(field, ratio = 1) {
    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
    this.pageNumber = 1;
    this.ratio = 1;
    this.id = field.id;
    this.fieldId = field.fieldId;
    this.content = field.content ?? field.id ?? "";
    this.pageNumber = field.pageNumber;
    this.x = field.x;
    this.y = field.y;
    this.width = field.width;
    this.height = field.height;
    this.ratio = ratio;
  }
};
var DocumentSigner = class {
  constructor(referenceId, fullName, consented, phoneNumber, emailAddress, type) {
    this.consented = false;
    this.referenceId = referenceId;
    this.fullName = fullName;
    this.phoneNumber = phoneNumber;
    this.emailAddress = emailAddress;
    this.type = type;
    this.consented = consented;
  }
};
var DocumentSignerType;
(function(DocumentSignerType2) {
  DocumentSignerType2["Customer"] = "Customer";
  DocumentSignerType2["Consultant"] = "Consultant";
})(DocumentSignerType || (DocumentSignerType = {}));

// src/app/shared/appointments/models/needs.ts
var CustomerNeedQuestion = class {
  constructor(question, possibleAnswers) {
    this.possibleAnswers = [];
    this.answers = [];
    this.storing = false;
    this.question = question;
    this.possibleAnswers = possibleAnswers;
  }
};
var CustomerNeedPossibleAnswer = class {
  constructor(title, answer) {
    this.title = title;
    this.answer = answer;
  }
};

// src/app/shared/appointments/models/appointment.ts
var Appointment = class {
  constructor() {
    this.id = "";
    this.accepted = false;
    this.opportunityTypes = [];
    this.opportunityPlumbingIssues = [];
    this.isEmergency = false;
    this.status = AppointmentStatus.Open;
    this.customerNeeds = {};
    this.payments = [];
    this.lenders = [];
    this.availablePromotions = [];
    this.availableFixtures = [];
    this.availableEntities = [];
    this.availableSkus = [];
    this.availablePaymentSettings = [];
    this.availableDocuments = [];
    this.availableDispositionStatuses = [];
    this.availablePresentationContent = [];
    this.availableShops = [];
    this.documents = [];
    this.documentSigningKeys = [];
    this.created_Utc = /* @__PURE__ */ new Date();
    this.lastUpdated_Utc = /* @__PURE__ */ new Date();
    this.storing = false;
    this.syncing = false;
    this.reverting = false;
    this.accepting = false;
    this.changed$ = new Subject();
    this.priceChanged$ = new Subject();
    this.customPriceChanged$ = new Subject();
    this.available = true;
    this.submittingEstimate = false;
    this.retrieving = false;
    this.checkInCompleted = false;
    this.summaryCompleted = false;
    this.needsCompleted = false;
    this.negotiationCompleted = false;
    this.pricingCompleted = false;
    this.completed = false;
    this.inspectionCompleted = false;
    this.presentationCompleted = false;
    this.jobSummaryCompleted = false;
    this.documentsCompleted = false;
    this.questions = [
      new CustomerNeedQuestion("How did you hear about Repipe Specialists?", [
        new CustomerNeedPossibleAnswer("Radio", "radio"),
        new CustomerNeedPossibleAnswer("TV", "tv"),
        new CustomerNeedPossibleAnswer("Internet", "internet"),
        new CustomerNeedPossibleAnswer("Direct Mail", "directmail"),
        new CustomerNeedPossibleAnswer("Referral Shop", "referralshop"),
        new CustomerNeedPossibleAnswer("Facebook / Instagram", "social"),
        new CustomerNeedPossibleAnswer("Not Applicable", "na"),
        new CustomerNeedPossibleAnswer("Other", "other")
      ]),
      new CustomerNeedQuestion("What was the primary reason you called us out today?", [
        new CustomerNeedPossibleAnswer("Old Pipes", "oldpipes"),
        new CustomerNeedPossibleAnswer("Leaks", "leaks"),
        new CustomerNeedPossibleAnswer("Water shut off", "watershutoff"),
        new CustomerNeedPossibleAnswer("Low pressure", "lowpressure"),
        new CustomerNeedPossibleAnswer("Rusty Water", "rustywater"),
        new CustomerNeedPossibleAnswer("Insurance related", "insurance"),
        new CustomerNeedPossibleAnswer("Polybutylene pipes", "polybutylene"),
        new CustomerNeedPossibleAnswer("Not Applicable", "na"),
        new CustomerNeedPossibleAnswer("Other", "other")
      ]),
      new CustomerNeedQuestion("What other problems are you having with your current plumbing system?", [
        new CustomerNeedPossibleAnswer("Hot water takes a long time to come out", "hotwater"),
        new CustomerNeedPossibleAnswer("Old water heater", "oldwaterheater"),
        new CustomerNeedPossibleAnswer("Drains", "drains"),
        new CustomerNeedPossibleAnswer("Not Applicable", "na"),
        new CustomerNeedPossibleAnswer("Other", "other")
      ]),
      new CustomerNeedQuestion("How much do you know about the repipe process?", [
        new CustomerNeedPossibleAnswer("None", "none"),
        new CustomerNeedPossibleAnswer("It's been fully explained", "explained"),
        new CustomerNeedPossibleAnswer("Some knowledge", "some"),
        new CustomerNeedPossibleAnswer("Not Applicable", "na"),
        new CustomerNeedPossibleAnswer("Other", "other")
      ]),
      new CustomerNeedQuestion("What is important to you when hiring a company to repipe your home?", [
        new CustomerNeedPossibleAnswer("Good Reviews", "reviews"),
        new CustomerNeedPossibleAnswer("Good rating with the BBB", "bbb"),
        new CustomerNeedPossibleAnswer("Fair price point", "price"),
        new CustomerNeedPossibleAnswer("Backs their warranty", "warranty"),
        new CustomerNeedPossibleAnswer("Many years in business", "yearsinbusiness"),
        new CustomerNeedPossibleAnswer("An all-inclusive job start to finish -- including patching", "allinclusive"),
        new CustomerNeedPossibleAnswer("Not Applicable", "na"),
        new CustomerNeedPossibleAnswer("Other", "other")
      ]),
      new CustomerNeedQuestion("Have you had any plumbers out to talk about your repipe?", [
        new CustomerNeedPossibleAnswer("Yes", "yes"),
        new CustomerNeedPossibleAnswer("No", "no"),
        new CustomerNeedPossibleAnswer("You're the first one", "first"),
        new CustomerNeedPossibleAnswer("Have had a couple of bids", "couplebids"),
        new CustomerNeedPossibleAnswer("Not Applicable", "na"),
        new CustomerNeedPossibleAnswer("Other", "other")
      ])
    ];
    this.documentsValidForEstimate = false;
    this.paymentsValidForEstimate = false;
  }
  get hasPlumbingIssues() {
    return this.opportunityPlumbingIssues.length > 0;
  }
  checkSummaryProgression() {
    this.summaryCompleted = true;
  }
  checkCheckInProgression() {
    if (this.property?.photo?.fileName != null || this.property?.photo_B64 != null) {
      this.checkInCompleted = true;
    } else {
      this.checkInCompleted = false;
    }
  }
  checkNeedsProgression() {
    let missingQuestion = false;
    for (var i = 0, len = this.questions.length; i < len; i++) {
      const question = this.questions[i];
      const answeredQuestion = this.customerNeeds[question.question];
      if (answeredQuestion == null || answeredQuestion.length <= 0) {
        missingQuestion = true;
        break;
      }
    }
    this.needsCompleted = !missingQuestion;
  }
  inspectionProgressionFixtureCheck(entities) {
    let foundFixture = false;
    for (var i = 0, len = entities.length; i < len; i++) {
      const entity = entities[i];
      const validFixture = entity.fixtures.find((x) => x.valid);
      if (validFixture != null) {
        foundFixture = true;
        break;
      } else if (!foundFixture) {
        foundFixture = this.inspectionProgressionFixtureCheck(entity.entities);
      }
    }
    return foundFixture;
  }
  checkInspectionProgression() {
    let hasAtLeastOneFixture = false;
    if (this.property?.entity != null) {
      hasAtLeastOneFixture = this.inspectionProgressionFixtureCheck(this.property.entity.entities);
    }
    this.inspectionCompleted = hasAtLeastOneFixture && (this.property?.entity?.valid ?? false);
  }
  checkPresentationProgression() {
    this.presentationCompleted = this.inspectionCompleted;
  }
  checkJobSummaryProgression() {
    this.jobSummaryCompleted = this.presentationCompleted;
  }
  checkPricingProgression() {
    this.pricingCompleted = this.customPrice?.finalPrice != null;
  }
  checkDocumentsProgression() {
    let missingDocument = this.documents.length <= 0;
    for (var i = 0, len = this.documents.length; i < len; i++) {
      const document2 = this.documents[i];
      if (!document2.executed) {
        missingDocument = true;
        break;
      }
    }
    this.documentsCompleted = !missingDocument;
  }
  checkCompleted() {
    this.completed = this.status == AppointmentStatus.PendingSubmission || this.status == AppointmentStatus.Submitted;
  }
  checkNegotiationCompleted() {
    this.negotiationCompleted = this.customPrice?.finalPrice != null;
  }
  checkShouldBePending() {
    if (this.documentsValidForEstimate && this.paymentsValidForEstimate && this.status != AppointmentStatus.Submitted) {
      this.status = AppointmentStatus.PendingSubmission;
    }
  }
  checkProgression() {
    this.checkSummaryProgression();
    this.checkCheckInProgression();
    this.checkNeedsProgression();
    this.checkInspectionProgression();
    this.checkPresentationProgression();
    this.checkJobSummaryProgression();
    this.checkPricingProgression();
    this.checkDocumentsProgression();
    this.checkNegotiationCompleted();
    this.checkCompleted();
  }
  checkDocumentValidity() {
    this.documents.forEach((document2) => document2.checkSigningValidity());
    let invalidDocument = this.documents.find((x) => x.displayInSigning && x.customerFacing && (!x.customerValid || !x.consultantValid));
    this.documentsValidForEstimate = this.documents.length > 0 && invalidDocument == null;
    this.checkShouldBePending();
  }
  doesDocumentRuleApply(rule, matches, entities = void 0) {
    if (entities != null) {
      for (var i = 0, len = entities.length; i < len; i++) {
        const entity = entities[i];
        const entityMatches = this.checkIfCriteriaMatched(entity, rule);
        matches.push(...entityMatches);
        if (matches.length == rule.criteria.length) {
          return true;
        } else {
          for (var j = 0, jlen = entity.fixtures.length; j < jlen; j++) {
            const fixture = entity.fixtures[j];
            const fixtureMatches = this.checkIfCriteriaMatched(fixture, rule);
            matches.push(...fixtureMatches);
            if (matches.length == rule.criteria.length) {
              return true;
            }
          }
          return this.doesDocumentRuleApply(rule, matches, entity.entities);
        }
      }
    } else {
      if (this.job != null) {
        const jobMatches = this.checkIfCriteriaMatched(this.job, rule);
        matches.push(...jobMatches);
        if (matches.length == rule.criteria.length) {
          return true;
        }
      }
      if (this.property?.entity != null) {
        const propertyMatches = this.checkIfCriteriaMatched(this.property.entity, rule);
        matches.push(...propertyMatches);
        if (matches.length == rule.criteria.length) {
          return true;
        } else {
          for (var j = 0, jlen = this.property.entity.fixtures.length; j < jlen; j++) {
            const fixture = this.property.entity.fixtures[j];
            const fixtureMatches = this.checkIfCriteriaMatched(fixture, rule);
            matches.push(...fixtureMatches);
            if (matches.length == rule.criteria.length) {
              return true;
            }
          }
          return this.doesDocumentRuleApply(rule, matches, this.property.entity.entities);
        }
      }
    }
    return false;
  }
  checkIfDocumentApplies(document2) {
    const matchingRules = [];
    for (var i = 0, len = document2.rules.length; i < len; i++) {
      const rule = document2.rules[i];
      const ruleMatches = this.doesDocumentRuleApply(rule, []);
      if (ruleMatches) {
        matchingRules.push(rule);
      }
    }
    if (matchingRules.length == document2.rules.length) {
      return true;
    } else {
      return false;
    }
  }
  applyDocument(document2) {
    const existingDoc = this.documents.find((x) => x.id == document2.id);
    if (existingDoc == null) {
      const apptDoc = new AppointmentDocument(document2.id, document2.name, document2.customerFacing, document2.shopFacing, document2.standalone, document2.dynamic, document2.alwaysShow, document2.displayInSigning, document2.mapping, document2.displayOrder, document2.content);
      this.documents.push(apptDoc);
    } else {
      existingDoc.content = document2.content;
      existingDoc.mapping = document2.mapping;
    }
  }
  removeDocument(document2) {
    let existingIndex = this.documents.findIndex((x) => x.id == document2.id);
    if (existingIndex > -1) {
      this.documents.splice(existingIndex, 1);
    }
  }
  generateDocuments(override = false) {
    if (override || this.status != AppointmentStatus.Submitted && this.status != AppointmentStatus.PendingSubmission) {
      if (this.property?.entity != null && this.price?.finalPrice != null) {
        this.documents = [];
        let addenda = new AppointmentDocument(generateId(), "Scope of Work Acknowledgments", true, true, false, true, true, true, void 0, 2, "<p>{{logo}}</p><p>{{document.name}}</p>{{timestamp}}");
        for (var i = 0, len = this.availableDocuments.length; i < len; i++) {
          const document2 = this.availableDocuments[i];
          const applies = this.checkIfDocumentApplies(document2);
          if (applies) {
            if (document2.standalone) {
              this.applyDocument(document2);
            } else {
              const existingAddendum = addenda.documents.find((x) => x.id == document2.id);
              if (existingAddendum == null) {
                const addendum = new AppointmentDocument(document2.id, document2.name, document2.customerFacing, document2.shopFacing, false, document2.dynamic, document2.alwaysShow, document2.displayInSigning, document2.mapping, addenda.documents.length, document2.content);
                addenda.documents.push(addendum);
              }
            }
          } else {
            this.removeDocument(document2);
          }
        }
        if (addenda.documents.length > 0) {
          this.documents.push(addenda);
        } else {
          const addendaIndex = this.documents.findIndex((x) => x.name == addenda.name);
          if (addendaIndex > -1) {
            this.documents.splice(addendaIndex, 1);
          }
        }
      } else {
        this.documents = [];
      }
      this.checkDocumentValidity();
    }
  }
  // #endregion
  // #region Entities
  flattenEntity(entity, flattened) {
    flattened.push(...entity.entities);
    entity.entities.forEach((childEntity) => [
      flattened.push(...this.flattenEntity(childEntity, flattened))
    ]);
    return flattened;
  }
  findEntity(entityId) {
    if (this.property?.entity != null) {
      const flattened = this.flattenEntity(this.property.entity, [this.property.entity]);
      for (var i = 0, len = flattened.length; i < len; i++) {
        const entity = flattened[i];
        for (var j = 0, jlen = entity.fixtures.length; j < jlen; j++) {
          const fixture = entity.fixtures[j];
          if (fixture.id == entityId) {
            return fixture;
          }
        }
        for (var j = 0, jlen = entity.entities.length; j < jlen; j++) {
          const childEntity = entity.entities[j];
          if (childEntity.id == entityId) {
            return childEntity;
          }
        }
      }
    }
    return void 0;
  }
  findParent(entityId) {
    if (this.property?.entity != null) {
      const flattened = this.flattenEntity(this.property.entity, [this.property.entity]);
      for (var i = 0, len = flattened.length; i < len; i++) {
        const entity = flattened[i];
        for (var j = 0, jlen = entity.fixtures.length; j < jlen; j++) {
          const fixture = entity.fixtures[j];
          if (fixture.id == entityId) {
            return entity;
          }
        }
        for (var j = 0, jlen = entity.entities.length; j < jlen; j++) {
          const childEntity = entity.entities[j];
          if (childEntity.id == entityId) {
            return entity;
          }
        }
      }
    }
    return void 0;
  }
  // #endregion
  // #region Fixtures
  getFixtureCountByName(name, entities = [], count = 0, attributesToMatch = []) {
    entities.forEach((entity) => {
      entity.fixtures.forEach((f) => {
        const fixtureName = f.name.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
        if (fixtureName == name) {
          if (attributesToMatch.length > 0) {
            let matchCount = 0;
            f.attributes.forEach((attribute) => {
              const attributeName = attribute.name.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
              const attributeValue = attribute.values[0]?.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
              attributesToMatch.forEach((attributeToMatch) => {
                const matchingName = attributeToMatch.name.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
                const matchingValue = attributeToMatch.value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
                if (attributeName == matchingName && (attributeValue == matchingValue || attributeValue == "true" && matchingValue == "yes" || attributeValue == "false" && matchingValue == "no")) {
                  matchCount = matchCount + 1;
                }
              });
            });
            if (matchCount == attributesToMatch.length) {
              count = count + 1;
            }
          } else {
            count = count + 1;
          }
        }
      });
      count = this.getFixtureCountByName(name, entity.entities, count, attributesToMatch);
    });
    return count;
  }
  getFixtureCount(type, entities = [], count = 0) {
    entities.forEach((entity) => {
      entity.fixtures.forEach((f) => {
        if (f.imageSrc_Base64 == type) {
          count = count + 1;
        }
      });
      count = this.getFixtureCount(type, entity.entities, count);
    });
    return count;
  }
  renumberFixturesByType(type, entities = [], count = 1) {
    entities.forEach((entity) => {
      entity.fixtures.forEach((f) => {
        if (f.imageSrc_Base64 == type) {
          f.number = count;
          count = count + 1;
        }
      });
      count = this.renumberFixturesByType(type, entity.entities, count);
    });
    return count;
  }
  renumberFixtures() {
    this.availableFixtures.forEach((fc) => {
      fc.fixtures.forEach((af) => {
        this.renumberFixturesByType(af.imageSrc_Base64, this.property?.entity?.entities);
      });
    });
  }
  // #endregion
  // #region Rooms
  getRoomTypeCount(type, entities = [], roomCount = 0) {
    entities.forEach((e) => {
      if (e.type == PropertyEntityType.Room && e.name != null) {
        const name = e.name.toLowerCase();
        if (name == type) {
          roomCount = roomCount + 1;
        }
      } else {
        roomCount = this.getRoomTypeCount(type, e.entities, roomCount);
      }
    });
    return roomCount;
  }
  renumberRoomsByType(type, entities = [], roomCount = 0) {
    entities.forEach((e) => {
      if (e.type == PropertyEntityType.Room && e.name != null) {
        const name = e.name.toLowerCase();
        if (name == type) {
          roomCount = roomCount + 1;
          e.number = roomCount;
        }
      } else {
        roomCount = this.renumberRoomsByType(type, e.entities, roomCount);
      }
    });
    return roomCount;
  }
  renumberRooms() {
    this.renumberRoomsByType("bathroom", this.property?.entity?.entities);
  }
  // We support passing in an appointment so we can check one on demand without having stored it first
  validateLenders(log = false, appointment = this) {
    for (var i = 0, len = appointment.lenders.length; i < len; i++) {
      const lender = this.lenders[i];
      try {
        if (lender.amountFinanced == null || lender.amountFinanced < 0 || lender.applicationId == null) {
          if (log) {
            console.warn("LENDER VALIDATION: A lender on the appointment is missing required information.");
          }
          return false;
        }
      } catch {
      }
    }
    return true;
  }
  // We support passing in an appointment so we can check one on demand without having stored it first
  validatePaymentDetails(log = false, appointment = this, hasLender = false) {
    const price = appointment.customPrice ?? appointment.price;
    if (price == null) {
      if (log) {
        console.warn("PAYMENT DETAIL VALIDATION: No price on Appointment");
      }
      return false;
    }
    if (appointment.paymentSetting == null) {
      if (log) {
        console.warn("PAYMENT DETAIL VALIDATION: No payment settings on appointment.");
      }
      return false;
    }
    let totalDetailAmount = 0;
    for (var i = 0, len = appointment.paymentSetting.details.length; i < len; i++) {
      const detail = appointment.paymentSetting.details[i];
      if (detail.amount < detail.minimumAmount) {
        if (log) {
          console.warn(`PAYMENT DETAIL VALIDATION: Detail amounts must be greater or equal to their minimum amount.`);
        }
        return false;
      }
      if (detail.maximumAmount != null && detail.amount > detail.maximumAmount) {
        if (log) {
          console.warn(`PAYMENT DETAIL VALIDATION: Detail amounts must be less than or equal to their maximum amounts.`);
        }
        return false;
      }
      if (hasLender) {
        if (detail.lenderAmounts.length == 0) {
          return false;
        } else {
          for (var j = 0, jlen = detail.lenderAmounts.length; j < jlen; j++) {
            const lenderAmount = detail.lenderAmounts[j];
            if (lenderAmount.amount == null) {
              if (log) {
                console.warn("PAYMENT DETAIL VALIDATION: Detale lender amounts must be populated.");
              }
              return false;
            }
          }
        }
      }
      totalDetailAmount = totalDetailAmount + detail.amount;
    }
    if (totalDetailAmount != price.finalPrice) {
      if (log) {
        console.warn("PAYMENT DETAIL VALIDATION: Detail amounts must equal the final price of the job.");
      }
      return false;
    }
    return true;
  }
  // We support passing in an appointment so we can check one on demand without having stored it first
  validatePayments(log = false, appointment = this) {
    const price = appointment.customPrice ?? appointment.price;
    if (price == null) {
      if (log) {
        console.warn("PAYMENT VALIDATION: No price on Appointment");
      }
      return false;
    }
    const deposit = appointment.paymentSetting?.details.find((x) => x.name.toLowerCase().includes("deposit"));
    if (deposit != null) {
      let totalPaid = 0;
      appointment.payments.forEach((payment) => {
        totalPaid = totalPaid + payment.amount;
      });
      if (deposit.amount > 0 && totalPaid < deposit.amount) {
        if (log) {
          console.warn("PAYMENT VALIDATION: Total paid is less than deposit amount.");
        }
        return false;
      }
    }
    for (var i = 0, len = appointment.payments.length; i < len; i++) {
      const payment = appointment.payments[i];
      if (payment.amount < 0) {
        if (log) {
          console.warn("PAYMENT VALIDATION: A payment can't have a negative amount.");
        }
        return false;
      }
    }
    return true;
  }
  checkPaymentsValidity(log = false) {
    const paymentsValid = this.validatePayments(log);
    const lendersValid = this.validateLenders(log);
    const detailsValid = this.validatePaymentDetails(log);
    this.paymentsValidForEstimate = paymentsValid && lendersValid && detailsValid;
    this.checkShouldBePending();
  }
  // #endregion
  // #region Payment Details
  setPaymentSetting(setting) {
    const price = this.customPrice ?? this.price;
    if (price?.finalPrice != null) {
      const setDetails = [];
      for (var i = 0, len = setting.details.length; i < len; i++) {
        const detail = setting.details[i];
        let amount = safePrice(price.finalPrice * (detail.defaultPercent / 100));
        if (detail.maximumAmount != null && amount > detail.maximumAmount) {
          amount = safePrice(detail.maximumAmount);
        }
        if (detail.minimumAmount != null && amount < detail.minimumAmount) {
          amount = safePrice(detail.minimumAmount);
        }
        const setDetail = new PaymentDetail(detail, amount);
        setDetails.push(setDetail);
      }
      const setMethods = [];
      for (var i = 0, len = setting.methods.length; i < len; i++) {
        const method = setting.methods[i];
        const setMethod = Object.assign(new PaymentMethod(), method);
        setMethods.push(setMethod);
      }
      const setSetting = Object.assign(new PaymentSetting(), setting);
      setSetting.details = setDetails;
      setSetting.methods = setMethods;
      this.paymentSetting = setSetting;
    }
  }
  generatePaymentSetting() {
    const price = this.customPrice ?? this.price;
    if (price?.finalPrice != null) {
      let matchedSetting;
      paymentLoop: for (var i = 0, len = this.availablePaymentSettings.length; i < len; i++) {
        const setting = this.availablePaymentSettings[i];
        if (setting.skuTrigger != null) {
          for (var j = 0, jlen = price.details.length; j < jlen; j++) {
            const detail = price.details[j];
            const matchingSku = detail.lineItems.find((x) => x.skuId == setting.skuTrigger);
            if (matchingSku != null) {
              this.setPaymentSetting(setting);
              matchedSetting = setting;
              break paymentLoop;
            }
          }
        }
      }
      if (matchedSetting == null) {
        matchedSetting = this.availablePaymentSettings.find((x) => x.skuTrigger == null);
        if (matchedSetting != null) {
          this.setPaymentSetting(matchedSetting);
        }
      }
    }
  }
  // #endregion
  // #region Pricing
  parseReferenceQuantity(entityId, rule, attributes) {
    const regex = /\[([^\.]+)\.([^\]]*)\](-?\d+)/;
    const match = rule.result.match(regex);
    if (match != null) {
      const referenceId = entityId;
      const refAttribute = match[2].replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
      let quantity = 0;
      const attribute = attributes.find((x) => x.name.replace(/[^a-zA-Z0-9]/g, "").toLowerCase() == refAttribute);
      if (attribute != null) {
        const attrQuantity = Number.parseInt(attribute.values[0]);
        if (match[3] != null) {
          const refQuantity = Number.parseInt(match[3]);
          quantity = attrQuantity + refQuantity;
        } else {
          quantity = attrQuantity;
        }
      }
      const parsedQuantity = {
        referenceId,
        attribute: refAttribute,
        quantity
      };
      return parsedQuantity;
    }
    return null;
  }
  getMatchingEntityAttribute(entity, attributeId) {
    for (var i = 0, len = entity.attributes.length; i < len; i++) {
      const attribute = entity.attributes[i];
      if (attribute.id == attributeId) {
        return attribute;
      }
    }
    const parent = this.findParent(entity.id);
    if (parent != null) {
      const attribute = this.getMatchingEntityAttribute(parent, attributeId);
      if (attribute != null) {
        return attribute;
      }
    } else if (this.job != null) {
      for (var i = 0, len = this.job.attributes.length; i < len; i++) {
        const attribute = this.job.attributes[i];
        if (attribute.id == attributeId) {
          return attribute;
        }
      }
    }
    return void 0;
  }
  checkIfCriteriaMatched(entity, rule) {
    var matches = [];
    for (var i = 0, len = rule.criteria.length; i < len; i++) {
      const criteria = rule.criteria[i];
      let matched = false;
      switch (criteria.triggerType) {
        case EntityCriteriaTriggerType.Attribute:
          {
            let matchingAttribute = this.getMatchingEntityAttribute(entity, criteria.trigger);
            if (matchingAttribute != null) {
              for (var j = 0, jlen = matchingAttribute.values.length; j < jlen; j++) {
                const value = matchingAttribute.values[j];
                let localValue = value.toLowerCase();
                if (value == "true") {
                  localValue = "yes";
                } else if (value == "false") {
                  localValue = "no";
                }
                const possibleValues = [];
                criteria.possibleValues.forEach((value2) => {
                  possibleValues.push(value2.toLowerCase());
                });
                switch (criteria.type) {
                  case EntityRuleCriteriaType.Exact:
                    {
                      if (possibleValues.includes(localValue)) {
                        matches.push(`Value: ${localValue} on Attribute: ${matchingAttribute.name}`);
                        matched = true;
                      }
                    }
                    break;
                  case EntityRuleCriteriaType.GreaterThanOrEqual:
                    {
                      var relValue = criteria.possibleValues[0];
                      var attrValue = localValue;
                      if (relValue != null) {
                        var relValueNum = parseInt(relValue);
                        var attrValueNum = parseInt(attrValue);
                        if (attrValueNum >= relValueNum) {
                          matches.push(`Value: ${attrValueNum} is greater than or equal to ${relValueNum} on Attribute: ${matchingAttribute.name}`);
                          matched = true;
                        }
                      }
                    }
                    break;
                  case EntityRuleCriteriaType.GreaterThan:
                    {
                      var relValue = criteria.possibleValues[0];
                      var attrValue = localValue;
                      if (relValue != null) {
                        var relValueNum = parseInt(relValue);
                        var attrValueNum = parseInt(attrValue);
                        if (attrValueNum > relValueNum) {
                          matches.push(`Value: ${attrValueNum} is greater than ${relValueNum} on Attribute: ${matchingAttribute.name}`);
                          matched = true;
                        }
                      }
                    }
                    break;
                  case EntityRuleCriteriaType.LessThanOrEqual:
                    {
                      var relValue = criteria.possibleValues[0];
                      var attrValue = localValue;
                      if (relValue != null) {
                        var relValueNum = parseInt(relValue);
                        var attrValueNum = parseInt(attrValue);
                        if (attrValueNum <= relValueNum) {
                          matches.push(`Value: ${attrValueNum} is less than or equal to ${relValueNum} on Attribute: ${matchingAttribute.name}`);
                          matched = true;
                        }
                      }
                    }
                    break;
                  case EntityRuleCriteriaType.LessThan:
                    {
                      var relValue = criteria.possibleValues[0];
                      var attrValue = localValue;
                      if (relValue != null) {
                        var relValueNum = parseInt(relValue);
                        var attrValueNum = parseInt(attrValue);
                        if (attrValueNum <= relValueNum) {
                          matches.push(`Value: ${attrValueNum} is less than ${relValueNum} on Attribute: ${matchingAttribute.name}`);
                          matched = true;
                        }
                      }
                    }
                    break;
                }
              }
            }
          }
          break;
        case EntityCriteriaTriggerType.ParentRestriction:
          {
            const parent = this.findParent(entity.id);
            if (parent?.entityId == criteria.trigger) {
              matches.push(`Parent Entity is ${parent.type}`);
            }
          }
          break;
      }
      if (criteria.triggerType == "Attribute") {
      }
    }
    return matches;
  }
  calcPricingForFixture(baseFixture, fixture, details, customPrices = []) {
    for (var i = 0, len = baseFixture.rules.length; i < len; i++) {
      const rule = baseFixture.rules[i];
      var matches = [];
      var entityMatches = this.checkIfCriteriaMatched(fixture, rule);
      if (entityMatches.length == rule.criteria.length) {
        matches.push(...entityMatches);
      }
      if (matches.length > 0) {
        const sku = this.availableSkus.find((x) => x.id == rule.skuId);
        if (sku != null) {
          const skuPrice = customPrices.find((x) => x.skuId == sku.id && x.entityId == fixture.id)?.price ?? sku.price;
          const lineItem = {
            entityId: fixture.id,
            entity: fixture,
            skuId: sku.id,
            skuCategory: sku.category,
            name: sku.name,
            customerFacing: sku.customerFacing,
            isAttachment: sku.isAttachment,
            description: "",
            price: safePrice(skuPrice),
            quantity: 0
          };
          switch (rule.resultType) {
            case EntityRuleResultType.Quantity:
              {
                lineItem.quantity = parseInt(rule.result);
              }
              break;
            case EntityRuleResultType.ReferenceQuantity:
              {
                const parsedQuantity = this.parseReferenceQuantity(fixture.id, rule, fixture.attributes);
                if (parsedQuantity != null) {
                  lineItem.quantity = parsedQuantity.quantity;
                }
              }
              break;
          }
          var detail = {
            ruleId: rule.id,
            matches,
            lineItems: [lineItem],
            result: ""
          };
          details.push(detail);
        }
      }
    }
  }
  calcPricingForFixtures(fixtures, details, customPrices = []) {
    for (var i = 0, len = fixtures.length; i < len; i++) {
      const fixture = fixtures[i];
      let baseFixture = void 0;
      for (var j = 0, jlen = this.availableFixtures.length; j < jlen; j++) {
        const fc = this.availableFixtures[j];
        for (var k = 0, klen = fc.fixtures.length; k < klen; k++) {
          const fcFixture = fc.fixtures[k];
          if (fcFixture.entityId == fixture.entityId) {
            baseFixture = fcFixture;
            break;
          }
        }
      }
      if (baseFixture != null) {
        this.calcPricingForFixture(baseFixture, fixture, details, customPrices);
      }
    }
  }
  calcPricingForEntity(baseEntity, entity, details, customPrices = []) {
    for (var i = 0, len = baseEntity.rules.length; i < len; i++) {
      const rule = baseEntity.rules[i];
      var matches = [];
      var entityMatches = this.checkIfCriteriaMatched(entity, rule);
      if (entityMatches.length == rule.criteria.length) {
        matches.push(...entityMatches);
      }
      if (matches.length > 0) {
        const sku = this.availableSkus.find((x) => x.id == rule.skuId);
        if (sku != null) {
          const skuPrice = customPrices.find((x) => x.skuId == sku.id && x.entityId == entity.id)?.price ?? sku.price;
          const lineItem = {
            entityId: entity.id,
            entity,
            skuId: sku.id,
            skuCategory: sku.category,
            name: sku.name,
            customerFacing: sku.customerFacing,
            isAttachment: sku.isAttachment,
            description: "",
            price: safePrice(skuPrice),
            quantity: 0
          };
          switch (rule.resultType) {
            case EntityRuleResultType.Quantity:
              {
                lineItem.quantity = parseInt(rule.result);
              }
              break;
            case EntityRuleResultType.ReferenceQuantity:
              {
                const parsedQuantity = this.parseReferenceQuantity(entity.id, rule, entity.attributes);
                if (parsedQuantity != null) {
                  lineItem.quantity = parsedQuantity.quantity;
                }
              }
              break;
          }
          var detail = {
            ruleId: rule.id,
            matches,
            lineItems: [lineItem],
            result: ""
          };
          details.push(detail);
        }
      }
    }
    this.calcPricingForFixtures(entity.fixtures, details, customPrices);
    this.calcPricingForEntities(details, entity.entities, customPrices);
  }
  calcPricingForEntities(details, entities = void 0, customPrices = []) {
    if (entities != null) {
      for (var i = 0, len = entities.length; i < len; i++) {
        const entity = entities[i];
        let baseEntity = void 0;
        this.availableEntities.forEach((ec) => {
          for (var j2 = 0, jlen2 = ec.entities.length; j2 < jlen2; j2++) {
            const ecEntity = ec.entities[j2];
            if (ecEntity.type == entity.type) {
              baseEntity = ecEntity;
              break;
            }
          }
        });
        if (baseEntity != null) {
          this.calcPricingForEntity(baseEntity, entity, details, customPrices);
        }
      }
    } else {
      if (this.job != null) {
        let baseEntity = void 0;
        for (var i = 0, len = this.availableEntities.length; i < len; i++) {
          const ec = this.availableEntities[i];
          for (var j = 0, jlen = ec.entities.length; j < jlen; j++) {
            const ecEntity = ec.entities[j];
            if (ecEntity.type == this.job.type) {
              baseEntity = ecEntity;
              break;
            }
          }
        }
        if (baseEntity != null) {
          this.calcPricingForEntity(baseEntity, this.job, details, customPrices);
        }
      }
      if (this.property?.entity != null) {
        let baseEntity = void 0;
        for (var i = 0, len = this.availableEntities.length; i < len; i++) {
          const ec = this.availableEntities[i];
          for (var j = 0, jlen = ec.entities.length; j < jlen; j++) {
            const ecEntity = ec.entities[j];
            if (ecEntity.type == this.property.entity.type) {
              baseEntity = ecEntity;
              break;
            }
          }
        }
        if (baseEntity != null) {
          this.calcPricingForEntity(baseEntity, this.property.entity, details, customPrices);
        }
      }
    }
  }
  calcAblPrice(parPrice) {
    let ablPrice = parPrice * 0.8;
    if (ablPrice <= 0) {
      ablPrice = 0;
    }
    return safePrice(ablPrice);
  }
  calcTargetPrice(parPrice) {
    return safePrice(parPrice + parPrice * 0.4);
  }
  calcParPrice(customItems, details) {
    let parPrice = 0;
    customItems.forEach((item) => {
      if (item.price != null) {
        parPrice = parPrice + item.price;
      }
    });
    details.forEach((detail) => {
      detail.lineItems.forEach((lineItem) => {
        parPrice = parPrice + lineItem.price * lineItem.quantity;
      });
    });
    if (parPrice <= 0) {
      parPrice = 0;
    }
    return safePrice(parPrice);
  }
  calcPromotionalPrice(retailPrice) {
    let promotionalPrice = retailPrice - retailPrice * 0.2;
    return safePrice(promotionalPrice);
  }
  calcFinalPrice(targetPromoPrice) {
    return safePrice(targetPromoPrice);
  }
  calcPricing(override = false) {
    if (this.status == AppointmentStatus.InProgress || override) {
      const originalFinalPrice = this.price?.finalPrice;
      const details = [];
      const considerations = [];
      this.price?.customItems.forEach((item) => {
        considerations.push(item);
      });
      const customPrices = [];
      if (this.price != null) {
        for (var i = 0, len = this.price.details.length; i < len; i++) {
          const detail = this.price.details[i];
          for (var j = 0, jlen = detail.lineItems.length; j < jlen; j++) {
            const lineItem = detail.lineItems[j];
            if (lineItem.skuCategory == "CUSTOM") {
              customPrices.push({
                entityId: lineItem.entityId,
                skuId: lineItem.skuId,
                price: lineItem.price
              });
            }
          }
        }
      }
      this.calcPricingForEntities(details, void 0, customPrices);
      const parPrice = this.calcParPrice(considerations, details);
      const ablPrice = this.calcAblPrice(parPrice);
      const targetPrice = this.calcTargetPrice(parPrice);
      const targetPromoPrice = this.calcPromotionalPrice(targetPrice);
      let finalPrice = this.price?.finalPrice;
      if (targetPromoPrice != this.price?.targetPromoPrice) {
        finalPrice = this.calcFinalPrice(targetPromoPrice);
      }
      if (finalPrice != null) {
        finalPrice = safePrice(finalPrice);
      }
      this.price = new AppointmentPrice(void 0, details, this.price?.customItems, this.price?.appliedPromotions, finalPrice, targetPrice, ablPrice, parPrice, targetPromoPrice);
      if (this.price.finalPrice != originalFinalPrice) {
        this.priceChanged$.next();
      }
    }
  }
  // #endregion
  // #region Attributes
  updateMappedDefaultValues(attribute, parentEntity) {
    const regex = /^\[entity\.type=([^\]]+)\](?:\.\[attribute\.[^\]]+\])*\.\{\{([0-9]+|count)\}\}$/;
    const match = attribute.defaultValue?.match(regex);
    if (match) {
      const entityType = match[1];
      const countStr = match[2];
      const attributes = {};
      const iterator = attribute.defaultValue.matchAll(/\[attribute\.([^=]+)=([^[\]]+)\]/g);
      for (const m of iterator) {
        attributes[m[1]] = m[2];
      }
      const result = {
        entityType,
        attributes,
        count: countStr === "count" ? "count" : Number(countStr)
      };
      switch (result.entityType) {
        case "room":
          {
            for (const [key, value] of Object.entries(result.attributes)) {
              switch (key) {
                case "roomtype":
                  {
                    const roomCount = this.getRoomTypeCount(value, parentEntity?.entities);
                    attribute.values = [`${roomCount}`];
                  }
                  break;
              }
            }
          }
          break;
        case "hosebibb":
          {
            const attributesToMatch = [];
            for (const [key, value] of Object.entries(result.attributes)) {
              attributesToMatch.push({
                name: key,
                value
              });
            }
            const fixtureCount = this.getFixtureCountByName(entityType, parentEntity?.entities, 0, attributesToMatch);
            attribute.values = [`${fixtureCount}`];
          }
          break;
      }
    }
  }
  updateAttributes(entities = void 0) {
    if (entities != null) {
      entities.forEach((e) => {
        e.attributes.forEach((a) => {
          this.updateMappedDefaultValues(a, e);
        });
        this.updateAttributes(e.entities);
      });
    } else if (this?.property?.entity != null) {
      this.property.entity.attributes.forEach((attribute) => {
        if (this.property?.entity != null) {
          this.updateMappedDefaultValues(attribute, this.property.entity);
        }
      });
      this.property.entity.entities.forEach((e) => {
        e.attributes.forEach((a) => {
          this.updateMappedDefaultValues(a, e);
        });
        this.updateAttributes(e.entities);
      });
    }
  }
  findAttributes(entity, id, entities = void 0, attributes = []) {
    if (entities != null) {
      for (var i = 0, len = entities.length; i < len; i++) {
        const entity2 = entities[i];
        for (var j = 0, jlen = entity2.attributes.length; j < jlen; j++) {
          const attribute = entity2.attributes[j];
          if (attribute.id == id) {
            attributes.push(attribute);
          }
        }
        for (var j = 0, jlen = entity2.fixtures.length; j < jlen; j++) {
          const fixture = entity2.fixtures[j];
          for (var k = 0, klen = fixture.attributes.length; k < klen; k++) {
            const attribute = fixture.attributes[k];
            if (attribute.id == id) {
              attributes.push(attribute);
            }
          }
        }
        this.findAttributes(entity2, id, entity2.entities, attributes);
      }
    } else {
      for (var i = 0, len = entity.attributes.length; i < len; i++) {
        const attribute = entity.attributes[i];
        if (attribute.id == id) {
          attributes.push(attribute);
        }
      }
      for (var i = 0, len = entity.fixtures.length; i < len; i++) {
        const fixture = entity.fixtures[i];
        for (var j = 0, jlen = fixture.attributes.length; j < jlen; j++) {
          const attribute = fixture.attributes[j];
          if (attribute.id == id) {
            attributes.push(attribute);
          }
        }
      }
      this.findAttributes(entity, id, entity.entities, attributes);
    }
    return attributes;
  }
  getAvailableEntities() {
    const entities = [];
    this.availableEntities.forEach((category) => {
      category.entities.forEach((e) => {
        entities.push(e);
      });
    });
    return entities;
  }
  getAvailableFixtures() {
    const fixtures = [];
    this.availableFixtures.forEach((category) => {
      category.fixtures.forEach((f) => {
        fixtures.push(f);
      });
    });
    return fixtures;
  }
  getBaseRules(entity, attributeId) {
    const availableEntities = this.getAvailableEntities();
    for (var i = 0, len = availableEntities.length; i < len; i++) {
      const availEntity = availableEntities[i];
      const attribute = availEntity.attributes.find((x) => x.id == attributeId);
      if (attribute != null) {
        return attribute.rules;
      }
    }
    const availableFixtures = this.getAvailableFixtures();
    for (var i = 0, len = availableFixtures.length; i < len; i++) {
      const availFixture = availableFixtures[i];
      if (availFixture.entityId == entity.entityId) {
        const attribute = availFixture.attributes.find((x) => x.id == attributeId);
        if (attribute != null) {
          return attribute.rules;
        }
      }
    }
    return [];
  }
  processAttributeRules(entities = void 0) {
    if (entities != null) {
      entities.forEach((entity) => {
        if (entity.attributes.length > 0) {
          const targetAttributes = [];
          entity.attributes.forEach((attribute) => {
            this.processRulesForAttribute(attribute);
          });
        }
        entity.fixtures.forEach((fixture) => {
          const targetAttributes = [];
          fixture.attributes.forEach((attribute) => {
            this.processRulesForAttribute(attribute);
          });
        });
        this.processAttributeRules(entity.entities);
      });
    } else if (this?.property?.entity != null) {
      this.property.entity.attributes.forEach((attribute) => {
        this.processRulesForAttribute(attribute);
      });
      this.processAttributeRules(this.property.entity.entities);
    }
  }
  processRulesForAttribute(attribute) {
    if (attribute.appliedRules != null) {
      let shouldDisable = false;
      let shouldHide = false;
      let newValue;
      attribute.appliedRules.forEach((rule) => {
        if (rule.shouldDisable) {
          shouldDisable = true;
          shouldHide = true;
        }
        if (rule.targetValue != null) {
          newValue = rule.targetValue;
        }
      });
      if (shouldDisable) {
        attribute.disabled = true;
        attribute.values = [];
      } else {
        attribute.disabled = false;
      }
      if (shouldHide) {
        attribute.hiddenByRule = true;
      } else {
        attribute.hiddenByRule = false;
      }
      if (newValue != null) {
        attribute.values = [newValue];
      }
    }
  }
  applyAttributeRules(entities = void 0) {
    if (entities != null) {
      entities.forEach((entity) => {
        if (entity.attributes.length > 0) {
          const targetAttributes = [];
          entity.attributes.forEach((attribute) => {
            this.applyRulesForAttribute(entity, attribute, targetAttributes);
          });
        }
        entity.fixtures.forEach((fixture) => {
          const targetAttributes = [];
          fixture.attributes.forEach((attribute) => {
            this.applyRulesForAttribute(fixture, attribute, targetAttributes);
          });
        });
        this.applyAttributeRules(entity.entities);
      });
    } else if (this?.property?.entity != null) {
      const targetAttributes = [];
      this.property.entity.attributes.forEach((attribute) => {
        this.applyRulesForAttribute(this.property.entity, attribute, targetAttributes);
      });
      if (this.job != null) {
        this.job.attributes.forEach((attribute) => {
          this.applyRulesForAttribute(this.job, attribute, targetAttributes);
        });
      }
      this.applyAttributeRules(this.property.entity.entities);
      this.processAttributeRules();
    }
  }
  applyRulesForAttribute(entity, attribute, targetAttributes) {
    const rules = this.getBaseRules(entity, attribute.id);
    for (var i = 0, len = rules.length; i < len; i++) {
      const rule = rules[i];
      let targetAttributes2 = [];
      if (entity instanceof AppointmentPropertyEntity) {
        targetAttributes2 = this.findAttributes(entity, rule.targetAttributeId);
      } else {
        entity.attributes.forEach((attribute2) => {
          if (attribute2.id == rule.targetAttributeId) {
            targetAttributes2.push(attribute2);
          }
        });
      }
      let triggerValue = rule.triggerValue.toLocaleLowerCase();
      if (attribute.type == EntityAttributeType.Boolean) {
        if (triggerValue.toLocaleLowerCase() == "yes") {
          triggerValue = "true";
        } else {
          triggerValue = "false";
        }
      }
      targetAttributes2.forEach((targetAttribute) => {
        const sanitizedValues = [];
        attribute.values.forEach((value) => {
          sanitizedValues.push(value.toLocaleLowerCase());
        });
        if (targetAttribute.appliedRules == null) {
          targetAttribute.appliedRules = [];
        }
        if (sanitizedValues.includes(triggerValue)) {
          const ruleIndex = targetAttribute.appliedRules.findIndex((x) => x.id == rule.id);
          if (ruleIndex < 0) {
            targetAttribute.appliedRules.push(rule);
          }
        } else {
          const ruleIndex = targetAttribute.appliedRules.findIndex((x) => x.id == rule.id);
          if (ruleIndex > -1) {
            targetAttribute.appliedRules.splice(ruleIndex, 1);
          }
        }
      });
    }
  }
  // #endregion
  toJSON() {
    const safe = deepClone(this);
    return safe;
    return {
      id: this.id,
      accepted: this.accepted,
      accepted_Utc: this.accepted_Utc,
      assignedTo: this.assignedTo,
      assigned_Utc: this.assigned_Utc,
      customer: this.customer,
      property: this.property,
      jobId: this.jobId,
      job: this.job,
      opportunityNotes: this.opportunityNotes,
      opportunityTypes: this.opportunityTypes,
      opportunityPlumbingIssues: this.opportunityPlumbingIssues,
      opportunityCouponCode: this.opportunityCouponCode,
      status: this.status,
      statusDescription: this.statusDescription,
      customerNeeds: this.customerNeeds,
      payments: this.payments,
      paymentSetting: this.paymentSetting,
      lenders: this.lenders,
      price: this.price,
      customPrice: this.customPrice,
      dispositionStatus: this.dispositionStatus,
      selectedShopId: this.selectedShopId,
      preferredInstallDate: this.preferredInstallDate,
      documents: this.documents,
      lastStored: this.lastStored,
      lastSynced: this.lastSynced,
      scheduled_Utc: this.scheduled_Utc,
      created_Utc: this.created_Utc,
      lastUpdated_Utc: this.lastUpdated_Utc
    };
  }
};
var AppointmentPricingState;
(function(AppointmentPricingState2) {
  AppointmentPricingState2["Internal"] = "Internal";
  AppointmentPricingState2["External"] = "External";
  AppointmentPricingState2["Documents"] = "Documents";
})(AppointmentPricingState || (AppointmentPricingState = {}));
var AppointmentEventType;
(function(AppointmentEventType2) {
  AppointmentEventType2["Generic"] = "Generic";
  AppointmentEventType2["Open"] = "Open";
  AppointmentEventType2["Close"] = "Close";
  AppointmentEventType2["Create"] = "Create";
  AppointmentEventType2["Accept"] = "Accept";
  AppointmentEventType2["Schedule"] = "Schedule";
  AppointmentEventType2["Status"] = "Status";
  AppointmentEventType2["ViewingStatus"] = "ViewingStatus";
  AppointmentEventType2["Property"] = "Property";
  AppointmentEventType2["Structure"] = "Structure";
  AppointmentEventType2["Floor"] = "Floor";
  AppointmentEventType2["Room"] = "Room";
  AppointmentEventType2["Fixture"] = "Fixture";
  AppointmentEventType2["CheckIn"] = "CheckIn";
  AppointmentEventType2["Needs"] = "Needs";
  AppointmentEventType2["Pricing"] = "Pricing";
})(AppointmentEventType || (AppointmentEventType = {}));
var AppointmentEventSubType;
(function(AppointmentEventSubType2) {
  AppointmentEventSubType2["Added"] = "Added";
  AppointmentEventSubType2["Removed"] = "Removed";
  AppointmentEventSubType2["Changed"] = "Changed";
  AppointmentEventSubType2["Started"] = "Started";
  AppointmentEventSubType2["Completed"] = "Completed";
})(AppointmentEventSubType || (AppointmentEventSubType = {}));
var AppointmentStatus;
(function(AppointmentStatus2) {
  AppointmentStatus2["Open"] = "Open";
  AppointmentStatus2["Canceled"] = "Canceled";
  AppointmentStatus2["InProgress"] = "InProgress";
  AppointmentStatus2["PendingSignatures"] = "PendingSignatures";
  AppointmentStatus2["PendingSubmission"] = "PendingSubmission";
  AppointmentStatus2["Submitted"] = "Submitted";
  AppointmentStatus2["Dispositioned"] = "Dispositioned";
})(AppointmentStatus || (AppointmentStatus = {}));
var AppointmentViewingStatus;
(function(AppointmentViewingStatus2) {
  AppointmentViewingStatus2["CheckIn"] = "CheckIn";
  AppointmentViewingStatus2["Summary"] = "Summary";
  AppointmentViewingStatus2["DetailedSummary"] = "DetailedSummary";
  AppointmentViewingStatus2["Needs"] = "Needs";
  AppointmentViewingStatus2["Diagram"] = "Diagram";
  AppointmentViewingStatus2["Presentation"] = "Presentation";
  AppointmentViewingStatus2["Completion"] = "Completion";
  AppointmentViewingStatus2["Inspection"] = "Inspection";
  AppointmentViewingStatus2["Documents"] = "Documents";
  AppointmentViewingStatus2["JobSummary"] = "JobSummary";
  AppointmentViewingStatus2["Pricing"] = "Pricing";
})(AppointmentViewingStatus || (AppointmentViewingStatus = {}));
var AppointmentDocument = class extends Document {
  constructor(id, name, customerFacing, shopFacing, standalone, dynamic, alwaysShow, displayInSigning = true, mapping, displayOrder = 0, content = void 0, executed = false, signers = [], rules = [], documents = [], signatures = [], userContent = [], lastUpdated_Utc = void 0, created_Utc = void 0, generatedContent = void 0, originalHash = void 0) {
    super(id, name, customerFacing, shopFacing, standalone, dynamic, alwaysShow, displayInSigning, mapping, displayOrder, content, executed, signers, rules, documents, signatures, userContent, lastUpdated_Utc, created_Utc);
    this.documents = [];
    this.validForExecution = false;
    this.validForSigner = false;
    this.uiDirection = "";
    this.rendered = false;
    this.checkedValidation = false;
    this.generatedContent = generatedContent;
    this.documents = documents;
    this.originalHash = originalHash;
  }
};
var NoteAudience;
(function(NoteAudience2) {
  NoteAudience2["Customer"] = "Customer";
  NoteAudience2["Shop"] = "Shop";
})(NoteAudience || (NoteAudience = {}));
var AppointmentPropertyEntity = class extends PropertyEntity {
  get hasInvalidAttributes() {
    const invalidAttribute = this.attributes.find((x) => !x.valid);
    return invalidAttribute != null;
  }
  get hasInvalidEntities() {
    const invalidEntity = this.entities.find((x) => !x.valid);
    return invalidEntity != null;
  }
  get hasInvalidFixtures() {
    const invalidFixture = this.fixtures.find((x) => !x.valid);
    return invalidFixture != null;
  }
  get valid() {
    const photosCount = this.photos.length + this.photos_B64.length;
    if (this.hasInvalidAttributes || this.hasInvalidFixtures || this.hasInvalidEntities || this.type == PropertyEntityType.Room && photosCount == 0) {
      return false;
    }
    return true;
  }
  updateRender(render) {
    this.localRender = render;
    this.render = void 0;
  }
  constructor(id, entityId, type, name, number, attributes = [], fixtures = [], renderDimensions, metafields, rules, photos = [], photos_B64 = [], render, localRender, notes) {
    super(id, entityId, type, name, attributes, fixtures);
    this.appointmentId = "";
    this.entities = [];
    this.fixtures = [];
    this.metafields = {};
    this.photos = [];
    this.photos_B64 = [];
    this.number = 1;
    this.resizing = false;
    this.moving = false;
    this.active = false;
    this.renderDimensions = new RenderDimensions(renderDimensions.x, renderDimensions.y, renderDimensions.width, renderDimensions.height, renderDimensions.rotation);
    this.metafields = metafields;
    this.rules = rules;
    this.photos = photos;
    this.photos_B64 = photos_B64;
    this.render = render;
    this.updateRender(localRender);
    this.notes = notes;
    this.number = number;
  }
  toFlat() {
    return {
      id: this.id,
      entityId: this.entityId,
      type: this.type,
      name: this.name,
      metafields: this.metafields,
      number: this.number
    };
  }
  toJSON() {
    return {
      id: this.id,
      entityId: this.entityId,
      type: this.type,
      name: this.name,
      attributes: this.attributes,
      entities: this.entities,
      fixtures: this.fixtures,
      rules: this.rules,
      notes: this.notes,
      renderDimensions: this.renderDimensions,
      metafields: this.metafields,
      photos: this.photos,
      photos_B64: this.photos_B64,
      render: this.render,
      number: this.number
    };
  }
};
var AppointmentFixture = class extends Fixture {
  get hasInvalidAttributes() {
    const invalidAttribute = this.attributes.find((x) => !x.valid);
    return invalidAttribute != null;
  }
  get valid() {
    const photosCount = this.photos.length + this.photos_B64.length;
    if (this.hasInvalidAttributes || photosCount == 0) {
      return false;
    }
    return true;
  }
  constructor(id, entityId, name, imageSrc_Base64, number, attributes = [], renderDimensions, photos = [], photos_B64 = [], notes) {
    super(id, entityId, name, imageSrc_Base64, attributes);
    this.photos = [];
    this.photos_B64 = [];
    this.number = 1;
    this.rotating = false;
    this.resizing = false;
    this.moving = false;
    this.renderDimensions = new RenderDimensions(renderDimensions.x, renderDimensions.y, renderDimensions.width, renderDimensions.height, renderDimensions.rotation);
    this.photos_B64 = photos_B64;
    this.photos = photos;
    this.notes = notes;
    this.number = number;
  }
  toJSON() {
    return {
      id: this.id,
      entityId: this.entityId,
      name: this.name,
      imageSrc_Base64: this.imageSrc_Base64,
      attributes: this.attributes,
      rules: this.rules,
      notes: this.notes,
      renderDimensions: this.renderDimensions,
      photos: this.photos,
      photos_B64: this.photos_B64,
      number: this.number
    };
  }
};

export {
  require_core,
  require_sha256,
  require_hmac,
  require_hmac_sha256,
  generateId,
  generateDeterministicId,
  hashString,
  deepClone,
  getDateOnly,
  safePrice,
  safeEquivalentPrice,
  EntityAttribute,
  EntityAttributeType,
  Property,
  PropertyEntityRenderDimensions,
  PropertyEntity,
  PropertyEntityType,
  RenderDimensions,
  Fixture,
  AppointmentPrice,
  EntityRuleResultType,
  EntityCriteriaTriggerType,
  EntityRuleCriteriaType,
  PaymentSetting,
  PaymentDetail,
  PaymentMethod,
  PaymentMethodType,
  Payment,
  PaymentStatus,
  toCanvas,
  toPng,
  Document,
  DocumentUserContent,
  DocumentSignature,
  DocumentSigningConsent,
  DocumentFieldMapping,
  DocumentSigner,
  DocumentSignerType,
  Appointment,
  AppointmentEventType,
  AppointmentEventSubType,
  AppointmentStatus,
  AppointmentDocument,
  NoteAudience,
  AppointmentPropertyEntity,
  AppointmentFixture
};
//# sourceMappingURL=chunk-N36JE2BE.js.map
