from std/osproc import execProcess, ProcessOption, startProcess, waitForExit, close
from std/strutils import split, endsWith, contains
from std/strformat import fmt
import pkg/owlkettle

type Theme = tuple[color, shade, style: string]

const
  themeShades* = ["Light", "", "Dark"]
  themeStyles* = ["Default", "Nord", "Dracula", "Catppuccin", "Everforest", "Gruvbox"]
  accentColors* = ["Blue", "Red", "Purple", "Pink", "Teal", "Green", "Yellow", "Orange", "Grey"]
  appID* = "com.tromjaro.ThemeSwitcher"
  appLogo* = "tromjaro-theme-switcher"

proc getCurrentTheme*(): Theme =
  let currentThemeString = execProcess("/usr/bin/xfconf-query",
    args=["--channel=xsettings", "--property=/Net/ThemeName"],
    options={})[0 .. ^2]

  # Split the theme string into words
  let words = currentThemeString.split('-')
  if words[0] != "Colloid":
    return
  var currentTheme: Theme = (color: "Blue", shade: "", style: "Default")

  case len(words):
    of 1: discard

    # Match against Colloid-Color, Colloid-Shade, Colloid-Style
    of 2:
      let word1 = words[1]
      if word1 in accentColors:
        currentTheme.color = word1
      elif word1 in themeShades:
        currentTheme.shade = word1
      elif word1 in themeStyles:
        currentTheme.style = word1
      else:
        return

    # Match against Colloid-Color-Shade, Colloid-Shade-Style
    of 3:
      let
        word1 = words[1]
        word2 = words[2]
      if (word1 in accentColors) and (word2 in themeShades):
        currentTheme.color = word1
        currentTheme.shade = word2
      elif (word1 in themeShades) and (word2 in themeStyles):
        currentTheme.shade = word1
        currentTheme.style = word2
      else:
        return

    # Match against Colloid-Color-Shade-Style
    of 4:
      let
        word1 = words[1]
        word2 = words[2]
        word3 = words[3]
      if (word1 in accentColors) and (word2 in themeShades) and (word3 in themeStyles):
        currentTheme.color = word1
        currentTheme.shade = word2
        currentTheme.style = word3
      else:
        return

    else:
      return

  return currentTheme

proc runCommand(command: string, args: openArray[string]): bool =
  ## This will run a command with the given args and return true upon success
  let process = startProcess(command, args=args, options={poParentStreams})
  result = process.waitForExit() == 0
  process.close()

proc setIconTheme(iconName: string) =
  # Change icon theme in XFCE
  discard runCommand("/usr/bin/xfconf-query",
    args=["--channel=xsettings", "--property=/Net/IconThemeName", "--create", "--type=string", "--set", iconName])

proc enableDarkPanels(): bool =
  # Return if dark panels is already enabled
  if execProcess("/usr/bin/xfconf-query",
    args=["--channel=xfce4-panel", "--property=/panels/dark-mode"], options={}) == "true\n":
    return
  # Try to enable it and return true upon success
  result = runCommand("/usr/bin/xfconf-query",
    args=["--channel=xfce4-panel", "--property=/panels/dark-mode", "--create", "--type=bool", "--set=true"])

proc setTheme*(themeName: string) =

  var panelNotification: string

  # Set the icon theme and panel color according to the chosen theme
  if themeName.endsWith("-Dark") or themeName.contains("-Dark-"):
    setIconTheme("zafiro-dark")
  else:
    setIconTheme("zafiro")
    if enableDarkPanels():
      panelNotification = " with dark panels"

  # Change the main theme to the chosen one
  discard runCommand("/usr/bin/xfconf-query",
    args=["--channel=xsettings", "--property=/Net/ThemeName", "--create", "--type=string", "--set", themeName])

  # Send notification about the theme change
  sendNotification(appID, "Theme Switcher", fmt"{themeName} theme{panelNotification} is enabled",
    icon=appLogo)