"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var SoundsSelector_exports = {};
__export(SoundsSelector_exports, {
  default: () => SoundsSelector_default
});
module.exports = __toCommonJS(SoundsSelector_exports);
var import_jsx_runtime = require("react/jsx-runtime");
var import_react = require("react");
var import_ink = require("ink");
var import_node_url = require("node:url");
var import_node_fs = require("node:fs");
var import_node_path = __toESM(require("node:path"), 1);
var import_BaseSelector = require("../base/BaseSelector.js");
var import_soundNotification = require("../../utils/soundNotification.js");
var import_contexts = require("../../contexts/index.js");
var import_agent_management = require("@dexto/agent-management");
const import_meta = {};
const BUILTIN_SOUNDS = [
  {
    id: "coin",
    name: "Coin",
    filename: "coin.wav"
  },
  {
    id: "confirm",
    name: "Confirm",
    filename: "confirm.wav"
  },
  {
    id: "ping",
    name: "Ping",
    filename: "ping.wav"
  },
  {
    id: "powerup",
    name: "Power Up",
    filename: "powerup.wav"
  },
  {
    id: "chime",
    name: "Chime",
    filename: "chime.wav"
  },
  {
    id: "levelup",
    name: "Level Up",
    filename: "levelup.wav"
  },
  {
    id: "boot",
    name: "Boot",
    filename: "boot.wav"
  },
  {
    id: "startup",
    name: "Startup",
    filename: "startup.wav"
  },
  {
    id: "success",
    name: "Success",
    filename: "success.wav"
  },
  {
    id: "win",
    name: "Win",
    filename: "win.wav"
  },
  {
    id: "treasure",
    name: "Treasure Chest",
    filename: "treasure.wav"
  }
];
const DEFAULT_CONFIG = {
  enabled: true,
  onStartup: false,
  onApprovalRequired: true,
  onTaskComplete: true
};
function getSoundEnabledKey(soundType) {
  switch (soundType) {
    case "startup":
      return "onStartup";
    case "approval":
      return "onApprovalRequired";
    case "complete":
      return "onTaskComplete";
  }
}
function getSoundFileKey(soundType) {
  switch (soundType) {
    case "startup":
      return "startupSoundFile";
    case "approval":
      return "approvalSoundFile";
    case "complete":
      return "completeSoundFile";
  }
}
function selectionLabel(soundType, selection) {
  if (selection.kind === "system") return soundType === "startup" ? "Startup" : "System";
  const normalizedRelative = selection.relativePath.replaceAll("\\", "/");
  const builtinFilename = normalizedRelative.startsWith("builtins/") ? normalizedRelative.slice("builtins/".length) : null;
  if (builtinFilename) {
    const builtin = BUILTIN_SOUNDS.find((s) => s.filename === builtinFilename);
    if (builtin) return builtin.name;
  }
  return normalizedRelative.replace(/\.[^/.]+$/, "");
}
function getAllowedCustomSoundExtensions() {
  switch (process.platform) {
    case "win32":
      return /* @__PURE__ */ new Set([".wav"]);
    case "linux":
      return /* @__PURE__ */ new Set([".wav", ".ogg", ".oga"]);
    default:
      return new Set(import_soundNotification.CUSTOM_SOUND_EXTENSIONS);
  }
}
async function listCustomSoundFiles(soundsDir) {
  const allowedExtensions = getAllowedCustomSoundExtensions();
  const results = [];
  const walk = async (dir) => {
    let entries;
    try {
      entries = await import_node_fs.promises.readdir(dir, { withFileTypes: true });
    } catch (error) {
      if (error.code === "ENOENT") return;
      throw error;
    }
    for (const entry of entries) {
      if (entry.name.startsWith(".")) continue;
      const absPath = import_node_path.default.join(dir, entry.name);
      if (entry.isDirectory()) {
        if (dir === soundsDir && entry.name === "builtins") continue;
        await walk(absPath);
        continue;
      }
      if (!entry.isFile()) continue;
      const ext = import_node_path.default.extname(entry.name).toLowerCase();
      if (!allowedExtensions.has(ext)) continue;
      const relative = import_node_path.default.relative(soundsDir, absPath);
      if (relative.startsWith("..") || import_node_path.default.isAbsolute(relative)) continue;
      results.push(relative.split(import_node_path.default.sep).join("/"));
    }
  };
  await walk(soundsDir);
  return results.sort((a, b) => a.localeCompare(b));
}
function formatCustomSoundLabel(relativePath) {
  return relativePath.replaceAll("\\", "/").replace(/\.[^/.]+$/, "");
}
function resolveSelection(soundType, config) {
  const configuredRelativePath = config[getSoundFileKey(soundType)];
  if (configuredRelativePath) {
    return { kind: "file", relativePath: configuredRelativePath };
  }
  return { kind: "system" };
}
const SoundsSelector = (0, import_react.forwardRef)(
  function SoundsSelector2({ isVisible, onClose }, ref) {
    const soundService = (0, import_contexts.useSoundService)();
    const baseSelectorRef = (0, import_react.useRef)(null);
    const [viewMode, setViewMode] = (0, import_react.useState)("main");
    const [selectedIndex, setSelectedIndex] = (0, import_react.useState)(0);
    const [pickAction, setPickAction] = (0, import_react.useState)("listen");
    const [isLoading, setIsLoading] = (0, import_react.useState)(false);
    const [isApplying, setIsApplying] = (0, import_react.useState)(false);
    const [error, setError] = (0, import_react.useState)(null);
    const [canPersistPreferences, setCanPersistPreferences] = (0, import_react.useState)(false);
    const [config, setConfig] = (0, import_react.useState)(DEFAULT_CONFIG);
    const [customSoundFiles, setCustomSoundFiles] = (0, import_react.useState)([]);
    const [approvalSelection, setApprovalSelection] = (0, import_react.useState)({
      kind: "system"
    });
    const [completeSelection, setCompleteSelection] = (0, import_react.useState)({
      kind: "system"
    });
    const [startupSelection, setStartupSelection] = (0, import_react.useState)({
      kind: "system"
    });
    const configRef = (0, import_react.useRef)(config);
    configRef.current = config;
    const closeOrBack = (0, import_react.useCallback)(() => {
      if (viewMode === "main") {
        onClose();
        return;
      }
      setViewMode("main");
      setSelectedIndex(0);
      setError(null);
    }, [onClose, viewMode]);
    (0, import_react.useImperativeHandle)(
      ref,
      () => ({
        handleInput: (input, key) => {
          if (!isVisible) return false;
          if (viewMode !== "main") {
            if (key.leftArrow) {
              setPickAction("listen");
              return true;
            }
            if (key.rightArrow) {
              setPickAction("select");
              return true;
            }
          }
          return baseSelectorRef.current?.handleInput(input, key) ?? false;
        }
      }),
      [isVisible, viewMode]
    );
    const builtinSoundPaths = (0, import_react.useMemo)(() => {
      return BUILTIN_SOUNDS.map((sound) => ({
        ...sound,
        absPath: (0, import_node_url.fileURLToPath)(
          new URL(`../../../assets/sounds/${sound.filename}`, import_meta.url)
        )
      }));
    }, []);
    const refreshSelections = (0, import_react.useCallback)((nextConfig) => {
      setStartupSelection(resolveSelection("startup", nextConfig));
      setApprovalSelection(resolveSelection("approval", nextConfig));
      setCompleteSelection(resolveSelection("complete", nextConfig));
    }, []);
    (0, import_react.useEffect)(() => {
      if (!isVisible) return;
      let cancelled = false;
      setIsLoading(true);
      setIsApplying(false);
      setError(null);
      setViewMode("main");
      setSelectedIndex(0);
      const run = async () => {
        const prefsExist = (0, import_agent_management.globalPreferencesExist)();
        setCanPersistPreferences(prefsExist);
        let nextConfig = DEFAULT_CONFIG;
        if (prefsExist) {
          try {
            const preferences = await (0, import_agent_management.loadGlobalPreferences)();
            nextConfig = {
              enabled: preferences.sounds?.enabled ?? nextConfig.enabled,
              onStartup: preferences.sounds?.onStartup ?? nextConfig.onStartup,
              startupSoundFile: preferences.sounds?.startupSoundFile,
              onApprovalRequired: preferences.sounds?.onApprovalRequired ?? nextConfig.onApprovalRequired,
              approvalSoundFile: preferences.sounds?.approvalSoundFile,
              onTaskComplete: preferences.sounds?.onTaskComplete ?? nextConfig.onTaskComplete,
              completeSoundFile: preferences.sounds?.completeSoundFile
            };
          } catch (err) {
            setCanPersistPreferences(false);
            if (!cancelled) {
              setError(
                `Failed to load preferences: ${err instanceof Error ? err.message : String(err)}`
              );
            }
          }
        }
        if (!cancelled) {
          setConfig(nextConfig);
          soundService?.setConfig(nextConfig);
          refreshSelections(nextConfig);
        }
        const soundsDir = (0, import_agent_management.getDextoGlobalPath)("sounds");
        try {
          const files = await listCustomSoundFiles(soundsDir);
          if (!cancelled) setCustomSoundFiles(files);
        } catch (err) {
          if (!cancelled) {
            setCustomSoundFiles([]);
            setError(
              `Failed to load custom sounds: ${err instanceof Error ? err.message : String(err)}`
            );
          }
        }
      };
      void run().catch((err) => {
        if (!cancelled) {
          setError(err instanceof Error ? err.message : String(err));
        }
      }).finally(() => {
        if (!cancelled) setIsLoading(false);
      });
      return () => {
        cancelled = true;
      };
    }, [isVisible, refreshSelections, soundService]);
    const mainItems = (0, import_react.useMemo)(
      () => [
        { type: "enabled", id: "enabled" },
        {
          type: "pick",
          id: "pick-startup",
          soundType: "startup",
          label: "startup sound"
        },
        {
          type: "pick",
          id: "pick-approval",
          soundType: "approval",
          label: "approval sound"
        },
        {
          type: "pick",
          id: "pick-complete",
          soundType: "complete",
          label: "completion sound"
        }
      ],
      []
    );
    const pickSoundType = viewMode === "pick-startup" ? "startup" : viewMode === "pick-approval" ? "approval" : viewMode === "pick-complete" ? "complete" : null;
    const pickItems = (0, import_react.useMemo)(() => {
      if (!pickSoundType) return [];
      const current = pickSoundType === "startup" ? startupSelection : pickSoundType === "approval" ? approvalSelection : completeSelection;
      const enabledKey = getSoundEnabledKey(pickSoundType);
      const isEnabled = config[enabledKey];
      const normalizedRelative = current.kind === "file" ? current.relativePath.replaceAll("\\", "/") : null;
      const items2 = [
        {
          type: "off",
          id: "off",
          label: "Off",
          isCurrent: !isEnabled
        },
        {
          type: "default",
          id: "default",
          label: "Default",
          isCurrent: isEnabled && current.kind === "system"
        },
        ...builtinSoundPaths.map((sound) => ({
          type: "builtin",
          id: sound.id,
          label: sound.name,
          isCurrent: isEnabled && normalizedRelative === import_node_path.default.posix.join("builtins", sound.filename)
        })),
        ...customSoundFiles.map((relativePath) => ({
          type: "file",
          id: relativePath,
          relativePath,
          label: formatCustomSoundLabel(relativePath),
          isCurrent: isEnabled && normalizedRelative === relativePath.replaceAll("\\", "/")
        }))
      ];
      return items2;
    }, [
      approvalSelection,
      builtinSoundPaths,
      customSoundFiles,
      completeSelection,
      config,
      pickSoundType,
      startupSelection
    ]);
    const items = viewMode === "main" ? mainItems : pickItems;
    const applyConfigUpdate = (0, import_react.useCallback)(
      async (partial) => {
        const previousConfig = configRef.current;
        const nextConfig = { ...previousConfig, ...partial };
        setConfig(nextConfig);
        soundService?.setConfig(partial);
        refreshSelections(nextConfig);
        if (!canPersistPreferences) {
          return;
        }
        try {
          await (0, import_agent_management.updateGlobalPreferences)({ sounds: partial });
        } catch (err) {
          setConfig(previousConfig);
          soundService?.setConfig(previousConfig);
          refreshSelections(previousConfig);
          setError(err instanceof Error ? err.message : String(err));
        }
      },
      [canPersistPreferences, refreshSelections, soundService]
    );
    const ensureBuiltinSoundFile = (0, import_react.useCallback)(
      async (soundId) => {
        const soundsDir = (0, import_agent_management.getDextoGlobalPath)("sounds");
        const builtinsDir = import_node_path.default.join(soundsDir, "builtins");
        await import_node_fs.promises.mkdir(builtinsDir, { recursive: true });
        const builtin = builtinSoundPaths.find((s) => s.id === soundId);
        if (!builtin) {
          throw new Error(`Unknown built-in sound: ${soundId}`);
        }
        const destPath = import_node_path.default.join(builtinsDir, builtin.filename);
        await import_node_fs.promises.copyFile(builtin.absPath, destPath);
        return import_node_path.default.posix.join("builtins", builtin.filename);
      },
      [builtinSoundPaths]
    );
    const previewPickItem = (0, import_react.useCallback)(
      (item) => {
        if (!pickSoundType) return;
        if (item.type === "off") {
          return;
        }
        if (item.type === "default") {
          const spec = (0, import_soundNotification.getDefaultSoundSpec)(pickSoundType);
          if (spec) (0, import_soundNotification.playSoundFile)(spec);
          return;
        }
        if (item.type === "builtin") {
          const builtin = builtinSoundPaths.find((s) => s.id === item.id);
          if (builtin) {
            (0, import_soundNotification.playSoundFile)(builtin.absPath);
          }
          return;
        }
        if (item.type === "file") {
          const soundsDir = import_node_path.default.normalize((0, import_agent_management.getDextoGlobalPath)("sounds"));
          const resolved = import_node_path.default.normalize(import_node_path.default.resolve(soundsDir, item.relativePath));
          if (resolved === soundsDir || resolved.startsWith(soundsDir + import_node_path.default.sep)) {
            (0, import_soundNotification.playSoundFile)(resolved);
          }
        }
      },
      [builtinSoundPaths, pickSoundType]
    );
    const handleSelect = (0, import_react.useCallback)(
      async (item) => {
        if (isApplying || isLoading) return;
        setIsApplying(true);
        setError(null);
        try {
          if (item.type === "enabled") {
            await applyConfigUpdate({ enabled: !configRef.current.enabled });
            return;
          }
          if (item.type === "pick") {
            setPickAction("listen");
            setViewMode(item.id);
            setSelectedIndex(0);
            return;
          }
          if (item.type === "off" || item.type === "default" || item.type === "builtin" || item.type === "file") {
            if (!pickSoundType) return;
            const enabledKey = getSoundEnabledKey(pickSoundType);
            const fileKey = getSoundFileKey(pickSoundType);
            if (pickAction === "listen") {
              previewPickItem(item);
              return;
            }
            if (item.type === "off") {
              await applyConfigUpdate({ [enabledKey]: false });
              setViewMode("main");
              setSelectedIndex(0);
              return;
            }
            if (item.type === "default") {
              const partial = {
                [enabledKey]: true,
                [fileKey]: void 0
              };
              await applyConfigUpdate(partial);
              (0, import_soundNotification.playNotificationSound)(pickSoundType, {
                ...configRef.current,
                ...partial
              });
            } else if (item.type === "builtin") {
              const relativePath = await ensureBuiltinSoundFile(item.id);
              const partial = {
                [enabledKey]: true,
                [fileKey]: relativePath
              };
              await applyConfigUpdate(partial);
              (0, import_soundNotification.playNotificationSound)(pickSoundType, {
                ...configRef.current,
                ...partial
              });
            } else {
              const partial = {
                [enabledKey]: true,
                [fileKey]: item.relativePath
              };
              await applyConfigUpdate(partial);
              (0, import_soundNotification.playNotificationSound)(pickSoundType, {
                ...configRef.current,
                ...partial
              });
            }
            setViewMode("main");
            setSelectedIndex(0);
            return;
          }
        } catch (err) {
          setError(err instanceof Error ? err.message : String(err));
        } finally {
          setIsApplying(false);
        }
      },
      [
        applyConfigUpdate,
        isApplying,
        isLoading,
        pickAction,
        pickSoundType,
        previewPickItem,
        ensureBuiltinSoundFile
      ]
    );
    const formatItem = (0, import_react.useCallback)(
      (item, isSelected) => {
        if (item.type === "enabled") {
          return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { wrap: "truncate-end", children: [
            /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: isSelected ? "cyan" : "gray", bold: isSelected, children: [
              "sounds:",
              " "
            ] }),
            /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: config.enabled ? "green" : "gray", bold: isSelected, children: config.enabled ? "On" : "Off" })
          ] });
        }
        if (item.type === "pick") {
          const enabled = item.soundType === "startup" ? config.onStartup : item.soundType === "approval" ? config.onApprovalRequired : config.onTaskComplete;
          const selection = item.soundType === "startup" ? startupSelection : item.soundType === "approval" ? approvalSelection : completeSelection;
          const currentLabel = enabled ? selectionLabel(item.soundType, selection) : "Off";
          return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
            import_ink.Text,
            {
              color: isSelected ? "cyan" : "gray",
              bold: isSelected,
              wrap: "truncate-end",
              children: [
                item.label,
                ": ",
                currentLabel
              ]
            }
          );
        }
        if (item.type === "off" || item.type === "default" || item.type === "builtin" || item.type === "file") {
          return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "row", children: [
            /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexGrow: 1, flexDirection: "row", children: [
              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "green", children: item.isCurrent ? "* " : "  " }),
              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
                import_ink.Text,
                {
                  color: isSelected ? "cyan" : "gray",
                  bold: isSelected,
                  wrap: "truncate-end",
                  children: item.label
                }
              )
            ] }),
            isSelected && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "row", marginLeft: 1, children: [
              /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
                import_ink.Text,
                {
                  inverse: pickAction === "listen",
                  bold: pickAction === "listen",
                  children: [
                    " ",
                    "Listen",
                    " "
                  ]
                }
              ),
              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { children: " " }),
              /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
                import_ink.Text,
                {
                  inverse: pickAction === "select",
                  bold: pickAction === "select",
                  children: [
                    " ",
                    "Select",
                    " "
                  ]
                }
              )
            ] })
          ] });
        }
        return null;
      },
      [approvalSelection, completeSelection, config, pickAction, startupSelection]
    );
    const title = viewMode === "main" ? "Sounds" : pickSoundType === "startup" ? "Select Startup Sound" : pickSoundType === "approval" ? "Select Approval Sound" : "Select Completion Sound";
    return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", children: [
      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
        import_BaseSelector.BaseSelector,
        {
          ref: baseSelectorRef,
          items,
          isVisible,
          isLoading,
          loadingMessage: "Loading sound settings...",
          selectedIndex,
          onSelectIndex: setSelectedIndex,
          onSelect: (item) => void handleSelect(item),
          onClose: closeOrBack,
          formatItem,
          title,
          instructionsOverride: viewMode === "main" ? "\u2191\u2193 navigate \u2022 Enter toggle/select \u2022 Esc close" : `\u2191\u2193 navigate \u2022 \u2190/\u2192 Listen/Select \u2022 Enter ${pickAction === "listen" ? "preview" : "select"} \u2022 Esc back`,
          borderColor: "magenta",
          emptyMessage: "No options available"
        }
      ),
      error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "red", wrap: "wrap", children: error }) })
    ] });
  }
);
var SoundsSelector_default = SoundsSelector;
