"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
var __typeError = (msg) => {
  throw TypeError(msg);
};
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
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 __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
var __runInitializers = (array, flags, self, value) => {
  for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
  return value;
};
var __decorateElement = (array, flags, name, decorators, target, extra) => {
  var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
  var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
  var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
  var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
    return __privateGet(this, extra);
  }, set [name](x) {
    return __privateSet(this, extra, x);
  } }, name));
  k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
  for (var i = decorators.length - 1; i >= 0; i--) {
    ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
    if (k) {
      ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
      if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
      if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
    }
    it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
    if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
    else if (typeof it !== "object" || it === null) __typeError("Object expected");
    else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
  }
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
};
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
var DoorLockServer_exports = {};
__export(DoorLockServer_exports, {
  DoorLockBaseServer: () => DoorLockBaseServer,
  DoorLockServer: () => DoorLockServer
});
module.exports = __toCommonJS(DoorLockServer_exports);
var import_Supervision = require("#behavior/supervision/Supervision.js");
var import_general = require("@matter/general");
var import_model = require("@matter/model");
var import_types = require("@matter/types");
var import_door_lock = require("@matter/types/clusters/door-lock");
var import_DoorLockBehavior = require("./DoorLockBehavior.js");
var import_LockAuth = require("./LockAuth.js");
var import_LockSchedule = require("./LockSchedule.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const AlarmCode = import_door_lock.DoorLock.AlarmCode;
const CredentialRule = import_door_lock.DoorLock.CredentialRule;
const CredentialType = import_door_lock.DoorLock.CredentialType;
const DataOperationType = import_door_lock.DoorLock.DataOperationType;
const DoorState = import_door_lock.DoorLock.DoorState;
const LockDataType = import_door_lock.DoorLock.LockDataType;
const LockOperationType = import_door_lock.DoorLock.LockOperationType;
const LockState = import_door_lock.DoorLock.LockState;
const OperationError = import_door_lock.DoorLock.OperationError;
const OperationSource = import_door_lock.DoorLock.OperationSource;
const UserStatus = import_door_lock.DoorLock.UserStatus;
const UserType = import_door_lock.DoorLock.UserType;
const DoorLockBaseServerClass = import_DoorLockBehavior.DoorLockBehavior.with(
  "PinCredential",
  "RfidCredential",
  "FingerCredentials",
  "FaceCredentials",
  "DoorPositionSensor",
  "CredentialOverTheAirAccess",
  "Unbolting",
  "User",
  "WeekDayAccessSchedules",
  "YearDayAccessSchedules",
  "HolidaySchedules"
);
class DoorLockBaseServer extends DoorLockBaseServerClass {
  initialize() {
    const state = this.state;
    if (!Object.values(state.supportedOperatingModes).some((v) => v)) {
      state.supportedOperatingModes = { vacation: true, privacy: true, passage: true, alwaysSet: 2047 };
    } else if (state.supportedOperatingModes.alwaysSet !== 2047) {
      throw new import_general.ImplementationError(
        `DoorLockServer: The "alwaysSet" bit-range in supportedOperatingModes must be set. Please check the specification about the meaning of this field because bits are inverted here!`
      );
    }
    if (!state.users) {
      state.users = [];
    }
    if (!state.credentials) {
      state.credentials = [];
    }
    if (!state.weekDaySchedules) {
      state.weekDaySchedules = [];
    }
    if (!state.yearDaySchedules) {
      state.yearDaySchedules = [];
    }
    if (!state.holidaySchedules) {
      state.holidaySchedules = [];
    }
    if (!state.credentialKey) {
      state.credentialKey = import_general.Bytes.of(this.env.get(import_general.Crypto).randomBytes(16));
      if (state.credentials.length > 0) {
        const auth = this.auth;
        state.credentials = state.credentials.map((c) => ({
          ...c,
          credentialData: auth.encrypt(c.credentialData)
        }));
      }
    }
    this.reactTo(this.events.doorState$Changed, this.#handleDoorStateChange);
  }
  [Symbol.asyncDispose]() {
    this.#stopAutoRelockTimer();
    return super[Symbol.asyncDispose]();
  }
  // ── Core Lock Operations ─────────────────────────────────────────────────
  lockDoor(request) {
    this.#validatePinIfRequired(request.pinCode, LockOperationType.Lock);
    this.state.lockState = LockState.Locked;
    this.#stopAutoRelockTimer();
    this.#emitLockOperation(LockOperationType.Lock, request.pinCode);
  }
  unlockDoor(request) {
    this.#validatePinIfRequired(request.pinCode, LockOperationType.Unlock);
    this.state.lockState = LockState.Unlocked;
    this.#emitLockOperation(LockOperationType.Unlock, request.pinCode);
    this.#scheduleAutoRelock();
  }
  unlockWithTimeout(request) {
    this.#validatePinIfRequired(request.pinCode, LockOperationType.Unlock);
    this.state.lockState = LockState.Unlocked;
    this.#emitLockOperation(LockOperationType.Unlock, request.pinCode);
    this.#scheduleAutoRelock(request.timeout);
  }
  unboltDoor(request) {
    this.#validatePinIfRequired(request.pinCode, LockOperationType.Unlatch);
    this.state.lockState = LockState.Unlatched;
    this.#emitLockOperation(LockOperationType.Unlatch, request.pinCode);
    this.#scheduleAutoRelock();
  }
  // ── Credential Storage (overridable) ─────────────────────────────────────
  //
  // The default implementation uses reversible encryption (AES-128-CCM) rather than hashing because the legacy
  // non-User commands (getPinCode, getRfidCode) must return plaintext credential data. Deployments where credential
  // secrecy is critical should override `cipher` (for HSM-backed encryption) or `auth` (for an external credential
  // store).
  /**
   * The cipher used for credential encryption. Override to integrate with an HSM or other secure storage.
   */
  get cipher() {
    return new import_general.AesCipher(this.env.get(import_general.Crypto), this.state.credentialKey);
  }
  /**
   * The credential/user store with integrated encryption. Override to replace the entire storage backend.
   */
  get auth() {
    return new import_LockAuth.LockAuth.Store(this.state, this.cipher);
  }
  // ── User Database (USR) ──────────────────────────────────────────────────
  setUser(request) {
    const { operationType, userIndex } = request;
    const maxUsers = this.state.numberOfTotalUsersSupported;
    const fabricIndex = this.#fabricIndex;
    if (userIndex < 1 || userIndex > maxUsers) {
      throw new import_types.StatusResponseError("Invalid user index", import_types.Status.InvalidCommand);
    }
    const auth = this.auth;
    const existing = auth.findUser(userIndex);
    if (operationType === DataOperationType.Add) {
      if (existing) {
        throw new import_door_lock.DoorLock.OccupiedError("User slot is occupied");
      }
      auth.addUser({
        userIndex,
        userName: request.userName ?? "",
        userUniqueId: request.userUniqueId ?? null,
        userStatus: request.userStatus ?? UserStatus.OccupiedEnabled,
        userType: request.userType ?? UserType.UnrestrictedUser,
        credentialRule: request.credentialRule ?? CredentialRule.Single,
        credentials: [],
        creatorFabricIndex: fabricIndex,
        lastModifiedFabricIndex: fabricIndex
      });
      this.#emitLockUserChange(LockDataType.UserIndex, DataOperationType.Add, userIndex, fabricIndex, null);
    } else if (operationType === DataOperationType.Modify) {
      if (!existing) {
        throw new import_types.StatusResponseError("User slot is available", import_types.Status.InvalidCommand);
      }
      if (request.userName !== null && fabricIndex !== existing.creatorFabricIndex) {
        throw new import_types.StatusResponseError("Cannot modify userName from different fabric", import_types.Status.InvalidCommand);
      }
      if (request.userUniqueId !== null && fabricIndex !== existing.creatorFabricIndex) {
        throw new import_types.StatusResponseError(
          "Cannot modify userUniqueId from different fabric",
          import_types.Status.InvalidCommand
        );
      }
      auth.replaceUser(userIndex, {
        ...existing,
        userName: request.userName ?? existing.userName,
        userUniqueId: request.userUniqueId ?? existing.userUniqueId,
        userStatus: request.userStatus ?? existing.userStatus,
        userType: request.userType ?? existing.userType,
        credentialRule: request.credentialRule ?? existing.credentialRule,
        lastModifiedFabricIndex: fabricIndex
      });
      this.#emitLockUserChange(LockDataType.UserIndex, DataOperationType.Modify, userIndex, fabricIndex, null);
    } else {
      throw new import_types.StatusResponseError("Invalid operation type", import_types.Status.InvalidCommand);
    }
  }
  getUser(request) {
    const maxUsers = this.state.numberOfTotalUsersSupported;
    if (request.userIndex < 1 || request.userIndex > maxUsers) {
      throw new import_types.StatusResponseError("Invalid user index", import_types.Status.InvalidCommand);
    }
    const auth = this.auth;
    const user = auth.findUser(request.userIndex);
    const nextUserIndex = auth.findNextOccupiedUserIndex(request.userIndex);
    if (!user) {
      return {
        userIndex: request.userIndex,
        userName: null,
        userUniqueId: null,
        userStatus: null,
        userType: null,
        credentialRule: null,
        credentials: null,
        creatorFabricIndex: null,
        lastModifiedFabricIndex: null,
        nextUserIndex
      };
    }
    return {
      userIndex: user.userIndex,
      userName: user.userName,
      userUniqueId: user.userUniqueId,
      userStatus: user.userStatus,
      userType: user.userType,
      credentialRule: user.credentialRule,
      credentials: [...user.credentials],
      creatorFabricIndex: user.creatorFabricIndex,
      lastModifiedFabricIndex: user.lastModifiedFabricIndex,
      nextUserIndex
    };
  }
  clearUser(request) {
    const { userIndex } = request;
    const maxUsers = this.state.numberOfTotalUsersSupported;
    const fabricIndex = this.#fabricIndex;
    const auth = this.auth;
    if (userIndex === 65534) {
      for (const user2 of auth.users) {
        this.#clearCredentialsForUser(auth, user2.userIndex);
        this.#clearSchedulesForUser(user2.userIndex);
      }
      auth.clearUsers();
      this.#emitLockUserChange(LockDataType.UserIndex, DataOperationType.Clear, 65534, fabricIndex, null);
      return;
    }
    if (userIndex < 1 || userIndex > maxUsers) {
      throw new import_types.StatusResponseError("Invalid user index", import_types.Status.InvalidCommand);
    }
    const user = auth.findUser(userIndex);
    if (!user) {
      return;
    }
    this.#clearCredentialsForUser(auth, userIndex);
    this.#clearSchedulesForUser(userIndex);
    auth.removeUser(userIndex);
    this.#emitLockUserChange(LockDataType.UserIndex, DataOperationType.Clear, userIndex, fabricIndex, null);
  }
  // ── Credential Management (USR) ──────────────────────────────────────────
  setCredential(request) {
    const { operationType, credential, credentialData, userIndex, userStatus, userType } = request;
    const fabricIndex = this.#fabricIndex;
    const maxCredentials = this.#maxCredentialsForType(credential.credentialType);
    const auth = this.auth;
    if (credential.credentialIndex < 0 || credential.credentialIndex > maxCredentials) {
      return { status: import_types.Status.InvalidCommand, userIndex: null, nextCredentialIndex: null };
    }
    if (!this.#validateCredentialDataLength(credential.credentialType, credentialData)) {
      return { status: import_types.Status.InvalidCommand, userIndex: null, nextCredentialIndex: null };
    }
    if (auth.isDuplicateCredential(credential.credentialType, credentialData, credential.credentialIndex)) {
      return { status: import_types.Status.Failure, userIndex: null, nextCredentialIndex: null };
    }
    const nextCredentialIndex = auth.findNextAvailableCredentialIndex(
      credential.credentialType,
      credential.credentialIndex,
      maxCredentials
    );
    if (operationType === DataOperationType.Add) {
      const existingCred = auth.findCredential(credential.credentialType, credential.credentialIndex);
      if (existingCred) {
        return { status: import_types.Status.Failure, userIndex: null, nextCredentialIndex };
      }
      auth.addCredential(credential.credentialType, credential.credentialIndex, credentialData, fabricIndex);
      let createdUserIndex = null;
      if (userIndex === null) {
        const newUserIndex = auth.findAvailableUserIndex(this.state.numberOfTotalUsersSupported);
        if (newUserIndex === null) {
          auth.removeCredential(credential.credentialType, credential.credentialIndex);
          return { status: import_types.Status.ResourceExhausted, userIndex: null, nextCredentialIndex };
        }
        auth.addUser({
          userIndex: newUserIndex,
          userName: "",
          userUniqueId: 4294967295,
          userStatus: userStatus ?? UserStatus.OccupiedEnabled,
          userType: userType ?? UserType.UnrestrictedUser,
          credentialRule: CredentialRule.Single,
          credentials: [
            { credentialType: credential.credentialType, credentialIndex: credential.credentialIndex }
          ],
          creatorFabricIndex: fabricIndex,
          lastModifiedFabricIndex: fabricIndex
        });
        createdUserIndex = newUserIndex;
        this.#emitLockUserChange(
          LockDataType.UserIndex,
          DataOperationType.Add,
          newUserIndex,
          fabricIndex,
          credential.credentialIndex
        );
      } else {
        const user = auth.findUser(userIndex);
        if (!user) {
          auth.removeCredential(credential.credentialType, credential.credentialIndex);
          return { status: import_types.Status.InvalidCommand, userIndex: null, nextCredentialIndex };
        }
        if (fabricIndex !== user.creatorFabricIndex) {
          auth.removeCredential(credential.credentialType, credential.credentialIndex);
          return { status: import_types.Status.InvalidCommand, userIndex: null, nextCredentialIndex };
        }
        if (user.credentials.length >= this.state.numberOfCredentialsSupportedPerUser) {
          auth.removeCredential(credential.credentialType, credential.credentialIndex);
          return { status: import_types.Status.ResourceExhausted, userIndex: null, nextCredentialIndex };
        }
        auth.replaceUser(userIndex, {
          ...user,
          credentials: [
            ...user.credentials,
            { credentialType: credential.credentialType, credentialIndex: credential.credentialIndex }
          ],
          lastModifiedFabricIndex: fabricIndex
        });
      }
      this.#emitLockUserChange(
        import_LockAuth.LockAuth.credentialTypeToLockDataType(credential.credentialType),
        DataOperationType.Add,
        userIndex ?? createdUserIndex,
        fabricIndex,
        credential.credentialIndex
      );
      return { status: import_types.Status.Success, userIndex: createdUserIndex, nextCredentialIndex };
    } else if (operationType === DataOperationType.Modify) {
      const existingCred = auth.findCredential(credential.credentialType, credential.credentialIndex);
      if (!existingCred) {
        return { status: import_types.Status.InvalidCommand, userIndex: null, nextCredentialIndex };
      }
      if (fabricIndex !== existingCred.creatorFabricIndex) {
        return { status: import_types.Status.InvalidCommand, userIndex: null, nextCredentialIndex };
      }
      if (userIndex !== null) {
        const user = auth.findUser(userIndex);
        if (!user) {
          return { status: import_types.Status.InvalidCommand, userIndex: null, nextCredentialIndex };
        }
        if (fabricIndex !== user.creatorFabricIndex) {
          return { status: import_types.Status.InvalidCommand, userIndex: null, nextCredentialIndex };
        }
        const hasCredential = user.credentials.some(
          (c) => c.credentialType === credential.credentialType && c.credentialIndex === credential.credentialIndex
        );
        if (!hasCredential) {
          return { status: import_types.Status.InvalidCommand, userIndex: null, nextCredentialIndex };
        }
      }
      auth.updateCredentialData(
        credential.credentialType,
        credential.credentialIndex,
        credentialData,
        fabricIndex
      );
      this.#emitLockUserChange(
        import_LockAuth.LockAuth.credentialTypeToLockDataType(credential.credentialType),
        DataOperationType.Modify,
        userIndex,
        fabricIndex,
        credential.credentialIndex
      );
      return { status: import_types.Status.Success, userIndex: null, nextCredentialIndex };
    }
    return { status: import_types.Status.InvalidCommand, userIndex: null, nextCredentialIndex: null };
  }
  getCredentialStatus(request) {
    const { credential } = request;
    const auth = this.auth;
    const cred = auth.findCredential(credential.credentialType, credential.credentialIndex);
    const nextCredentialIndex = auth.findNextOccupiedCredentialIndex(
      credential.credentialType,
      credential.credentialIndex
    );
    if (!cred) {
      return {
        credentialExists: false,
        userIndex: null,
        creatorFabricIndex: null,
        lastModifiedFabricIndex: null,
        nextCredentialIndex
      };
    }
    const userIndex = auth.findUserIndexForCredential(credential.credentialType, credential.credentialIndex);
    return {
      credentialExists: true,
      userIndex,
      creatorFabricIndex: cred.creatorFabricIndex,
      lastModifiedFabricIndex: cred.lastModifiedFabricIndex,
      nextCredentialIndex
    };
  }
  clearCredential(request) {
    const { credential } = request;
    const fabricIndex = this.#fabricIndex;
    const auth = this.auth;
    if (credential === null) {
      const typesToClear = [
        CredentialType.Pin,
        CredentialType.Rfid,
        CredentialType.Fingerprint,
        CredentialType.FingerVein,
        CredentialType.Face
      ];
      for (const type of typesToClear) {
        this.#clearAllCredentialsOfType(auth, type, fabricIndex);
      }
      return;
    }
    if (credential.credentialType === CredentialType.ProgrammingPin) {
      throw new import_types.StatusResponseError("Cannot clear ProgrammingPIN", import_types.Status.InvalidCommand);
    }
    if (credential.credentialIndex === 65534) {
      this.#clearAllCredentialsOfType(auth, credential.credentialType, fabricIndex);
      return;
    }
    const cred = auth.findCredential(credential.credentialType, credential.credentialIndex);
    if (!cred) {
      throw new import_types.StatusResponseError("Credential not found", import_types.Status.InvalidCommand);
    }
    this.#removeCredentialFromUsers(auth, credential.credentialType, credential.credentialIndex);
    auth.removeCredential(credential.credentialType, credential.credentialIndex);
    this.#emitLockUserChange(
      import_LockAuth.LockAuth.credentialTypeToLockDataType(credential.credentialType),
      DataOperationType.Clear,
      null,
      fabricIndex,
      credential.credentialIndex
    );
  }
  // ── Schedules (WDSCH, YDSCH, HDSCH) ─────────────────────────────────────
  setWeekDaySchedule(request) {
    const maxSchedules = this.state.numberOfWeekDaySchedulesSupportedPerUser;
    const { weekDayIndex, userIndex } = request;
    if (weekDayIndex < 1 || weekDayIndex > maxSchedules) {
      throw new import_types.StatusResponseError("Invalid schedule index", import_types.Status.InvalidCommand);
    }
    this.#requireValidUser(userIndex);
    if (request.endHour < request.startHour) {
      throw new import_types.StatusResponseError("End hour must be >= start hour", import_types.Status.InvalidCommand);
    }
    if (request.endHour === request.startHour && request.endMinute <= request.startMinute) {
      throw new import_types.StatusResponseError("End time must be after start time", import_types.Status.InvalidCommand);
    }
    const schedules = this.state.weekDaySchedules.filter(
      (s) => !(s.weekDayIndex === weekDayIndex && s.userIndex === userIndex)
    );
    const schedule = {
      weekDayIndex,
      userIndex,
      daysMask: request.daysMask,
      startHour: request.startHour,
      startMinute: request.startMinute,
      endHour: request.endHour,
      endMinute: request.endMinute
    };
    this.state.weekDaySchedules = [...schedules, schedule];
  }
  getWeekDaySchedule(request) {
    const maxSchedules = this.state.numberOfWeekDaySchedulesSupportedPerUser;
    const { weekDayIndex, userIndex } = request;
    if (weekDayIndex < 1 || weekDayIndex > maxSchedules || userIndex < 1 || userIndex > this.state.numberOfTotalUsersSupported) {
      const response = { weekDayIndex, userIndex, status: import_types.Status.InvalidCommand };
      (0, import_Supervision.Supervision)(response, "weekDayIndex").constraint = false;
      (0, import_Supervision.Supervision)(response, "userIndex").constraint = false;
      return response;
    }
    if (!this.auth.findUser(userIndex)) {
      return { weekDayIndex, userIndex, status: import_types.Status.NotFound };
    }
    const schedule = this.state.weekDaySchedules.find(
      (s) => s.weekDayIndex === weekDayIndex && s.userIndex === userIndex
    );
    if (!schedule) {
      return { weekDayIndex, userIndex, status: import_types.Status.NotFound };
    }
    return {
      weekDayIndex,
      userIndex,
      status: import_types.Status.Success,
      daysMask: schedule.daysMask,
      startHour: schedule.startHour,
      startMinute: schedule.startMinute,
      endHour: schedule.endHour,
      endMinute: schedule.endMinute
    };
  }
  clearWeekDaySchedule(request) {
    const { weekDayIndex, userIndex } = request;
    this.#requireValidUser(userIndex);
    if (weekDayIndex === 254) {
      this.state.weekDaySchedules = this.state.weekDaySchedules.filter((s) => s.userIndex !== userIndex);
    } else {
      const maxSchedules = this.state.numberOfWeekDaySchedulesSupportedPerUser;
      if (weekDayIndex < 1 || weekDayIndex > maxSchedules) {
        throw new import_types.StatusResponseError("Invalid schedule index", import_types.Status.InvalidCommand);
      }
      this.state.weekDaySchedules = this.state.weekDaySchedules.filter(
        (s) => !(s.weekDayIndex === weekDayIndex && s.userIndex === userIndex)
      );
    }
  }
  setYearDaySchedule(request) {
    const maxSchedules = this.state.numberOfYearDaySchedulesSupportedPerUser;
    const { yearDayIndex, userIndex } = request;
    if (yearDayIndex < 1 || yearDayIndex > maxSchedules) {
      throw new import_types.StatusResponseError("Invalid schedule index", import_types.Status.InvalidCommand);
    }
    this.#requireValidUser(userIndex);
    if (request.localEndTime <= request.localStartTime) {
      throw new import_types.StatusResponseError("End time must be after start time", import_types.Status.InvalidCommand);
    }
    const schedules = this.state.yearDaySchedules.filter(
      (s) => !(s.yearDayIndex === yearDayIndex && s.userIndex === userIndex)
    );
    const schedule = {
      yearDayIndex,
      userIndex,
      localStartTime: request.localStartTime,
      localEndTime: request.localEndTime
    };
    this.state.yearDaySchedules = [...schedules, schedule];
  }
  getYearDaySchedule(request) {
    const maxSchedules = this.state.numberOfYearDaySchedulesSupportedPerUser;
    const { yearDayIndex, userIndex } = request;
    if (yearDayIndex < 1 || yearDayIndex > maxSchedules || userIndex < 1 || userIndex > this.state.numberOfTotalUsersSupported) {
      const response = { yearDayIndex, userIndex, status: import_types.Status.InvalidCommand };
      (0, import_Supervision.Supervision)(response, "yearDayIndex").constraint = false;
      (0, import_Supervision.Supervision)(response, "userIndex").constraint = false;
      return response;
    }
    if (!this.auth.findUser(userIndex)) {
      return { yearDayIndex, userIndex, status: import_types.Status.NotFound };
    }
    const schedule = this.state.yearDaySchedules.find(
      (s) => s.yearDayIndex === yearDayIndex && s.userIndex === userIndex
    );
    if (!schedule) {
      return { yearDayIndex, userIndex, status: import_types.Status.NotFound };
    }
    return {
      yearDayIndex,
      userIndex,
      status: import_types.Status.Success,
      localStartTime: schedule.localStartTime,
      localEndTime: schedule.localEndTime
    };
  }
  clearYearDaySchedule(request) {
    const { yearDayIndex, userIndex } = request;
    this.#requireValidUser(userIndex);
    if (yearDayIndex === 254) {
      this.state.yearDaySchedules = this.state.yearDaySchedules.filter((s) => s.userIndex !== userIndex);
    } else {
      const maxSchedules = this.state.numberOfYearDaySchedulesSupportedPerUser;
      if (yearDayIndex < 1 || yearDayIndex > maxSchedules) {
        throw new import_types.StatusResponseError("Invalid schedule index", import_types.Status.InvalidCommand);
      }
      this.state.yearDaySchedules = this.state.yearDaySchedules.filter(
        (s) => !(s.yearDayIndex === yearDayIndex && s.userIndex === userIndex)
      );
    }
  }
  setHolidaySchedule(request) {
    const maxSchedules = this.state.numberOfHolidaySchedulesSupported;
    const { holidayIndex } = request;
    if (holidayIndex < 1 || holidayIndex > maxSchedules) {
      throw new import_types.StatusResponseError("Invalid schedule index", import_types.Status.InvalidCommand);
    }
    if (request.localEndTime <= request.localStartTime) {
      throw new import_types.StatusResponseError("End time must be after start time", import_types.Status.InvalidCommand);
    }
    if (request.operatingMode !== import_door_lock.DoorLock.OperatingMode.Normal && request.operatingMode !== import_door_lock.DoorLock.OperatingMode.Vacation && request.operatingMode !== import_door_lock.DoorLock.OperatingMode.Privacy && request.operatingMode !== import_door_lock.DoorLock.OperatingMode.NoRemoteLockUnlock && request.operatingMode !== import_door_lock.DoorLock.OperatingMode.Passage) {
      throw new import_types.StatusResponseError("Invalid operating mode", import_types.Status.InvalidCommand);
    }
    const schedules = this.state.holidaySchedules.filter((s) => s.holidayIndex !== holidayIndex);
    const schedule = {
      holidayIndex,
      localStartTime: request.localStartTime,
      localEndTime: request.localEndTime,
      operatingMode: request.operatingMode
    };
    this.state.holidaySchedules = [...schedules, schedule];
  }
  getHolidaySchedule(request) {
    const maxSchedules = this.state.numberOfHolidaySchedulesSupported;
    const { holidayIndex } = request;
    if (holidayIndex < 1 || holidayIndex > maxSchedules) {
      const response = { holidayIndex, status: import_types.Status.InvalidCommand };
      (0, import_Supervision.Supervision)(response, "holidayIndex").constraint = false;
      return response;
    }
    const schedule = this.state.holidaySchedules.find((s) => s.holidayIndex === holidayIndex);
    if (!schedule) {
      return { holidayIndex, status: import_types.Status.NotFound };
    }
    return {
      holidayIndex,
      status: import_types.Status.Success,
      localStartTime: schedule.localStartTime,
      localEndTime: schedule.localEndTime,
      operatingMode: schedule.operatingMode
    };
  }
  clearHolidaySchedule(request) {
    const { holidayIndex } = request;
    if (holidayIndex === 254) {
      this.state.holidaySchedules = [];
    } else {
      const maxSchedules = this.state.numberOfHolidaySchedulesSupported;
      if (holidayIndex < 1 || holidayIndex > maxSchedules) {
        throw new import_types.StatusResponseError("Invalid schedule index", import_types.Status.InvalidCommand);
      }
      this.state.holidaySchedules = this.state.holidaySchedules.filter((s) => s.holidayIndex !== holidayIndex);
    }
  }
  // ── Private Helpers ────────────────────────────────────────────────────────
  get #fabricIndex() {
    const fabric = this.context.fabric;
    if (fabric === void 0) {
      throw new import_types.StatusResponseError("Fabric required", import_types.Status.UnsupportedAccess);
    }
    return fabric;
  }
  get #sourceNode() {
    const context = this.context;
    if ("subject" in context && context.subject?.kind === "node") {
      return context.subject.id;
    }
    return null;
  }
  #stopAutoRelockTimer() {
    this.internal.autoRelockTimer?.stop();
    this.internal.autoRelockTimer = void 0;
  }
  #scheduleAutoRelock(timeoutSeconds) {
    this.#stopAutoRelockTimer();
    const timeout = timeoutSeconds ?? this.state.autoRelockTime;
    if (timeout === void 0 || timeout === 0) {
      return;
    }
    this.internal.autoRelockTimer = import_general.Time.getTimer(
      "auto-relock",
      (0, import_general.Seconds)(timeout),
      this.callback(this.#autoRelock, { lock: true })
    ).start();
  }
  #autoRelock() {
    if (this.state.lockState !== LockState.Locked) {
      this.state.lockState = LockState.Locked;
      this.events.lockOperation.emit(
        {
          lockOperationType: LockOperationType.Lock,
          operationSource: OperationSource.Auto,
          userIndex: null,
          fabricIndex: null,
          sourceNode: null,
          credentials: null
        },
        this.context
      );
    }
  }
  // ── PIN Validation ─────────────────────────────────────────────────────────
  #validatePinIfRequired(pinCode, operationType) {
    const requirePin = this.state.requirePinForRemoteOperation;
    if (pinCode !== void 0) {
      this.#validatePin(pinCode, operationType);
      return;
    }
    if (requirePin) {
      this.#emitLockOperationError(operationType, OperationError.InvalidCredential);
      throw new import_types.StatusResponseError("PIN required for remote operation", import_types.Status.Failure);
    }
  }
  #validatePin(pinCode, operationType) {
    if (this.state.wrongCodeEntryLimit !== void 0 && this.state.userCodeTemporaryDisableTime !== void 0) {
      if (this.internal.wrongCodeCount >= this.state.wrongCodeEntryLimit) {
        this.#emitLockOperationError(operationType, OperationError.InvalidCredential);
        throw new import_types.StatusResponseError("User code temporarily disabled", import_types.Status.Failure);
      }
    }
    const auth = this.auth;
    for (const cred of auth.credentials) {
      if (cred.credentialType !== CredentialType.Pin) {
        continue;
      }
      const decrypted = auth.decrypt(cred.credentialData);
      if (import_general.Bytes.areEqual(decrypted, pinCode)) {
        const userIndex = auth.findUserIndexForCredential(CredentialType.Pin, cred.credentialIndex);
        if (userIndex !== null) {
          const user = auth.findUser(userIndex);
          if (user && user.userStatus === UserStatus.OccupiedDisabled) {
            this.#emitLockOperationError(operationType, OperationError.DisabledUserDenied);
            throw new import_types.StatusResponseError("User is disabled", import_types.Status.Failure);
          }
        }
        this.internal.wrongCodeCount = 0;
        return;
      }
    }
    const wrongCount = ++this.internal.wrongCodeCount;
    if (this.state.wrongCodeEntryLimit !== void 0 && wrongCount >= this.state.wrongCodeEntryLimit) {
      this.events.doorLockAlarm.emit({ alarmCode: AlarmCode.WrongCodeEntryLimit }, this.context);
      if (this.state.userCodeTemporaryDisableTime !== void 0) {
        import_general.Time.getTimer(
          "wrong-code-disable",
          (0, import_general.Seconds)(this.state.userCodeTemporaryDisableTime),
          this.callback(
            () => {
              this.internal.wrongCodeCount = 0;
            },
            { lock: true }
          )
        ).start();
      }
    }
    this.#emitLockOperationError(operationType, OperationError.InvalidCredential);
    throw new import_types.StatusResponseError("Invalid PIN code", import_types.Status.Failure);
  }
  // ── Event Emission ─────────────────────────────────────────────────────────
  #emitLockOperation(operationType, pinCode) {
    let userIndex = null;
    let credentials = null;
    if (pinCode !== void 0) {
      const auth = this.auth;
      for (const cred of auth.credentials) {
        if (cred.credentialType !== CredentialType.Pin) continue;
        const decrypted = auth.decrypt(cred.credentialData);
        if (import_general.Bytes.areEqual(decrypted, pinCode)) {
          userIndex = auth.findUserIndexForCredential(CredentialType.Pin, cred.credentialIndex);
          credentials = [{ credentialType: CredentialType.Pin, credentialIndex: cred.credentialIndex }];
          break;
        }
      }
    }
    this.events.lockOperation.emit(
      {
        lockOperationType: operationType,
        operationSource: OperationSource.Remote,
        userIndex,
        fabricIndex: this.#fabricIndex,
        sourceNode: this.#sourceNode,
        credentials
      },
      this.context
    );
  }
  #emitLockOperationError(operationType, error) {
    this.events.lockOperationError.emit(
      {
        lockOperationType: operationType,
        operationSource: OperationSource.Remote,
        operationError: error,
        userIndex: null,
        fabricIndex: this.#fabricIndex,
        sourceNode: this.#sourceNode,
        credentials: null
      },
      this.context
    );
  }
  #emitLockUserChange(lockDataType, dataOperationType, userIndex, fabricIndex, dataIndex) {
    this.events.lockUserChange.emit(
      {
        lockDataType,
        dataOperationType,
        operationSource: OperationSource.Remote,
        userIndex,
        fabricIndex,
        sourceNode: this.#sourceNode,
        dataIndex
      },
      this.context
    );
  }
  // ── DPS ────────────────────────────────────────────────────────────────────
  #handleDoorStateChange(value) {
    if (value === null) {
      return;
    }
    this.events.doorStateChange.emit({ doorState: value }, this.context);
    if (value === DoorState.DoorOpen) {
      if (this.state.doorOpenEvents !== void 0) {
        this.state.doorOpenEvents++;
      }
    } else if (value === DoorState.DoorClosed) {
      if (this.state.doorClosedEvents !== void 0) {
        this.state.doorClosedEvents++;
      }
    }
  }
  // ── User/Credential/Schedule helpers ───────────────────────────────────────
  #requireValidUser(userIndex) {
    const maxUsers = this.state.numberOfTotalUsersSupported;
    if (userIndex < 1 || userIndex > maxUsers) {
      throw new import_types.StatusResponseError("Invalid user index", import_types.Status.InvalidCommand);
    }
    if (!this.auth.findUser(userIndex)) {
      throw new import_types.StatusResponseError("User not found", import_types.Status.Failure);
    }
  }
  #maxCredentialsForType(type) {
    switch (type) {
      case CredentialType.Pin:
      case CredentialType.ProgrammingPin:
        return this.state.numberOfPinUsersSupported;
      case CredentialType.Rfid:
        return this.state.numberOfRfidUsersSupported;
      default:
        return this.state.numberOfTotalUsersSupported;
    }
  }
  #validateCredentialDataLength(type, data) {
    switch (type) {
      case CredentialType.Pin:
      case CredentialType.ProgrammingPin: {
        const min = this.state.minPinCodeLength;
        const max = this.state.maxPinCodeLength;
        return data.byteLength >= min && data.byteLength <= max;
      }
      case CredentialType.Rfid: {
        const min = this.state.minRfidCodeLength;
        const max = this.state.maxRfidCodeLength;
        return data.byteLength >= min && data.byteLength <= max;
      }
      default:
        return true;
    }
  }
  #clearCredentialsForUser(auth, userIndex) {
    const user = auth.findUser(userIndex);
    if (!user) return;
    for (const cred of user.credentials) {
      auth.removeCredential(cred.credentialType, cred.credentialIndex);
    }
  }
  #clearAllCredentialsOfType(auth, type, fabricIndex) {
    const credsOfType = auth.credentials.filter((c) => c.credentialType === type);
    for (const cred of credsOfType) {
      this.#removeCredentialFromUsers(auth, type, cred.credentialIndex);
    }
    auth.removeAllCredentialsOfType(type);
    this.#emitLockUserChange(
      import_LockAuth.LockAuth.credentialTypeToLockDataType(type),
      DataOperationType.Clear,
      null,
      fabricIndex,
      65534
    );
  }
  #removeCredentialFromUsers(auth, type, index) {
    const userIndex = auth.findUserIndexForCredential(type, index);
    if (userIndex === null) return;
    const user = auth.findUser(userIndex);
    if (!user) return;
    auth.replaceUser(userIndex, {
      ...user,
      credentials: user.credentials.filter((c) => !(c.credentialType === type && c.credentialIndex === index))
    });
  }
  #clearSchedulesForUser(userIndex) {
    this.state.weekDaySchedules = this.state.weekDaySchedules.filter((s) => s.userIndex !== userIndex);
    this.state.yearDaySchedules = this.state.yearDaySchedules.filter((s) => s.userIndex !== userIndex);
  }
}
const throwInvalidCommand = () => {
  throw new import_types.StatusResponseError("Invalid field value", import_types.Status.InvalidCommand);
};
for (const method of [
  "setUser",
  "getUser",
  "clearUser",
  "setCredential",
  "setWeekDaySchedule",
  "clearWeekDaySchedule",
  "setYearDaySchedule",
  "clearYearDaySchedule",
  "setHolidaySchedule",
  "clearHolidaySchedule"
]) {
  (0, import_Supervision.Supervision)(DoorLockBaseServer, method).onValidationError = throwInvalidCommand;
}
for (const fieldName of ["weekDayIndex", "userIndex"]) {
  (0, import_Supervision.Supervision)(DoorLockBaseServer, "getWeekDaySchedule", fieldName).constraint = false;
}
for (const fieldName of ["yearDayIndex", "userIndex"]) {
  (0, import_Supervision.Supervision)(DoorLockBaseServer, "getYearDaySchedule", fieldName).constraint = false;
}
(0, import_Supervision.Supervision)(DoorLockBaseServer, "getHolidaySchedule", "holidayIndex").constraint = false;
((DoorLockBaseServer2) => {
  var _credentialKey_dec, _holidaySchedules_dec, _yearDaySchedules_dec, _weekDaySchedules_dec, _credentials_dec, _users_dec, _a, _init;
  class State extends (_a = DoorLockBaseServerClass.State, _users_dec = [(0, import_model.field)((0, import_model.listOf)(import_LockAuth.LockAuth.User), import_model.nonvolatile)], _credentials_dec = [(0, import_model.field)((0, import_model.listOf)(import_LockAuth.LockAuth.Credential), import_model.nonvolatile)], _weekDaySchedules_dec = [(0, import_model.field)((0, import_model.listOf)(import_LockSchedule.LockSchedule.WeekDay), import_model.nonvolatile)], _yearDaySchedules_dec = [(0, import_model.field)((0, import_model.listOf)(import_LockSchedule.LockSchedule.YearDay), import_model.nonvolatile)], _holidaySchedules_dec = [(0, import_model.field)((0, import_model.listOf)(import_LockSchedule.LockSchedule.Holiday), import_model.nonvolatile)], _credentialKey_dec = [(0, import_model.field)(import_model.octstr, import_model.nonvolatile)], _a) {
    constructor() {
      super(...arguments);
      __publicField(this, "users", __runInitializers(_init, 8, this, [])), __runInitializers(_init, 11, this);
      __publicField(this, "credentials", __runInitializers(_init, 12, this, [])), __runInitializers(_init, 15, this);
      __publicField(this, "weekDaySchedules", __runInitializers(_init, 16, this, [])), __runInitializers(_init, 19, this);
      __publicField(this, "yearDaySchedules", __runInitializers(_init, 20, this, [])), __runInitializers(_init, 23, this);
      __publicField(this, "holidaySchedules", __runInitializers(_init, 24, this, [])), __runInitializers(_init, 27, this);
      __publicField(this, "credentialKey", __runInitializers(_init, 28, this)), __runInitializers(_init, 31, this);
    }
  }
  _init = __decoratorStart(_a);
  __decorateElement(_init, 5, "users", _users_dec, State);
  __decorateElement(_init, 5, "credentials", _credentials_dec, State);
  __decorateElement(_init, 5, "weekDaySchedules", _weekDaySchedules_dec, State);
  __decorateElement(_init, 5, "yearDaySchedules", _yearDaySchedules_dec, State);
  __decorateElement(_init, 5, "holidaySchedules", _holidaySchedules_dec, State);
  __decorateElement(_init, 5, "credentialKey", _credentialKey_dec, State);
  __decoratorMetadata(_init, State);
  DoorLockBaseServer2.State = State;
  class Internal {
    wrongCodeCount = 0;
    autoRelockTimer;
  }
  DoorLockBaseServer2.Internal = Internal;
})(DoorLockBaseServer || (DoorLockBaseServer = {}));
class DoorLockServer extends DoorLockBaseServer.for(import_door_lock.DoorLock) {
}
//# sourceMappingURL=DoorLockServer.js.map
