"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var FieldValue_exports = {};
__export(FieldValue_exports, {
  FieldValue: () => FieldValue
});
module.exports = __toCommonJS(FieldValue_exports);
var import_general = require("@matter/general");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
function FieldValue(value) {
  if (typeof value === "function") {
    throw new import_general.UnexpectedDataError("Cannot cast function to FieldValue");
  }
  if (typeof value === "object" && value !== null) {
    if (Array.isArray(value)) {
      return value;
    }
    if (value instanceof Date) {
      return value;
    }
    return value;
  }
  return value;
}
((FieldValue2) => {
  FieldValue2.percent = "percent";
  FieldValue2.celsius = "celsius";
  FieldValue2.reference = "reference";
  FieldValue2.properties = "properties";
  FieldValue2.bytes = "bytes";
  FieldValue2.none = "none";
  function is(value, type) {
    return value && value.type === type;
  }
  FieldValue2.is = is;
  FieldValue2.Invalid = /* @__PURE__ */ Symbol("invalid");
  FieldValue2.None = {
    type: FieldValue2.none
  };
  function Reference(name) {
    return { type: FieldValue2.reference, name };
  }
  FieldValue2.Reference = Reference;
  function Celsius(value) {
    return { type: FieldValue2.celsius, value };
  }
  FieldValue2.Celsius = Celsius;
  function Percent(value) {
    return { type: FieldValue2.percent, value };
  }
  FieldValue2.Percent = Percent;
  function Bytes(value) {
    return { type: FieldValue2.bytes, value: typeof value === "string" ? value : import_general.Bytes.toHex(import_general.Bytes.of(value)) };
  }
  FieldValue2.Bytes = Bytes;
  function serialize(value) {
    if (value === null) {
      return "null";
    }
    if (is(value, FieldValue2.none)) {
      return "";
    }
    if (is(value, FieldValue2.reference)) {
      return value.name;
    }
    if (is(value, FieldValue2.celsius)) {
      return `${value.value}\xB0C`;
    }
    if (is(value, FieldValue2.percent)) {
      return `${value.value}%`;
    }
    if (is(value, FieldValue2.properties)) {
      return (0, import_general.serialize)(value.properties) ?? "?";
    }
    return value.toString();
  }
  FieldValue2.serialize = serialize;
  function numericValue(value, typeName) {
    if (typeof value === "boolean") {
      return value ? 1 : 0;
    }
    if (typeof value === "number") {
      return value;
    }
    if (is(value, FieldValue2.celsius)) {
      switch (typeName) {
        case "temperature":
        case "temp-diff":
        // Thermostat < 1.2
        case "TemperatureDifference":
          return value.value * 100;
        case "temp-u8":
        // Thermostat < 1.2
        case "UnsignedTemperature":
        // Thermostat 1.2+
        case "temp-s8":
        // Thermostat < 1.2
        case "SignedTemperature":
          return value.value * 10;
      }
      return;
    }
    if (is(value, FieldValue2.percent)) {
      switch (typeName) {
        case "percent100ths":
          return value.value * 100;
        default:
          return value.value;
      }
    }
  }
  FieldValue2.numericValue = numericValue;
  function objectValue(value) {
    if (is(value, FieldValue2.properties)) {
      return value.properties;
    }
  }
  FieldValue2.objectValue = objectValue;
  function unwrap(value, typeName) {
    if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date) {
      return value;
    }
    const type = value.type;
    switch (type) {
      case "properties":
        return objectValue(value);
      case "reference":
        return;
      case "none":
        return;
      // undefined
      case "percent":
      case "celsius":
        return numericValue(value, typeName);
      case void 0:
        throw new import_general.UnexpectedDataError(`Field value objects must be wrappers with "type" field`);
      default:
        throw new import_general.UnexpectedDataError(`Unsupported wrapped object type "${type}"`);
    }
  }
  FieldValue2.unwrap = unwrap;
  function referenced(value) {
    if (is(value, FieldValue2.reference)) {
      return value.name;
    }
  }
  FieldValue2.referenced = referenced;
  function cast(type, value) {
    if (value === void 0 || value === null || type === "any") {
      return value;
    }
    if (value === "null" || value === "NULL") {
      return null;
    }
    if (value === "") {
      if (type === "string") {
        return "";
      }
      return void 0;
    }
    if (FieldValue2.is(value, FieldValue2.reference)) {
      return value;
    }
    switch (type) {
      case "string":
        return value.toString();
      case "boolean":
        if (typeof value === "string") {
          value = value.trim().toLowerCase();
        }
        return value !== "false" && value !== "no" && !!value;
      case "bitmap":
      case "enum":
        if (FieldValue2.is(value, FieldValue2.properties) && type === "bitmap") {
          return value;
        }
        const id = Number(value);
        if (!Number.isFinite(id)) {
          if (typeof value === "string") {
            return value;
          }
          return;
        }
        return id;
      case "integer":
        if (typeof value === "string") {
          let type2;
          if (value.endsWith("\xB0C")) {
            type2 = FieldValue2.celsius;
          } else if (value.endsWith("%")) {
            type2 = FieldValue2.percent;
          }
          if (type2) {
            value = Number.parseInt(value);
            if (!Number.isFinite(value)) {
              return FieldValue2.Invalid;
            }
            return { type: type2, value };
          }
          const match = value.match(/^(0x[0-9a-f]+|0b[01]+|\d+)/i);
          if (match) {
            value = match[1];
          }
        }
        try {
          switch (typeof value) {
            case "string":
            case "number":
            case "bigint":
            case "boolean":
              break;
            default:
              if (FieldValue2.is(value, FieldValue2.celsius) || FieldValue2.is(value, FieldValue2.percent)) {
                return value;
              }
              return FieldValue2.Invalid;
          }
          const i = BigInt(value);
          const n = Number(i);
          if (BigInt(n) === i) {
            return n;
          }
          return i;
        } catch (e) {
          if (e instanceof SyntaxError) {
            return FieldValue2.Invalid;
          }
          throw e;
        }
      case "float":
        const float = Number(value);
        if (!Number.isFinite(float)) {
          return FieldValue2.Invalid;
        }
        return float.valueOf();
      case "date":
        if (value instanceof Date) {
          return value;
        }
        if (typeof value !== "string") {
          return FieldValue2.Invalid;
        }
        value = new Date(value);
        if (!Number.isFinite(value.valueOf())) {
          return FieldValue2.Invalid;
        }
        return value;
      case "object":
        if (FieldValue2.is(value, FieldValue2.properties)) {
          return value;
        }
        break;
      case "bytes":
        if (value === "empty") {
          return void 0;
        }
        if (FieldValue2.is(value, FieldValue2.bytes)) {
          return value;
        }
        if (typeof value === "string" || import_general.Bytes.isBytes(value)) {
          return Bytes(value);
        }
        break;
      case "array":
        if (value === "0" || value === "{0,0}") {
          return;
        }
        if (value === "empty" || value === "[]" || value === "{}") {
          return [];
        }
        if (Array.isArray(value)) {
          return value;
        }
        return FieldValue2.Invalid;
    }
    return FieldValue2.Invalid;
  }
  FieldValue2.cast = cast;
})(FieldValue || (FieldValue = {}));
//# sourceMappingURL=FieldValue.js.map
