(function () {
  "use strict";

  const webview = window.chrome && window.chrome.webview;
  const connection = document.getElementById("playout-connection-state");
  const prepare = document.getElementById("playout-prepare");
  const takeIn = document.getElementById("playout-take-in");
  const next = document.getElementById("playout-next");
  const takeOut = document.getElementById("playout-take-out");
  const backgroundNone = document.getElementById("playout-background-none");
  const backgroundFile = document.getElementById("playout-background-file");
  const backgroundName = document.getElementById("playout-background-name");
  const fadeDuration = document.getElementById("playout-fade-duration");
  const status = document.getElementById("playout-status");
  const controls = [prepare, takeIn, next, takeOut, backgroundNone,
    backgroundFile, fadeDuration];
  let currentState = null;
  let localBusy = false;

  function hasOpenDialog() {
    return Array.from(document.querySelectorAll("[role='dialog'], [role='alertdialog']"))
      .some(function (dialog) {
        const container = dialog.closest("[hidden]");
        return !container && !dialog.hidden;
      });
  }

  function post(type, payload) {
    if (!webview || localBusy || hasOpenDialog()) return;
    localBusy = true;
    render(currentState);
    webview.postMessage({ type: type, payload: payload || {} });
  }

  function setAllDisabled(disabled) {
    controls.forEach(function (control) {
      if (control) control.disabled = disabled;
    });
  }

  function phaseLabel(phase) {
    if (phase === "prepared") return "PREPARED";
    if (phase === "program") return "PROGRAM";
    return "IDLE";
  }

  function connectionLabel(playout) {
    if (!playout) return "미연결";
    if (playout.outcomeUnknown) return "결과 불명확";
    if (playout.mode === "disabled") return "송출 비활성";
    if (playout.mode === "dryRun") return "DRY RUN";
    if (playout.isConnected) return "Tornado2 연결됨";
    if (playout.isProcessRunning) return "Tornado2 감지됨";
    return "미연결";
  }

  function pageLabel(playout) {
    if (!playout || playout.pageCount <= 0) return "";
    return " · Page " + String(playout.pageIndexZeroBased + 1) +
      "/" + String(playout.pageCount);
  }

  function nextLabel(playout) {
    if (!playout || playout.nextKind === "none") return "";
    if (playout.nextKind === "endOfPlaylist") return " · 마지막 항목";
    return playout.nextKind === "pageNext" ? " · 다음 페이지" : " · 다음 항목";
  }

  function canTakeInFromState(playout, hasPlaylist) {
    return playout.phase === "prepared" ||
      hasPlaylist && (playout.phase === "idle" || playout.phase === "program");
  }

  function canAdvanceFromState(playout) {
    return playout.phase === "program" &&
      playout.nextKind !== "none" && playout.nextKind !== "endOfPlaylist";
  }

  function statusState(playout, busy) {
    if (!playout) return "error";
    if (playout.outcomeUnknown === true ||
        playout.connectionState === "outcomeUnknown") {
      return "outcome-unknown";
    }
    if (busy) return "busy";
    if (playout.mode === "disabled" ||
        playout.connectionState === "faulted" ||
        playout.connectionState === "disposed") {
      return "error";
    }
    if (playout.phase === "program") return "program";
    if (playout.phase === "prepared") return "prepared";
    return "idle";
  }

  function render(state) {
    currentState = state || currentState;
    const playout = currentState && currentState.playout;
    const nativeBusy = !!(currentState && currentState.isBusy) ||
      !!(playout && playout.isBusy);
    const busy = localBusy || nativeBusy;
    status.dataset.state = statusState(playout, busy);
    if (!playout) {
      connection.textContent = "미연결";
      status.textContent = "송출 엔진 상태를 사용할 수 없습니다.";
      status.title = status.textContent;
      setAllDisabled(true);
      return;
    }

    const commandAvailable = playout.isCommandAvailable === true &&
      playout.outcomeUnknown !== true &&
      playout.isTakeOutCompletionPending !== true;
    const hasPlaylist = Array.isArray(currentState.playlist) &&
      currentState.playlist.some(function (row) { return row.isEnabled === true; });
    const liveTakeInAllowed = playout.mode !== "live" ||
      playout.liveTakeInAllowed === true;
    const canPrepareToggle = playout.phase === "idle" ? hasPlaylist :
      playout.phase === "prepared" || playout.phase === "program";

    const nextConnectionText = connectionLabel(playout);
    if (connection.textContent !== nextConnectionText) {
      connection.textContent = nextConnectionText;
    }
    connection.classList.toggle("connected", playout.isConnected === true);
    connection.classList.toggle("outcome-unknown", playout.outcomeUnknown === true);
    connection.classList.toggle("dry-run", playout.mode === "dryRun");
    prepare.classList.toggle("active", playout.phase !== "idle");
    prepare.disabled = busy || !commandAvailable || !canPrepareToggle ||
      playout.isPlayCompletionPending === true;
    const canTakeIn = canTakeInFromState(playout, hasPlaylist);
    takeIn.disabled = busy || !commandAvailable || !liveTakeInAllowed ||
      !canTakeIn || playout.isPlayCompletionPending === true;
    next.disabled = busy || !commandAvailable ||
      !canAdvanceFromState(playout) ||
      playout.isPlayCompletionPending === true;
    // MainForm's Escape path called StopAll whenever the Tornado player existed,
    // even if its local m_TakeIn flag had already drifted back to IDLE.
    takeOut.disabled = busy || !commandAvailable;
    backgroundNone.disabled = busy || playout.canChangeBackground !== true;
    backgroundFile.disabled = busy || playout.canChangeBackground !== true;
    // MainForm.Designer keeps panel3 (which owns ComboDi) invisible. Preserve
    // the native fade value as read-only state, but never expose an operator
    // interaction path from the WebView shell.
    fadeDuration.disabled = true;
    backgroundNone.checked = playout.backgroundEnabled !== true;
    backgroundName.value = playout.backgroundEnabled === true
      ? (playout.backgroundFileName || "선택한 배경") : "배경없음";
    fadeDuration.value = String(playout.fadeDuration);

    const scene = playout.onAirCode || playout.preparedCode;
    const sceneLabel = scene ? " · " + scene : "";
    const refresh = playout.refreshActive
      ? " · 자동 갱신 " + String(playout.refreshCompletedCount) + "회" : "";
    status.textContent = phaseLabel(playout.phase) + sceneLabel +
      pageLabel(playout) + nextLabel(playout) + refresh +
      (playout.message ? " · " + playout.message : "");
    status.title = status.textContent;
  }

  prepare.addEventListener("click", function () {
    post("prepare-playout", {});
  });
  takeIn.addEventListener("click", function () {
    post("take-in", {});
  });
  next.addEventListener("click", function () {
    post("next-playout", {});
  });
  takeOut.addEventListener("click", function () {
    post("take-out", {});
  });
  backgroundFile.addEventListener("click", function () {
    post("choose-background", {});
  });
  backgroundNone.addEventListener("change", function () {
    post("toggle-background", {});
  });
  document.addEventListener("keydown", function (event) {
    if (event.defaultPrevented) return;
    const legacyShortcut = event.key === "F2" || event.key === "F3" ||
      event.key === "F8" || event.key === "Escape";
    if (hasOpenDialog()) {
      // ShowDialog/MessageBox own these keys. Consume browser defaults (notably
      // Chromium's F3 Find Next) without invoking a MainForm playout shortcut.
      if (legacyShortcut) event.preventDefault();
      return;
    }
    if (event.repeat) return;
    if (event.key === "F2") {
      event.preventDefault();
      if (!backgroundFile.disabled) backgroundFile.click();
    } else if (event.key === "F3") {
      event.preventDefault();
      if (!backgroundNone.disabled) backgroundNone.click();
    } else if (event.key === "F8") {
      event.preventDefault();
      if (!takeIn.disabled) takeIn.click();
    } else if (event.key === "Escape") {
      event.preventDefault();
      if (!takeOut.disabled) takeOut.click();
    }
  });

  if (webview) {
    webview.addEventListener("message", function (event) {
      if (event.data && event.data.type === "state" && event.data.payload) {
        localBusy = false;
        render(event.data.payload);
      }
    });
  } else {
    setAllDisabled(true);
    status.dataset.state = "error";
    status.textContent = "WebView2 송출 브리지를 사용할 수 없습니다.";
    status.title = status.textContent;
  }
}());
