////
// Our tiny browser, only for NOSE apps.
// Check /public/browser-nav.js for the 2nd part.

import { $, $$ } from "./dom"
import { focusInput } from "./focus"

const controls = $("browser-controls") as HTMLDivElement
const address = $("browser-address") as HTMLSpanElement
let iframe: HTMLIFrameElement
let iframeWindow: Window

export function isBrowsing(): boolean {
  return document.querySelector("iframe.browser.active") !== null
}

export function openBrowser(url: string) {
  iframe = $$("iframe.browser.active") as HTMLIFrameElement
  iframeWindow = iframe.contentWindow as Window
  iframe.src = url
  iframe.sandbox.add("allow-scripts", "allow-same-origin", "allow-forms")
  iframe.height = "540"
  iframe.width = "960"
  iframe.tabIndex = 0

  window.addEventListener("message", handleAppMessage)
  window.addEventListener("keydown", handleBrowserKeydown)
  controls.addEventListener("click", handleClick)
  iframe.addEventListener("load", handlePageLoad)

  controls.style.display = ""
  const main = document.querySelector("#content")
  main?.prepend(iframe)

  setAddress(url)
}

function handleAppMessage(event: MessageEvent) {
  const origin = event.origin
  if (!origin.includes('localhost') && !origin.match(/\.local$/)) {
    return
  }

  const { type, data } = event.data

  switch (type) {
    case 'NAV_READY':
      break

    case 'URL_CHANGED':
      setAddress(data.url)
      break

    case 'TITLE_CHANGED':
      // TODO: browser titles
      console.log('Page title:', data.title)
      break

    case 'NAV_BLOCKED':
      showNavigationError(data.url, data.reason)
      break
  }
}

function closeBrowser() {
  iframe.remove()
  controls.style.display = "none"
  window.removeEventListener("keydown", handleBrowserKeydown)
  window.removeEventListener("message", handleAppMessage)
  controls.removeEventListener("click", handleClick)
  iframe.removeEventListener("load", handlePageLoad)
  focusInput()
}

function handleBrowserKeydown(e: KeyboardEvent) {
  if (e.key === "Escape" || (e.ctrlKey && e.key === "c")) {
    e.preventDefault()
    closeBrowser()
  }
}

function handleClick(e: MouseEvent) {
  const target = e.target
  if (!(target instanceof HTMLElement)) return

  switch (target.id) {
    case "back-button":
      navigateBack(); break
    case "forward-button":
      navigateForward(); break
    case "stop-button":
      stopLoading(); break
    case "reload-button":
      reloadBrowser(); break
    case "close-button":
      closeBrowser(); break
    default:
      return
  }

  e.preventDefault()
}

function handlePageLoad() {
}

function setAddress(url: string) {
  address.textContent = url.replace(/https?:\/\//, "")
}

function navigateBack() {
  sendNavCommand('back')
}

function navigateForward() {
  sendNavCommand('forward')
}

function reloadBrowser() {
  sendNavCommand('reload')
}

function stopLoading() {
  sendNavCommand('stop')
}

function sendNavCommand(action: 'back' | 'forward' | 'reload' | 'stop') {
  if (!iframe.contentWindow) return

  iframe.contentWindow.postMessage({
    type: 'NAV_COMMAND',
    action
  }, '*')
}

function showNavigationError(url: string, reason: string) {
  alert(`NAVIGATION BLOCKED\n\n${url}\n\n${reason}`)
}