--[[
  ExportDialog.lua
  WebP Exporter (cwebp) – v1.2.1
  UI panel shown in Lightroom's Export dialog.
  Separated from service provider for clarity and maintainability.

  v1.2.1: removed f:system_color() calls for compatibility
          with all Lightroom SDK versions.
--]]

local LrView      = import 'LrView'
local LrDialogs   = import 'LrDialogs'
local LrTasks     = import 'LrTasks'
local LrPathUtils = import 'LrPathUtils'
local LrFileUtils = import 'LrFileUtils'

local PLUGIN_VERSION = "1.2.2"

local function isWin() return WIN_ENV end

local function trim(s)
  if not s then return "" end
  return (s:gsub("^%s+", ""):gsub("%s+$", ""))
end

local function normalizeExePath(p)
  if not p then return "" end
  p = trim(p)
  if (#p >= 2) and (
    (p:sub(1,1) == '"' and p:sub(-1) == '"') or
    (p:sub(1,1) == "'" and p:sub(-1) == "'")
  ) then
    p = p:sub(2, -2)
    p = trim(p)
  end
  return p
end

local function quotePosix(s)
  if s == nil then return "''" end
  return "'" .. string.gsub(s, "'", "'\"'\"'") .. "'"
end

local function fileExists(path)
  return path and path ~= '' and LrFileUtils.exists(path)
end

local function validateExe(exePath)
  exePath = normalizeExePath(exePath)
  if exePath == "" then return false end
  local cmd
  if isWin() then
    cmd = 'cmd.exe /c "' .. exePath .. '" -version > NUL 2>&1'
  else
    cmd = quotePosix(exePath) .. ' -version > /dev/null 2>&1'
  end
  local rc = LrTasks.execute(cmd)
  return rc == 0
end

local function macArch()
  local handle = io.popen("uname -m 2>/dev/null")
  if not handle then return "x86_64" end
  local result = trim(handle:read("*l") or "")
  handle:close()
  if result == "arm64" then return "arm64" end
  return "x86_64"
end

local function resolveCwebp(settings)
  local candidates = {}

  if settings.cwebpPath and settings.cwebpPath ~= "" then
    table.insert(candidates, { path = normalizeExePath(settings.cwebpPath), source = "user setting" })
  end

  local binDir = LrPathUtils.child(_PLUGIN.path, "bin")
  if isWin() then
    table.insert(candidates, { path = LrPathUtils.child(LrPathUtils.child(binDir, "win"), "cwebp.exe"), source = "plugin bundle (win)" })
    table.insert(candidates, { path = LrPathUtils.child(binDir, "cwebp.exe"),                          source = "plugin bundle root" })
    table.insert(candidates, { path = "C:\\Program Files\\WebP\\bin\\cwebp.exe",                       source = "Program Files" })
    table.insert(candidates, { path = "C:\\Program Files (x86)\\WebP\\bin\\cwebp.exe",                 source = "Program Files (x86)" })
  else
    local arch      = macArch()
    local macBinDir = LrPathUtils.child(binDir, "mac")
    local archDir   = LrPathUtils.child(macBinDir, arch)
    local otherDir  = LrPathUtils.child(macBinDir, arch == "arm64" and "x86_64" or "arm64")

    table.insert(candidates, { path = LrPathUtils.child(archDir,   "cwebp"), source = "plugin bundle mac/" .. arch })
    table.insert(candidates, { path = LrPathUtils.child(otherDir,  "cwebp"), source = "plugin bundle mac/" .. (arch == "arm64" and "x86_64" or "arm64") .. " (Rosetta)" })
    table.insert(candidates, { path = LrPathUtils.child(macBinDir, "cwebp"), source = "plugin bundle mac (generic)" })
    table.insert(candidates, { path = LrPathUtils.child(binDir,    "cwebp"), source = "plugin bundle root" })
    table.insert(candidates, { path = "/opt/homebrew/bin/cwebp",              source = "Homebrew Apple Silicon" })
    table.insert(candidates, { path = "/usr/local/bin/cwebp",                 source = "Homebrew Intel" })
    table.insert(candidates, { path = "/usr/bin/cwebp",                       source = "/usr/bin" })
    table.insert(candidates, { path = "/bin/cwebp",                           source = "/bin" })
  end

  for _, entry in ipairs(candidates) do
    if fileExists(entry.path) and validateExe(entry.path) then
      return entry.path, entry.source
    end
  end

  -- PATH fallback
  if isWin() then
    local rc = LrTasks.execute('cmd.exe /c where cwebp > NUL 2>&1')
    if rc == 0 then return "cwebp", "system PATH" end
  else
    local rc = LrTasks.execute('cwebp -version > /dev/null 2>&1')
    if rc == 0 then return "cwebp", "system PATH" end
  end

  return nil, "not found"
end

-- ── Public module ────────────────────────────────────────────────────────────

local ExportDialog = {}

function ExportDialog.exportPresetFields()
  return {
    { key = 'webpMode',           default = 'lossy' },
    { key = 'webpQuality',        default = 80 },
    { key = 'webpNearLossless',   default = 60 },
    { key = 'webpZLevel',         default = 6 },
    { key = 'webpMethod',         default = 4 },
    { key = 'webpPreset',         default = 'photo' },
    { key = 'webpMetadata',       default = 'icc,exif,xmp' },
    { key = 'webpUseMt',          default = true },
    { key = 'webpColorSpace',     default = 'sRGB' },
    { key = 'deleteIntermediate', default = true },
    { key = 'cwebpPath',          default = '' },
    { key = 'debugMode',          default = false },
  }
end

function ExportDialog.startDialog(propertyTable)
  propertyTable.webpQuality       = tonumber(propertyTable.webpQuality) or 80
  propertyTable.webpNearLossless  = tonumber(propertyTable.webpNearLossless) or 60
  propertyTable.webpZLevel        = tonumber(propertyTable.webpZLevel) or 6
  propertyTable.webpMethod        = tonumber(propertyTable.webpMethod) or 4
end

function ExportDialog.sectionsForBottomOfDialog(f, propertyTable)
  return {
    {
      title = "WebP (cwebp) Settings  –  v" .. PLUGIN_VERSION,

      synopsis = function(props)
        return string.format(
          "%s · q=%s · preset=%s · metadata=%s",
          tostring(props.webpMode),
          tostring(props.webpQuality),
          tostring(props.webpPreset),
          tostring(props.webpMetadata)
        )
      end,

      -- ── Mode ──────────────────────────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:static_text { title = "Encoding mode", width = 140 },
        f:popup_menu {
          value = LrView.bind('webpMode'),
          items = {
            { title = "Lossy",         value = "lossy" },
            { title = "Lossless",      value = "lossless" },
            { title = "Near-lossless", value = "near_lossless" },
          },
        },
      },

      -- ── Quality ───────────────────────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:static_text { title = "Quality (0–100)", width = 140 },
        f:edit_field { value = LrView.bind('webpQuality'), width_in_chars = 6 },
        f:static_text { title = "  lossy + lossless hint" },
      },

      -- ── Near-lossless ─────────────────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:static_text { title = "Near-lossless (0–100)", width = 140 },
        f:edit_field {
          value = LrView.bind('webpNearLossless'),
          width_in_chars = 6,
          enabled = LrView.bind {
            keys = { 'webpMode' },
            transform = function(v) return v == "near_lossless" end,
          },
        },
        f:static_text { title = "  0 = max quality reduction" },
      },

      -- ── Lossless z-level ──────────────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:static_text { title = "Lossless level (0–9)", width = 140 },
        f:edit_field {
          value = LrView.bind('webpZLevel'),
          width_in_chars = 6,
          enabled = LrView.bind {
            keys = { 'webpMode' },
            transform = function(v) return v == "lossless" end,
          },
        },
        f:static_text { title = "  6 = default" },
      },

      -- ── Preset ────────────────────────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:static_text { title = "Preset", width = 140 },
        f:popup_menu {
          value = LrView.bind('webpPreset'),
          items = {
            { title = "photo",    value = "photo" },
            { title = "picture",  value = "picture" },
            { title = "drawing",  value = "drawing" },
            { title = "icon",     value = "icon" },
            { title = "text",     value = "text" },
            { title = "default",  value = "default" },
          },
        },
      },

      -- ── Method + Multi-thread ─────────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:static_text { title = "Method (0–6)", width = 140 },
        f:edit_field { value = LrView.bind('webpMethod'), width_in_chars = 6 },
        f:static_text { title = "  4 = default  |  " },
        f:checkbox { title = "Multi-thread (-mt)", value = LrView.bind('webpUseMt') },
      },

      -- ── Metadata ──────────────────────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:static_text { title = "Metadata", width = 140 },
        f:popup_menu {
          value = LrView.bind('webpMetadata'),
          items = {
            { title = "none",         value = "none" },
            { title = "icc",          value = "icc" },
            { title = "exif",         value = "exif" },
            { title = "xmp",          value = "xmp" },
            { title = "icc,exif,xmp", value = "icc,exif,xmp" },
            { title = "all",          value = "all" },
          },
        },
      },

      -- ── Color space ───────────────────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:static_text { title = "Render color space", width = 140 },
        f:popup_menu {
          value = LrView.bind('webpColorSpace'),
          items = {
            { title = "sRGB",         value = "sRGB" },
            { title = "Adobe RGB",    value = "AdobeRGB" },
            { title = "ProPhoto RGB", value = "ProPhotoRGB" },
          },
        },
      },

      -- ── Keep / delete intermediate ────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:checkbox {
          title = "Delete intermediate TIFF after conversion  (uncheck to keep it for debugging)",
          value = LrView.bind('deleteIntermediate'),
        },
      },

      -- ── Debug mode ────────────────────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:checkbox {
          title = "Debug mode – write detailed log to export folder  (webp-export-log.txt)",
          value = LrView.bind('debugMode'),
        },
      },

      f:spacer { height = 12 },

      -- ── cwebp path ────────────────────────────────────────────────────────
      f:row {
        spacing = f:control_spacing(),
        f:static_text { title = "cwebp executable path", width = 140 },
        f:edit_field {
          value = LrView.bind('cwebpPath'),
          width_in_chars = 44,
          placeholder_string = isWin()
            and "C:\\path\\to\\cwebp.exe  (leave empty for auto-detect)"
            or  "/path/to/cwebp  (leave empty for auto-detect)",
        },
        f:push_button {
          title = "Browse…",
          action = function()
            local res = LrDialogs.runOpenPanel {
              title = "Select cwebp executable",
              canChooseFiles = true,
              canChooseDirectories = false,
              allowsMultipleSelection = false,
            }
            if res and res[1] then
              propertyTable.cwebpPath = res[1]
            end
          end,
        },
      },

      -- ── Test button ───────────────────────────────────────────────────────
      f:spacer { height = 6 },
      f:row {
        spacing = f:control_spacing(),
        f:push_button {
          title = "▶  Test cwebp  (verify before exporting)",
          action = function()
            LrTasks.startAsyncTask(function()
              local exe, source = resolveCwebp(propertyTable)
              if not exe then
                LrDialogs.message(
                  "WebP Exporter – Test Result",
                  "cwebp NOT found.\n\n" ..
                  "macOS: place cwebp in the plugin folder:\n" ..
                  "  bin/mac/arm64/cwebp   (Apple Silicon)\n" ..
                  "  bin/mac/x86_64/cwebp  (Intel)\n\n" ..
                  "Windows: place cwebp.exe in:\n" ..
                  "  bin/win/cwebp.exe\n\n" ..
                  "Or set the full path manually in the field above.\n" ..
                  "Download from: developers.google.com/speed/webp/docs/precompiled",
                  "critical"
                )
              else
                LrDialogs.message(
                  "WebP Exporter – Test Result",
                  "cwebp found and working.\n\nPath: " .. exe .. "\nSource: " .. source .. "\n\nYou are ready to export WebP files.",
                  "info"
                )
              end
            end)
          end,
        },
        f:static_text { title = "  <- click to verify cwebp is correctly installed" },
      },

      -- ── Author ────────────────────────────────────────────────────────────
      f:spacer { height = 10 },
      f:row {
        spacing = f:control_spacing(),
        f:static_text { title = "Plugin by Marco De Maio  |  marcodemaio.it" },
      },
    },
  }
end

return ExportDialog
