{ config, pkgs, lib, ... }:

let
  cfg = config.local.xmonad;
  themeCfg = config.local.theme;

  projectType = with lib; types.submodule {
    options = {
      name = mkOption {
        type = types.str;
      };
      workdir = mkOption {
        type = types.str;
      };
      windowCount = mkOption {
        type = types.ints.positive;
        default = 1;
      };
      terminalCommands = mkOption {
        type = types.listOf types.str;
        default = [ ];
      };
      spawnPrograms = mkOption {
        type = types.listOf types.str;
        default = [ ];
      };
    };
  };

  mkXmonadProjectSpawnProgram = program:
    "spawn \"${program}\"";

  mkXmonadProjectTerminalCommand = command:
    "spawn $ terminal' workdir $ Just \"${command}\"";


  mkXmonadProject = { name, workdir, windowCount, spawnPrograms, terminalCommands }:
    ''
      Project {
        projectName = "${name}",
        projectStartHook =
          do
            let workdir = "${workdir}"
            ${lib.concatStringsSep "\n" (map mkXmonadProjectSpawnProgram spawnPrograms)}
            ${lib.concatStringsSep "\n" (map mkXmonadProjectTerminalCommand terminalCommands)}
            replicateM_ ${toString windowCount} $ spawn $ terminal workdir
      }
    '';

  xmonadProjects = lib.concatStringsSep "  , " (map mkXmonadProject cfg.projects);
in
{
  options.local.xmonad = with lib;
    {
      projects = mkOption {
        type = types.listOf projectType;
        default = [ ];
      };
    };

  config = {
    home.packages = with pkgs; [
      xclip # access x clipboard from a console
      dmenu # menu for x window system
      nitrogen # wallpaper manager
    ];

    xsession = {
      enable = true;

      windowManager.xmonad = {
        enable = true;
        enableContribAndExtras = true;

        haskellPackages = pkgs.unstable.haskellPackages;
        extraPackages = (hp: [
          hp.dbus
          hp.monad-logger
        ]);

        config = pkgs.substituteAll {
          src = ./xmonad_config.hs;
          projects = "\n  " + xmonadProjects;
          inherit (themeCfg.bar) background mainText inactiveText;
          inherit (themeCfg.window) activeBorder inactiveBorder;
          inherit (themeCfg.highlights) critical warning success;
          inherit (themeCfg.syntax) mark1 mark2 mark3;
          kdbBrightnessScriptPath = "${./scripts/kdb_brightness.sh}";
        };
      };

      initExtra = ''
        ${pkgs.nitrogen}/bin/nitrogen --restore &
      '';
    };

    services.flameshot = {
      enable = true;

      # See: https://github.com/flameshot-org/flameshot/blob/master/flameshot.example.ini
      settings = {
        General = {
          disabledTrayIcon = true;
          savePathFixed = true;
          showDesktopNotification = false;
          showSidePanelButton = true;
        };
      };
    };
  };
}
