/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { createServer } from "node:http";
import { Parser } from "xml2js";
class AccessoryMethodError extends Error {
  constructor(message, status = 400) {
    super(message);
    this.status = status;
  }
  status;
}
class AccessoryServer {
  #server;
  #isClosed = false;
  #subject;
  constructor(subject, onReady) {
    this.#subject = subject;
    this.#server = createServer(this.#handleRequest.bind(this));
    this.#server.listen(0, "127.0.0.1", onReady);
  }
  static create(subject) {
    return new Promise((resolve) => {
      const server = new AccessoryServer(subject, () => resolve(server));
    });
  }
  get port() {
    const port = this.#server.address()?.port;
    if (typeof port !== "number") {
      throw new Error("Accessory server has no assigned port");
    }
    return port;
  }
  async close() {
    if (!this.#isClosed) {
      this.#isClosed = true;
      await new Promise(
        (resolve) => this.#server.close((error) => {
          if (error) {
            console.warn("Error closing accessory server", error);
          }
          resolve();
        })
      );
    }
  }
  #handleRequest(request, response) {
    request.on("error", (error) => {
      console.warn("Accessory server request error", error);
    });
    response.on("error", (error) => {
      console.warn("Accessory server response error", error);
    });
    const parser = new Parser();
    request.on("data", (chunk) => {
      parser.parseString(chunk, (error, result) => {
        if (error) {
          response.writeHead(400);
          response.end();
          return;
        }
        if (result !== void 0) {
          this.#invoke(result).then(
            () => {
              response.writeHead(200);
              response.end(
                `<?xml version="1.0"?>
<methodResponse><params><param><value><boolean>1</boolean></value></param></params></methodResponse>`
              );
            },
            (error2) => {
              const status = error2 instanceof AccessoryMethodError ? error2.status : 500;
              console.warn(`Accessory invocation error (HTTP ${status}):`, error2);
              response.writeHead(status);
              response.end();
            }
          );
        }
      });
    });
  }
  async #invoke(request) {
    const methodName = request?.methodCall?.methodName?.[0];
    if (typeof methodName !== "string") {
      throw new AccessoryMethodError("Missing or invalid accessory method name");
    }
    switch (methodName) {
      case "reboot":
      case "factoryReset":
      case "start":
      case "stop":
        await this.#subject.backchannel({ name: methodName });
        return;
      case "waitForMessage":
      case "createOtaImage":
      case "compareFiles":
      case "createFile":
      case "deleteFile":
        throw new AccessoryMethodError(`Unimplemented accessory method ${methodName}`, 404);
    }
    throw new AccessoryMethodError(`Unsupported accessory method ${methodName}`, 404);
  }
}
export {
  AccessoryMethodError,
  AccessoryServer
};
//# sourceMappingURL=accessory-server.js.map
