{
  lib,
  config,
  ...
}: let
  inherit (lib) mkOption types mkIf recursiveUpdate trivial strings lists;
  inherit (builtins) concatStringsSep elem genList elemAt length;
  inherit (trivial) boolToString;
  inherit (strings) floatToString;
  inherit (lists) remove;
  cfg = config.horseman.wm.hyprland;
  homeCfg = config.horseman;

  keybinding = types.submodule {
    options = {
      flags = mkOption {
        type = types.listOf (types.enum ["l" "r" "c" "g" "o" "e" "m" "t" "i" "s" "d" "p"]);
      };

      mods = mkOption {
        type = types.listOf types.str;
      };

      key = mkOption {
        type = types.str;
      };

      dispatcher = mkOption {
        type = types.str;
      };

      params = mkOption {
        type = types.str;
      };
    };
  };
  submapKeybinding = types.submodule {
    options = {
      flags = mkOption {
        type = types.listOf (types.enum ["l" "r" "c" "g" "o" "e" "m" "t" "i" "s" "d" "p"]);
      };

      mods = mkOption {
        type = types.listOf types.str;
      };

      key = mkOption {
        type = types.str;
      };
    };
  };
  vec2 = types.submodule {
    options = {
      x = mkOption {type = types.int;};
      y = mkOption {type = types.int;};
    };
  };
  fontWeight = types.enum ["thin" "ultralight" "light" "semilight" "book" "normal" "medium" "semibold" "bold" "ultrabold" "heavy" "ultraheavy"];
in {
  options.horseman.wm.hyprland.config = {
    execOnce = mkOption {
      type = types.listOf types.str;
      default = [];
    };
    env = mkOption {
      type = types.listOf types.str;
      default = [];
    };
    windowrules = mkOption {
      type = types.listOf types.str;
      default = [];
    };
    workspaces = mkOption {
      type = types.listOf types.str;
      default = [];
    };
    general = {
      borderSize = mkOption {
        type = types.int;
        default = 1;
      };
      noBorderOnFloating = mkOption {
        type = types.bool;
        default = false;
      };
      gapsIn = mkOption {
        type = types.int;
        default = 5;
      };
      gapsOut = mkOption {
        type = types.int;
        default = 20;
      };
      gapsWorkspaces = mkOption {
        type = types.int;
        default = 0;
      };
      col.inactiveBorder = mkOption {
        type = types.str;
        default = "0xff444444";
      };
      col.activeBorder = mkOption {
        type = types.str;
        default = "0xffffffff";
      };
      col.nogroupBorder = mkOption {
        type = types.str;
        default = "0xffffaaff";
      };
      col.nogroupBorderActive = mkOption {
        type = types.str;
        default = "0xffff00ff";
      };
      layout = mkOption {
        type = types.enum ["dwindle" "master"];
        default = "dwindle";
      };
      noFocusFallback = mkOption {
        type = types.bool;
        default = false;
      };
      resizeOnBorder = mkOption {
        type = types.bool;
        default = false;
      };
      extendBorderGrabArea = mkOption {
        type = types.int;
        default = 15;
      };
      hoverIconOnBorder = mkOption {
        type = types.bool;
        default = true;
      };
      allowTearing = mkOption {
        type = types.bool;
        default = false;
      };
      resizeCorner = mkOption {
        type = types.ints.between 0 4;
        default = 0;
      };

      snap = {
        enabled = mkOption {
          type = types.bool;
          default = false;
        };
        windowGap = mkOption {
          type = types.int;
          default = 10;
        };
        monitorGap = mkOption {
          type = types.int;
          default = 10;
        };
        borderOverlap = mkOption {
          type = types.bool;
          default = false;
        };
      };
    };

    decoration = {
      rounding = mkOption {
        type = types.int;
        default = 0;
      };
      roundingPower = mkOption {
        type = types.numbers.between 2 10;
        default = 2.0;
      };
      activeOpacity = mkOption {
        type = types.numbers.between 0 1;
        default = 1.0;
      };
      inactiveOpacity = mkOption {
        type = types.numbers.between 0 1;
        default = 1.0;
      };
      fullscreenOpacity = mkOption {
        type = types.numbers.between 0 1;
        default = 1.0;
      };
      dimInactive = mkOption {
        type = types.bool;
        default = false;
      };
      dimStrength = mkOption {
        type = types.numbers.between 0 1;
        default = 0.5;
      };
      dimSpecial = mkOption {
        type = types.numbers.between 0 1;
        default = 0.2;
      };
      dimAround = mkOption {
        type = types.numbers.between 0 1;
        default = 0.4;
      };
      screenShader = mkOption {
        type = types.str;
        default = "";
      };
      borderPartOfWindow = mkOption {
        type = types.bool;
        default = true;
      };

      blur = {
        enabled = mkOption {
          type = types.bool;
          default = true;
        };
        size = mkOption {
          type = types.int;
          default = 8;
        };
        passes = mkOption {
          type = types.int;
          default = 1;
        };
        ignoreOpacity = mkOption {
          type = types.bool;
          default = true;
        };
        newOptimizations = mkOption {
          type = types.bool;
          default = true;
        };
        xray = mkOption {
          type = types.bool;
          default = false;
        };
        noise = mkOption {
          type = types.numbers.between 0 1;
          default = 0.0117;
        };
        contrast = mkOption {
          type = types.numbers.between 0 2;
          default = 0.8916;
        };
        brightness = mkOption {
          type = types.numbers.between 0 2;
          default = 0.8172;
        };
        vibrancy = mkOption {
          type = types.numbers.between 0 1;
          default = 0.1696;
        };
        vibrancyDarkness = mkOption {
          type = types.numbers.between 0 1;
          default = 0.0;
        };
        special = mkOption {
          type = types.bool;
          default = false;
        };
        popups = mkOption {
          type = types.bool;
          default = false;
        };
        popupsIgnorealpha = mkOption {
          type = types.numbers.between 0 1;
          default = 0.2;
        };
        inputMethods = mkOption {
          type = types.bool;
          default = false;
        };
        inputMethodsIgnorealpha = mkOption {
          type = types.numbers.between 0 1;
          default = 0.2;
        };
      };

      shadow = {
        enabled = mkOption {
          type = types.bool;
          default = true;
        };
        range = mkOption {
          type = types.int;
          default = 4;
        };
        renderPower = mkOption {
          type = types.ints.between 1 4;
          default = 3;
        };
        sharp = mkOption {
          type = types.bool;
          default = false;
        };
        ignoreWindow = mkOption {
          type = types.bool;
          default = true;
        };
        color = mkOption {
          type = types.str;
          default = "0xee1a1a1a";
        };
        colorInactive = mkOption {
          type = types.nullOr types.str;
          default = null;
        };
        offset = mkOption {
          type = vec2;
          default = {
            x = 0;
            y = 0;
          };
        };
        scale = mkOption {
          type = types.numbers.between 0 1;
          default = 1.0;
        };
      };
    };

    animations = {
      enabled = mkOption {
        type = types.bool;
        default = true;
      };
      workspaceWraparound = mkOption {
        type = types.bool;
        default = false;
      };

      beziers = mkOption {
        type = types.listOf (types.submodule {
          options = {
            name = mkOption {type = types.str;};
            startX = mkOption {type = types.number;};
            startY = mkOption {type = types.number;};
            endX = mkOption {type = types.number;};
            endY = mkOption {type = types.number;};
          };
        });
      };

      animations = mkOption {
        type = types.listOf (types.submodule {
          options = {
            name = mkOption {type = types.str;};
            on = mkOption {type = types.bool;};
            speed = mkOption {
              type = types.number;
              default = 0;
            };
            curve = mkOption {
              type = types.str;
              default = "";
            };
            style = mkOption {
              type = types.str;
              default = "";
            };
          };
        });
      };
    };

    input = {
      kbModel = mkOption {
        type = types.str;
        default = "";
      };
      kbLayout = mkOption {
        type = types.str;
        default = "us";
      };
      kbVariant = mkOption {
        type = types.str;
        default = "";
      };
      kbOptions = mkOption {
        type = types.str;
        default = "";
      };
      kbRules = mkOption {
        type = types.str;
        default = "";
      };
      kbFile = mkOption {
        type = types.str;
        default = "";
      };
      numlockByDefault = mkOption {
        type = types.bool;
        default = false;
      };
      resolveBindsBySym = mkOption {
        type = types.bool;
        default = false;
      };
      repeatRate = mkOption {
        type = types.int;
        default = 25;
      };
      repeatDelay = mkOption {
        type = types.int;
        default = 600;
      };
      sensitivity = mkOption {
        type = types.numbers.between 0 1;
        default = 0.0;
      };
      accelProfile = mkOption {
        type = types.enum ["" "adaptive" "flat"];
        default = "";
      };
      forceNoAccel = mkOption {
        type = types.bool;
        default = false;
      };
      leftHanded = mkOption {
        type = types.bool;
        default = false;
      };
      scrollPoints = mkOption {
        type = types.str;
        default = "";
      };
      scrollMethod = mkOption {
        type = types.enum ["" "2fg" "edge" "on_button_down" "no_scroll"];
        default = "";
      };
      scrollButton = mkOption {
        type = types.int;
        default = 0;
      };
      scrollButtonLock = mkOption {
        type = types.bool;
        default = false;
      };
      scrollFactor = mkOption {
        type = types.float;
        default = 1.0;
      };
      naturalScroll = mkOption {
        type = types.bool;
        default = false;
      };
      followMouse = mkOption {
        type = types.enum [0 1 2 3];
        default = 1;
      };
      followMouseThreshold = mkOption {
        type = types.float;
        default = 0.0;
      };
      focusOnClose = mkOption {
        type = types.enum [0 1];
        default = 0;
      };
      mouseRefocus = mkOption {
        type = types.bool;
        default = true;
      };
      floatSwitchOverrideFocus = mkOption {
        type = types.enum [1 2];
        default = 1;
      };
      specialFallthrough = mkOption {
        type = types.bool;
        default = false;
      };
      offWindowAxisEvents = mkOption {
        type = types.enum [0 1 2 3];
        default = 1;
      };
      emulateDiscreteScroll = mkOption {
        type = types.enum [0 1 2];
        default = 1;
      };

      touchpad = {
        disableWhileTyping = mkOption {
          type = types.bool;
          default = true;
        };
        naturalScroll = mkOption {
          type = types.bool;
          default = false;
        };
        scrollFactor = mkOption {
          type = types.float;
          default = 1.0;
        };
        middleButtonEmulation = mkOption {
          type = types.bool;
          default = false;
        };
        tapButtonMap = mkOption {
          type = types.enum ["lrm" "lmr"];
          default = "lrm";
        };
        clickfingerBehavior = mkOption {
          type = types.bool;
          default = false;
        };
        tapToClick = mkOption {
          type = types.bool;
          default = true;
        };
        dragLock = mkOption {
          type = types.bool;
          default = false;
        };
        tapAndDrag = mkOption {
          type = types.bool;
          default = true;
        };
        flipX = mkOption {
          type = types.bool;
          default = false;
        };
        flipY = mkOption {
          type = types.bool;
          default = false;
        };
      };

      touchdevice = {
        transform = mkOption {
          type = types.ints.between (-1) 7;
          default = -1;
        };
        output = mkOption {
          type = types.str;
          default = "[[Auto]]";
        };
        enabled = mkOption {
          type = types.bool;
          default = true;
        };
      };

      tablet = {
        transform = mkOption {
          type = types.ints.between (-1) 7;
          default = -1;
        };
        output = mkOption {
          type = types.str;
          default = "";
        };
        regionPosition = mkOption {
          type = vec2;
          default = {
            x = 0;
            y = 0;
          };
        };
        absoluteRegionPosition = mkOption {
          type = types.bool;
          default = false;
        };
        regionSize = mkOption {
          type = vec2;
          default = {
            x = 0;
            y = 0;
          };
        };
        relativeInput = mkOption {
          type = types.bool;
          default = false;
        };
        leftHanded = mkOption {
          type = types.bool;
          default = false;
        };
        activeAreaSize = mkOption {
          type = vec2;
          default = {
            x = 0;
            y = 0;
          };
        };
        activeAreaPosition = mkOption {
          type = vec2;
          default = {
            x = 0;
            y = 0;
          };
        };
      };
    };

    gestures = {
      workspaceSwipe = mkOption {
        type = types.bool;
        default = false;
      };
      workspaceSwipeFingers = mkOption {
        type = types.int;
        default = 3;
      };
      workspaceSwipeMinFingers = mkOption {
        type = types.bool;
        default = false;
      };
      workspaceSwipeDistance = mkOption {
        type = types.int;
        default = 300;
      };
      workspaceSwipeTouch = mkOption {
        type = types.bool;
        default = false;
      };
      workspaceSwipeInvert = mkOption {
        type = types.bool;
        default = true;
      };
      workspaceSwipeTouchInvert = mkOption {
        type = types.bool;
        default = false;
      };
      workspaceSwipeMinSpeedToForce = mkOption {
        type = types.int;
        default = 30;
      };
      workspaceSwipeCancelRatio = mkOption {
        type = types.numbers.between 0 1;
        default = 0.5;
      };
      workspaceSwipeCreateNew = mkOption {
        type = types.bool;
        default = true;
      };
      workspaceSwipeDirectionLock = mkOption {
        type = types.bool;
        default = true;
      };
      workspaceSwipeDirectionLockThreshold = mkOption {
        type = types.int;
        default = 10;
      };
      workspaceSwipeForever = mkOption {
        type = types.bool;
        default = false;
      };
      workspaceSwipeUseR = mkOption {
        type = types.bool;
        default = false;
      };
    };

    group = {
      autoGroup = mkOption {
        type = types.bool;
        default = true;
      };
      insertAfterCurrent = mkOption {
        type = types.bool;
        default = true;
      };
      focusRemovedWindow = mkOption {
        type = types.bool;
        default = true;
      };
      dragIntoGroup = mkOption {
        type = types.enum [0 1 2];
        default = 1;
      };
      mergeGroupsOnDrag = mkOption {
        type = types.bool;
        default = true;
      };
      mergeGroupsOnGroupbar = mkOption {
        type = types.bool;
        default = true;
      };
      mergeFloatedIntoTiledOnGroupbar = mkOption {
        type = types.bool;
        default = false;
      };
      groupOnMovetoworkspace = mkOption {
        type = types.bool;
        default = false;
      };
      col.borderActive = mkOption {
        type = types.str;
        default = "0x66ffff00";
      };
      col.borderInactive = mkOption {
        type = types.str;
        default = "0x66777700";
      };
      col.borderLockedActive = mkOption {
        type = types.str;
        default = "0x66ff5500";
      };
      col.borderLockedInactive = mkOption {
        type = types.str;
        default = "0x66775500";
      };

      groupbar = {
        enabled = mkOption {
          type = types.bool;
          default = true;
        };
        fontFamily = mkOption {
          type = types.str;
          default = "";
        };
        fontSize = mkOption {
          type = types.int;
          default = 8;
        };
        fontWeightActive = mkOption {
          type = fontWeight;
          default = "normal";
        };
        fontWeightInactive = mkOption {
          type = fontWeight;
          default = "normal";
        };
        gradients = mkOption {
          type = types.bool;
          default = false;
        };
        height = mkOption {
          type = types.int;
          default = 14;
        };
        indicatorGap = mkOption {
          type = types.int;
          default = 0;
        };
        indicatorHeight = mkOption {
          type = types.int;
          default = 3;
        };
        stacked = mkOption {
          type = types.bool;
          default = false;
        };
        priority = mkOption {
          type = types.int;
          default = 3;
        };
        renderTitles = mkOption {
          type = types.bool;
          default = true;
        };
        textOffset = mkOption {
          type = types.int;
          default = 0;
        };
        scrolling = mkOption {
          type = types.bool;
          default = true;
        };
        rounding = mkOption {
          type = types.int;
          default = 1;
        };
        gradientRounding = mkOption {
          type = types.int;
          default = 2;
        };
        roundOnlyEdges = mkOption {
          type = types.bool;
          default = true;
        };
        gradientRoundOnlyEdges = mkOption {
          type = types.bool;
          default = true;
        };
        textColor = mkOption {
          type = types.str;
          default = "0xffffffff";
        };
        col.active = mkOption {
          type = types.str;
          default = "0x66ffff00";
        };
        col.inactive = mkOption {
          type = types.str;
          default = "0x66777700";
        };
        col.lockedActive = mkOption {
          type = types.str;
          default = "0x66ff5500";
        };
        col.lockedInactive = mkOption {
          type = types.str;
          default = "0x66775500";
        };
        gapsIn = mkOption {
          type = types.int;
          default = 2;
        };
        gapsOut = mkOption {
          type = types.int;
          default = 2;
        };
        keepUpperGap = mkOption {
          type = types.bool;
          default = true;
        };
      };
    };

    misc = {
      disableHyprlandLogo = mkOption {
        type = types.bool;
        default = false;
      };
      disableSplashRendering = mkOption {
        type = types.bool;
        default = false;
      };
      col.splash = mkOption {
        type = types.str;
        default = "0xffffffff";
      };
      fontFamily = mkOption {
        type = types.str;
        default = "Sans";
      };
      splashFontFamily = mkOption {
        type = types.str;
        default = "";
      };
      forceDefaultWallpaper = mkOption {
        type = types.enum [(-1) 0 1 2];
        default = -1;
      };
      vfr = mkOption {
        type = types.bool;
        default = true;
      };
      vrr = mkOption {
        type = types.enum [0 1 2 3];
        default = 0;
      };
      mouseMoveEnablesDPMS = mkOption {
        type = types.bool;
        default = false;
      };
      keyPressEnablesDPMS = mkOption {
        type = types.bool;
        default = false;
      };
      alwaysFollowOnDnd = mkOption {
        type = types.bool;
        default = true;
      };
      layersHogKeyboardFocus = mkOption {
        type = types.bool;
        default = true;
      };
      animateManualResizes = mkOption {
        type = types.bool;
        default = false;
      };
      animateMouseWindowdragging = mkOption {
        type = types.bool;
        default = false;
      };
      disableAutoreload = mkOption {
        type = types.bool;
        default = false;
      };
      enableSwallow = mkOption {
        type = types.bool;
        default = false;
      };
      swallowRegex = mkOption {
        type = types.str;
        default = "";
      };
      swallowExceptionRegex = mkOption {
        type = types.str;
        default = "";
      };
      focusOnActivate = mkOption {
        type = types.bool;
        default = false;
      };
      mouseMoveFocusesMonitor = mkOption {
        type = types.bool;
        default = true;
      };
      allowSessionLockRestore = mkOption {
        type = types.bool;
        default = false;
      };
      backgroundColor = mkOption {
        type = types.str;
        default = "0x111111";
      };
      closeSpecialOnEmpty = mkOption {
        type = types.bool;
        default = true;
      };
      newWindowTakesOverFullscreen = mkOption {
        type = types.enum [0 1 2];
        default = 0;
      };
      exitWindowRetainsFullscreen = mkOption {
        type = types.bool;
        default = false;
      };
      initialWorkspaceTracking = mkOption {
        type = types.enum [0 1 2];
        default = 1;
      };
      middleClickPaste = mkOption {
        type = types.bool;
        default = true;
      };
      renderUnfocusedFps = mkOption {
        type = types.int;
        default = 15;
      };
      disableXdgEnvChecks = mkOption {
        type = types.bool;
        default = false;
      };
      disableHyprlandQtutilsCheck = mkOption {
        type = types.bool;
        default = false;
      };
      lockdeadScreenDelay = mkOption {
        type = types.int;
        default = 1000;
      };
      enableAnrDialog = mkOption {
        type = types.bool;
        default = true;
      };
      anrMissedPings = mkOption {
        type = types.int;
        default = 1;
      };
    };

    binds = {
      passMouseWhenBound = mkOption {
        type = types.bool;
        default = false;
      };
      scrollEventDelay = mkOption {
        type = types.int;
        default = 300;
      };
      workspaceBackAndForth = mkOption {
        type = types.bool;
        default = false;
      };
      hideSpecialOnWorkspaceChange = mkOption {
        type = types.bool;
        default = false;
      };
      allowWorkspaceCycles = mkOption {
        type = types.bool;
        default = false;
      };
      workspaceCenterOn = mkOption {
        type = types.enum [0 1];
        default = 0;
      };
      focusPreferredMethod = mkOption {
        type = types.enum [0 1];
        default = 0;
      };
      ignoreGroupLock = mkOption {
        type = types.bool;
        default = false;
      };
      movefocusCyclesFullscreen = mkOption {
        type = types.bool;
        default = false;
      };
      movefocusCyclesGroupfirst = mkOption {
        type = types.bool;
        default = false;
      };
      disableKeybindGrabbing = mkOption {
        type = types.bool;
        default = false;
      };
      windowDirectionMonitorFallback = mkOption {
        type = types.bool;
        default = true;
      };
      allowPinFullscreen = mkOption {
        type = types.bool;
        default = false;
      };
      dragThreshold = mkOption {
        type = types.int;
        default = 0;
      };
    };

    xwayland = {
      enabled = mkOption {
        type = types.bool;
        default = true;
      };
      useNearestNeighbor = mkOption {
        type = types.bool;
        default = true;
      };
      forceZeroScaling = mkOption {
        type = types.bool;
        default = false;
      };
      createAbstractSocket = mkOption {
        type = types.bool;
        default = false;
      };
    };

    opengl = {
      nvidiaAntiFlicker = mkOption {
        type = types.bool;
        default = true;
      };
    };

    render = {
      directScanout = mkOption {
        type = types.enum [0 1 2];
        default = 0;
      };
      expandUndersizedTextures = mkOption {
        type = types.bool;
        default = true;
      };
      xpMode = mkOption {
        type = types.bool;
        default = false;
      };
      ctmAnimation = mkOption {
        type = types.enum [0 1 2];
        default = 2;
      };
      cmFsPassthrough = mkOption {
        type = types.enum [0 1 2];
        default = 2;
      };
      cmEnabled = mkOption {
        type = types.bool;
        default = true;
      };
      sendContentType = mkOption {
        type = types.bool;
        default = true;
      };
    };

    cursor = {
      syncGsettingsTheme = mkOption {
        type = types.bool;
        default = true;
      };
      noHardwareCursors = mkOption {
        type = types.enum [0 1 2];
        default = 2;
      };
      noBreakFsVrr = mkOption {
        type = types.enum [0 1 2];
        default = 2;
      };
      minRefreshRate = mkOption {
        type = types.int;
        default = 24;
      };
      hotspotPadding = mkOption {
        type = types.int;
        default = 1;
      };
      inactiveTimeout = mkOption {
        type = types.number;
        default = 0;
      };
      noWarps = mkOption {
        type = types.bool;
        default = false;
      };
      persistentWarps = mkOption {
        type = types.bool;
        default = false;
      };
      warpOnChangeWorkspace = mkOption {
        type = types.enum [0 1 2];
        default = 0;
      };
      warpOnToggleSpecial = mkOption {
        type = types.enum [0 1 2];
        default = 0;
      };
      defaultMonitor = mkOption {
        type = types.str;
        default = "";
      };
      zoomFactor = mkOption {
        type = types.float;
        default = 1.0;
      };
      zoomRigid = mkOption {
        type = types.bool;
        default = false;
      };
      enableHyprcursor = mkOption {
        type = types.bool;
        default = true;
      };
      hideOnKeyPress = mkOption {
        type = types.bool;
        default = false;
      };
      hideOnTouch = mkOption {
        type = types.bool;
        default = true;
      };
      useCpuBuffer = mkOption {
        type = types.enum [0 1 2];
        default = 2;
      };
      warpBackAfterNonMouseInput = mkOption {
        type = types.bool;
        default = false;
      };
    };

    ecosystem = {
      noUpdateNews = mkOption {
        type = types.bool;
        default = false;
      };
      noDonationNag = mkOption {
        type = types.bool;
        default = false;
      };
      enforcePermissions = mkOption {
        type = types.bool;
        default = false;
      };
    };

    dwindle = {
      pseudotile = mkOption {type = types.bool;};
      preserveSplit = mkOption {type = types.bool;};
    };

    master = {
      newStatus = mkOption {type = types.enum ["master" "slave" "inherit"];};
    };

    monitors = {
      defaultMonitor = mkOption {type = types.bool;};
      bindWorkspaces = mkOption {
        type = types.enum ["no" "interlaced"];
        default = "no";
      };

      displays = mkOption {
        type = types.listOf (types.submodule {
          options = {
            output = mkOption {type = types.str;};
            resolution = mkOption {
              type = types.str;
              default = "highres";
            };
            refreshRate = mkOption {
              type = types.str;
              default = "highrr";
            };
            x = mkOption {type = types.int;};
            y = mkOption {type = types.int;};
            scale = mkOption {
              type = types.number;
              default = 1;
            };
            transform = mkOption {
              type = types.enum [0 1 2 3 4 5 6 7];
              default = 0;
            };
            wallpaper = mkOption {
              type = types.nullOr types.path;
              default = null;
            };
            bar = mkOption {
              type = types.enum ["" "left" "right" "top" "bottom"];
              default = "";
            };
          };
        });
      };
    };

    keybindings = {
      binds = mkOption {type = types.listOf keybinding;};

      submaps = mkOption {
        type = types.listOf (types.submodule {
          options = {
            name = mkOption {type = types.str;};
            enterBind = mkOption {type = submapKeybinding;};
            exitBind = mkOption {type = submapKeybinding;};
            binds = mkOption {type = types.listOf keybinding;};
          };
        });
      };
    };

    sleep = {
      lockCommand = mkOption {type = types.str;};

      listeners = mkOption {
        type = types.listOf (types.submodule {
          options = {
            timeout = mkOption {type = types.ints.positive;};
            onTimeout = mkOption {type = types.str;};
            onResume = mkOption {
              type = types.str;
              default = "";
            };
            ignoreInhibit = mkOption {
              type = types.bool;
              default = false;
            };
          };
        });
      };
    };

    waybar = {
      layout = {
        horizontal = {
          left = mkOption {type = types.listOf types.str;};
          center = mkOption {type = types.listOf types.str;};
          right = mkOption {type = types.listOf types.str;};
        };
        vertical = {
          left = mkOption {type = types.listOf types.str;};
          center = mkOption {type = types.listOf types.str;};
          right = mkOption {type = types.listOf types.str;};
        };
      };
      formats = {
        horizontal = mkOption {
          type = types.attrs;
        };
        vertical = mkOption {
          type = types.attrs;
        };
      };
      modules = mkOption {
        type = types.attrs;
      };
    };
  };

  config = mkIf cfg.enable {
    home-manager.users.${homeCfg.username} = {
      xdg.configFile."hypr/hypridle.conf".text = ''
        # This file has been auto-generated.
        general {
            lock_cmd = ${cfg.config.sleep.lockCommand}
        }

        ${concatStringsSep "\n\n" (map (lis: ''
            listener {
                timeout = ${toString lis.timeout}
                on-timeout = ${lis.onTimeout}
                on-resume = ${lis.onResume}
            }
          '')
          cfg.config.sleep.listeners)}
      '';

      xdg.configFile."hypr/hyprpaper.conf".text = ''
        # This file has been auto-generated.
        ${concatStringsSep "\n" (map (dis:
          if dis.wallpaper != null
          then ''
            preload = ${dis.wallpaper}
            wallpaper = ${dis.output}, ${dis.wallpaper}
          ''
          else "")
        cfg.config.monitors.displays)}

        preload = /home/horseman/nix-config/misc/wallpaper.jpg
        wallpaper = , /home/horseman/nix-config/misc/wallpaper.jpg
      '';

      xdg.configFile."hypr/hyprlock.conf".text = ''
        $font = Monospace

        general {
            hide_cursor = false
        }

        animations {
            enabled = true
            bezier = linear, 1, 1, 0, 0
            animation = fadeIn, 1, 5, linear
            animation = fadeOut, 1, 5, linear
            animation = inputFieldDots, 1, 2, linear
        }

        background {
            monitor =
            path = screenshot
            blur_passes = 3
        }

        input-field {
            monitor =
            size = 20%, 5%
            outline_thickness = 3
            inner_color = rgba(0, 0, 0, 0.0) # no fill

            outer_color = rgba(33ccffee) rgba(00ff99ee) 45deg
            check_color = rgba(00ff99ee) rgba(ff6633ee) 120deg
            fail_color = rgba(ff6633ee) rgba(ff0066ee) 40deg

            font_color = rgb(143, 143, 143)
            fade_on_empty = false
            rounding = 15

            font_family = $font
            placeholder_text = Input password...
            fail_text = $PAMFAIL

            dots_spacing = 0.3

            position = 0, -20
            halign = center
            valign = center
        }

        label {
            monitor =
            text = $TIME
            font_size = 90
            font_family = $font

            position = 0, -50
            halign = center
            valign = top
        }
      '';

      xdg.configFile."hypr/hyprland.conf".text = ''
        # This file has been auto-generated.

        ${concatStringsSep "\n" (map (kb: "bind${concatStringsSep "" kb.flags} = ${concatStringsSep " " kb.mods}, ${kb.key}, ${kb.dispatcher}${
            if (elem "m" kb.flags) # Mouse binds take one argument less
            then ""
            else ", ${kb.params}"
          }")
          cfg.config.keybindings.binds)}

        ${concatStringsSep "\n\n" (map (sm: ''
            bind${concatStringsSep "" sm.enterBind.flags} = ${concatStringsSep " " sm.enterBind.mods}, ${sm.enterBind.key}, submap, ${sm.name}
            submap = ${sm.name}

            ${concatStringsSep "\n" (map (kb: "bind${concatStringsSep "" kb.flags} = ${concatStringsSep " " kb.mods}, ${kb.key}, ${kb.dispatcher}${
                if (elem "m" kb.flags) # Mouse binds take one argument less
                then ""
                else ", ${kb.params}"
              }")
              sm.binds)}

            bind${concatStringsSep "" sm.exitBind.flags} = ${concatStringsSep " " sm.exitBind.mods}, ${sm.exitBind.key}, submap, reset
            submap = reset
          '')
          cfg.config.keybindings.submaps)}

        ${concatStringsSep "\n" (map (x: "exec-once = " + x) cfg.config.execOnce)}

        ${concatStringsSep "\n" (map (x: "env = " + x) cfg.config.env)}

        general {
            border_size = ${toString cfg.config.general.borderSize}
            no_border_on_floating = ${boolToString cfg.config.general.noBorderOnFloating}
            gaps_in = ${toString cfg.config.general.gapsIn}
            gaps_out = ${toString cfg.config.general.gapsOut}
            gaps_workspaces = ${toString cfg.config.general.gapsWorkspaces}
            col.inactive_border = ${cfg.config.general.col.inactiveBorder}
            col.active_border = ${cfg.config.general.col.activeBorder}
            col.nogroup_border = ${cfg.config.general.col.nogroupBorder}
            col.nogroup_border_active = ${cfg.config.general.col.nogroupBorderActive}
            layout = ${cfg.config.general.layout}
            no_focus_fallback = ${boolToString cfg.config.general.noFocusFallback}
            resize_on_border = ${boolToString cfg.config.general.resizeOnBorder}
            extend_border_grab_area = ${toString cfg.config.general.extendBorderGrabArea}
            hover_icon_on_border = ${boolToString cfg.config.general.hoverIconOnBorder}
            allow_tearing = ${boolToString cfg.config.general.allowTearing}
            resize_corner = ${toString cfg.config.general.resizeCorner}

            snap {
                enabled = ${boolToString cfg.config.general.snap.enabled}
                window_gap = ${toString cfg.config.general.snap.windowGap}
                monitor_gap = ${toString cfg.config.general.snap.monitorGap}
                border_overlap = ${boolToString cfg.config.general.snap.borderOverlap}
            }
        }

        decoration {
            rounding = ${toString cfg.config.decoration.rounding}
            rounding_power = ${toString cfg.config.decoration.roundingPower}
            active_opacity = ${toString cfg.config.decoration.activeOpacity}
            inactive_opacity = ${toString cfg.config.decoration.inactiveOpacity}
            fullscreen_opacity = ${toString cfg.config.decoration.fullscreenOpacity}
            dim_inactive = ${boolToString cfg.config.decoration.dimInactive}
            dim_strength = ${toString cfg.config.decoration.dimStrength}
            dim_special = ${toString cfg.config.decoration.dimSpecial}
            dim_around = ${toString cfg.config.decoration.dimAround}
            screen_shader = ${toString cfg.config.decoration.screenShader}
            border_part_of_window = ${boolToString cfg.config.decoration.borderPartOfWindow}

            blur {
                enabled = ${boolToString cfg.config.decoration.blur.enabled}
                size = ${toString cfg.config.decoration.blur.size}
                passes = ${toString cfg.config.decoration.blur.passes}
                ignore_opacity = ${boolToString cfg.config.decoration.blur.ignoreOpacity}
                new_optimizations = ${boolToString cfg.config.decoration.blur.newOptimizations}
                xray = ${boolToString cfg.config.decoration.blur.xray}
                noise = ${toString cfg.config.decoration.blur.noise}
                contrast = ${toString cfg.config.decoration.blur.contrast}
                brightness = ${toString cfg.config.decoration.blur.brightness}
                vibrancy = ${toString cfg.config.decoration.blur.vibrancy}
                vibrancy_darkness = ${toString cfg.config.decoration.blur.vibrancyDarkness}
                special = ${boolToString cfg.config.decoration.blur.special}
                popups = ${boolToString cfg.config.decoration.blur.popups}
                popups_ignorealpha = ${toString cfg.config.decoration.blur.popupsIgnorealpha}
                input_methods = ${boolToString cfg.config.decoration.blur.inputMethods}
                input_methods_ignorealpha = ${toString cfg.config.decoration.blur.inputMethodsIgnorealpha}
            }

            shadow {
                enabled = ${boolToString cfg.config.decoration.shadow.enabled}
                range = ${toString cfg.config.decoration.shadow.range}
                render_power = ${toString cfg.config.decoration.shadow.renderPower}
                sharp = ${boolToString cfg.config.decoration.shadow.sharp}
                ignore_window = ${boolToString cfg.config.decoration.shadow.ignoreWindow}
                color = ${toString cfg.config.decoration.shadow.color}
                ${
          if (cfg.config.decoration.shadow.colorInactive == null)
          then ""
          else "color_inactive = ${toString cfg.config.decoration.shadow.colorInactive}"
        }
                offset = ${toString cfg.config.decoration.shadow.offset.x} ${toString cfg.config.decoration.shadow.offset.y}
                scale = ${toString cfg.config.decoration.shadow.scale}
            }
        }

        animations {
            enabled = ${boolToString cfg.config.animations.enabled}
            workspace_wraparound = ${boolToString cfg.config.animations.workspaceWraparound}

            ${concatStringsSep "\n    " (map (bez: "bezier = ${bez.name}, ${floatToString bez.startX}, ${floatToString bez.startY}, ${floatToString bez.endX}, ${floatToString bez.endY}") cfg.config.animations.beziers)}

            ${concatStringsSep "\n    " (map (anim: "animation = ${anim.name}, ${toString anim.on}, ${floatToString anim.speed}, ${anim.curve}, ${anim.style}") cfg.config.animations.animations)}
        }

        input {
            kb_model = ${toString cfg.config.input.kbModel}
            kb_layout = ${toString cfg.config.input.kbLayout}
            kb_variant = ${toString cfg.config.input.kbVariant}
            kb_options = ${toString cfg.config.input.kbOptions}
            kb_rules = ${toString cfg.config.input.kbRules}
            kb_file = ${toString cfg.config.input.kbFile}
            numlock_by_default = ${boolToString cfg.config.input.numlockByDefault}
            resolve_binds_by_sym = ${boolToString cfg.config.input.resolveBindsBySym}
            repeat_rate = ${toString cfg.config.input.repeatRate}
            repeat_delay = ${toString cfg.config.input.repeatDelay}
            sensitivity = ${toString cfg.config.input.sensitivity}
            accel_profile = ${toString cfg.config.input.accelProfile}
            force_no_accel = ${boolToString cfg.config.input.forceNoAccel}
            left_handed = ${boolToString cfg.config.input.leftHanded}
            scroll_points = ${toString cfg.config.input.scrollPoints}
            scroll_method = ${toString cfg.config.input.scrollMethod}
            scroll_button = ${toString cfg.config.input.scrollButton}
            scroll_button_lock = ${boolToString cfg.config.input.scrollButtonLock}
            scroll_factor = ${toString cfg.config.input.scrollFactor}
            natural_scroll = ${boolToString cfg.config.input.naturalScroll}
            follow_mouse = ${toString cfg.config.input.followMouse}
            follow_mouse_threshold = ${toString cfg.config.input.followMouseThreshold}
            focus_on_close = ${toString cfg.config.input.focusOnClose}
            mouse_refocus = ${boolToString cfg.config.input.mouseRefocus}
            float_switch_override_focus = ${toString cfg.config.input.floatSwitchOverrideFocus}
            special_fallthrough = ${boolToString cfg.config.input.specialFallthrough}
            off_window_axis_events = ${toString cfg.config.input.offWindowAxisEvents}
            emulate_discrete_scroll = ${toString cfg.config.input.emulateDiscreteScroll}

            touchpad {
                disable_while_typing = ${boolToString cfg.config.input.touchpad.disableWhileTyping}
                natural_scroll = ${boolToString cfg.config.input.touchpad.naturalScroll}
                scroll_factor = ${toString cfg.config.input.touchpad.scrollFactor}
                middle_button_emulation = ${boolToString cfg.config.input.touchpad.middleButtonEmulation}
                tap_button_map = ${toString cfg.config.input.touchpad.tapButtonMap}
                clickfinger_behavior = ${boolToString cfg.config.input.touchpad.clickfingerBehavior}
                tap-to-click = ${boolToString cfg.config.input.touchpad.tapToClick}
                drag_lock = ${toString cfg.config.input.touchpad.dragLock}
                tap-and-drag = ${toString cfg.config.input.touchpad.tapAndDrag}
                flip_x = ${boolToString cfg.config.input.touchpad.flipX}
                flip_y = ${boolToString cfg.config.input.touchpad.flipY}
            }

            touchdevice {
                transform = ${toString cfg.config.input.touchdevice.transform}
                output = ${toString cfg.config.input.touchdevice.output}
                enabled = ${boolToString cfg.config.input.touchdevice.enabled}
            }

            tablet {
                transform = ${toString cfg.config.input.tablet.transform}
                output = ${toString cfg.config.input.tablet.output}
                region_position = ${toString cfg.config.input.tablet.regionPosition.x} ${toString cfg.config.input.tablet.regionPosition.y}
                absolute_region_position = ${boolToString cfg.config.input.tablet.absoluteRegionPosition}
                region_size = ${toString cfg.config.input.tablet.regionSize.x} ${toString cfg.config.input.tablet.regionSize.y}
                relative_input = ${boolToString cfg.config.input.tablet.relativeInput}
                left_handed = ${boolToString cfg.config.input.tablet.leftHanded}
                active_area_size = ${toString cfg.config.input.tablet.activeAreaSize.x} ${toString cfg.config.input.tablet.activeAreaSize.y}
                active_area_position = ${toString cfg.config.input.tablet.activeAreaPosition.x} ${toString cfg.config.input.tablet.activeAreaPosition.y}
            }
        }

        gestures {
            workspace_swipe = ${boolToString cfg.config.gestures.workspaceSwipe}
            workspace_swipe_fingers = ${toString cfg.config.gestures.workspaceSwipeFingers}
            workspace_swipe_min_fingers = ${boolToString cfg.config.gestures.workspaceSwipeMinFingers}
            workspace_swipe_distance = ${toString cfg.config.gestures.workspaceSwipeDistance}
            workspace_swipe_touch = ${boolToString cfg.config.gestures.workspaceSwipeTouch}
            workspace_swipe_invert = ${boolToString cfg.config.gestures.workspaceSwipeInvert}
            workspace_swipe_touch_invert = ${boolToString cfg.config.gestures.workspaceSwipeTouchInvert}
            workspace_swipe_min_speed_to_force = ${toString cfg.config.gestures.workspaceSwipeMinSpeedToForce}
            workspace_swipe_cancel_ratio = ${floatToString cfg.config.gestures.workspaceSwipeCancelRatio}
            workspace_swipe_create_new = ${boolToString cfg.config.gestures.workspaceSwipeCreateNew}
            workspace_swipe_direction_lock = ${boolToString cfg.config.gestures.workspaceSwipeDirectionLock}
            workspace_swipe_direction_lock_threshold = ${toString cfg.config.gestures.workspaceSwipeDirectionLockThreshold}
            workspace_swipe_forever = ${boolToString cfg.config.gestures.workspaceSwipeForever}
            workspace_swipe_use_r = ${boolToString cfg.config.gestures.workspaceSwipeUseR}
        }

        group {
            auto_group = ${boolToString cfg.config.group.autoGroup}
            insert_after_current = ${boolToString cfg.config.group.insertAfterCurrent}
            focus_removed_window = ${boolToString cfg.config.group.focusRemovedWindow}
            drag_into_group = ${toString cfg.config.group.dragIntoGroup}
            merge_groups_on_drag = ${boolToString cfg.config.group.mergeGroupsOnDrag}
            merge_groups_on_groupbar = ${boolToString cfg.config.group.mergeGroupsOnGroupbar}
            merge_floated_into_tiled_on_groupbar = ${boolToString cfg.config.group.mergeFloatedIntoTiledOnGroupbar}
            group_on_movetoworkspace = ${boolToString cfg.config.group.groupOnMovetoworkspace}
            col.border_active = ${toString cfg.config.group.col.borderActive}
            col.border_inactive = ${toString cfg.config.group.col.borderInactive}
            col.border_locked_active = ${toString cfg.config.group.col.borderLockedActive}
            col.border_locked_inactive = ${toString cfg.config.group.col.borderLockedInactive}

            groupbar {
                enabled = ${boolToString cfg.config.group.groupbar.enabled}
                font_family = ${toString cfg.config.group.groupbar.fontFamily}
                font_size = ${toString cfg.config.group.groupbar.fontSize}
                font_weight_active = ${toString cfg.config.group.groupbar.fontWeightActive}
                font_weight_inactive = ${toString cfg.config.group.groupbar.fontWeightInactive}
                gradients = ${boolToString cfg.config.group.groupbar.gradients}
                height = ${toString cfg.config.group.groupbar.height}
                indicator_gap = ${toString cfg.config.group.groupbar.indicatorGap}
                indicator_height = ${toString cfg.config.group.groupbar.indicatorHeight}
                stacked = ${boolToString cfg.config.group.groupbar.stacked}
                priority = ${toString cfg.config.group.groupbar.priority}
                render_titles = ${boolToString cfg.config.group.groupbar.renderTitles}
                text_offset = ${toString cfg.config.group.groupbar.textOffset}
                scrolling = ${boolToString cfg.config.group.groupbar.scrolling}
                rounding = ${toString cfg.config.group.groupbar.rounding}
                gradient_rounding = ${toString cfg.config.group.groupbar.gradientRounding}
                round_only_edges = ${boolToString cfg.config.group.groupbar.roundOnlyEdges}
                gradient_round_only_edges = ${boolToString cfg.config.group.groupbar.gradientRoundOnlyEdges}
                text_color = ${toString cfg.config.group.groupbar.textColor}
                col.active = ${toString cfg.config.group.groupbar.col.active}
                col.inactive = ${toString cfg.config.group.groupbar.col.inactive}
                col.locked_active = ${toString cfg.config.group.groupbar.col.lockedActive}
                col.locked_inactive = ${toString cfg.config.group.groupbar.col.lockedInactive}
                gaps_in = ${toString cfg.config.group.groupbar.gapsIn}
                gaps_out = ${toString cfg.config.group.groupbar.gapsOut}
                keep_upper_gap = ${boolToString cfg.config.group.groupbar.keepUpperGap}
            }
        }

        misc {
            disable_hyprland_logo = ${boolToString cfg.config.misc.disableHyprlandLogo}
            disable_splash_rendering = ${boolToString cfg.config.misc.disableSplashRendering}
            col.splash = ${toString cfg.config.misc.col.splash}
            font_family = ${toString cfg.config.misc.fontFamily}
            splash_font_family = ${toString cfg.config.misc.splashFontFamily}
            force_default_wallpaper = ${toString cfg.config.misc.forceDefaultWallpaper}
            vfr = ${toString cfg.config.misc.vfr}
            vrr = ${toString cfg.config.misc.vrr}
            mouse_move_enables_dpms = ${boolToString cfg.config.misc.mouseMoveEnablesDPMS}
            key_press_enables_dpms = ${boolToString cfg.config.misc.keyPressEnablesDPMS}
            always_follow_on_dnd = ${boolToString cfg.config.misc.alwaysFollowOnDnd}
            layers_hog_keyboard_focus = ${boolToString cfg.config.misc.layersHogKeyboardFocus}
            animate_manual_resizes = ${boolToString cfg.config.misc.animateManualResizes}
            animate_mouse_windowdragging = ${boolToString cfg.config.misc.animateMouseWindowdragging}
            disable_autoreload = ${boolToString cfg.config.misc.disableAutoreload}
            enable_swallow = ${boolToString cfg.config.misc.enableSwallow}
            swallow_regex = ${toString cfg.config.misc.swallowRegex}
            swallow_exception_regex = ${toString cfg.config.misc.swallowExceptionRegex}
            focus_on_activate = ${boolToString cfg.config.misc.focusOnActivate}
            mouse_move_focuses_monitor = ${boolToString cfg.config.misc.mouseMoveFocusesMonitor}
            allow_session_lock_restore = ${boolToString cfg.config.misc.allowSessionLockRestore}
            background_color = ${toString cfg.config.misc.backgroundColor}
            close_special_on_empty = ${boolToString cfg.config.misc.closeSpecialOnEmpty}
            new_window_takes_over_fullscreen = ${toString cfg.config.misc.newWindowTakesOverFullscreen}
            exit_window_retains_fullscreen = ${boolToString cfg.config.misc.exitWindowRetainsFullscreen}
            initial_workspace_tracking = ${toString cfg.config.misc.initialWorkspaceTracking}
            middle_click_paste = ${boolToString cfg.config.misc.middleClickPaste}
            render_unfocused_fps = ${toString cfg.config.misc.renderUnfocusedFps}
            disable_xdg_env_checks = ${boolToString cfg.config.misc.disableXdgEnvChecks}
            disable_hyprland_qtutils_check = ${boolToString cfg.config.misc.disableHyprlandQtutilsCheck}
            lockdead_screen_delay = ${toString cfg.config.misc.lockdeadScreenDelay}
            enable_anr_dialog = ${boolToString cfg.config.misc.enableAnrDialog}
            anr_missed_pings = ${toString cfg.config.misc.anrMissedPings}
        }

        binds {
            pass_mouse_when_bound = ${boolToString cfg.config.binds.passMouseWhenBound}
            scroll_event_delay = ${toString cfg.config.binds.scrollEventDelay}
            workspace_back_and_forth = ${boolToString cfg.config.binds.workspaceBackAndForth}
            hide_special_on_workspace_change = ${boolToString cfg.config.binds.hideSpecialOnWorkspaceChange}
            allow_workspace_cycles = ${boolToString cfg.config.binds.allowWorkspaceCycles}
            workspace_center_on = ${toString cfg.config.binds.workspaceCenterOn}
            focus_preferred_method = ${toString cfg.config.binds.focusPreferredMethod}
            ignore_group_lock = ${boolToString cfg.config.binds.ignoreGroupLock}
            movefocus_cycles_fullscreen = ${boolToString cfg.config.binds.movefocusCyclesFullscreen}
            movefocus_cycles_groupfirst = ${boolToString cfg.config.binds.movefocusCyclesGroupfirst}
            disable_keybind_grabbing = ${boolToString cfg.config.binds.disableKeybindGrabbing}
            window_direction_monitor_fallback = ${boolToString cfg.config.binds.windowDirectionMonitorFallback}
            allow_pin_fullscreen = ${boolToString cfg.config.binds.allowPinFullscreen}
            drag_threshold = ${toString cfg.config.binds.dragThreshold}
        }

        xwayland {
            enabled = ${boolToString cfg.config.xwayland.enabled}
            use_nearest_neighbor = ${boolToString cfg.config.xwayland.useNearestNeighbor}
            force_zero_scaling = ${boolToString cfg.config.xwayland.forceZeroScaling}
            create_abstract_socket = ${boolToString cfg.config.xwayland.createAbstractSocket}
        }

        opengl {
            nvidia_anti_flicker = ${boolToString cfg.config.opengl.nvidiaAntiFlicker}
        }

        render {
            direct_scanout = ${toString cfg.config.render.directScanout}
            expand_undersized_textures = ${boolToString cfg.config.render.expandUndersizedTextures}
            xp_mode = ${boolToString cfg.config.render.xpMode}
            ctm_animation = ${toString cfg.config.render.ctmAnimation}
            cm_fs_passthrough = ${toString cfg.config.render.cmFsPassthrough}
            cm_enabled = ${boolToString cfg.config.render.cmEnabled}
            send_content_type = ${boolToString cfg.config.render.sendContentType}
        }

        cursor {
            sync_gsettings_theme = ${boolToString cfg.config.cursor.syncGsettingsTheme}
            no_hardware_cursors = ${toString cfg.config.cursor.noHardwareCursors}
            no_break_fs_vrr = ${toString cfg.config.cursor.noBreakFsVrr}
            min_refresh_rate = ${toString cfg.config.cursor.minRefreshRate}
            hotspot_padding = ${toString cfg.config.cursor.hotspotPadding}
            inactive_timeout = ${toString cfg.config.cursor.inactiveTimeout}
            no_warps = ${boolToString cfg.config.cursor.noWarps}
            persistent_warps = ${boolToString cfg.config.cursor.persistentWarps}
            warp_on_change_workspace = ${toString cfg.config.cursor.warpOnChangeWorkspace}
            warp_on_toggle_special = ${toString cfg.config.cursor.warpOnToggleSpecial}
            default_monitor = ${toString cfg.config.cursor.defaultMonitor}
            zoom_factor = ${toString cfg.config.cursor.zoomFactor}
            zoom_rigid = ${boolToString cfg.config.cursor.zoomRigid}
            enable_hyprcursor = ${boolToString cfg.config.cursor.enableHyprcursor}
            hide_on_key_press = ${boolToString cfg.config.cursor.hideOnKeyPress}
            hide_on_touch = ${boolToString cfg.config.cursor.hideOnTouch}
            use_cpu_buffer = ${toString cfg.config.cursor.useCpuBuffer}
            warp_back_after_non_mouse_input = ${boolToString cfg.config.cursor.warpBackAfterNonMouseInput}
        }

        ecosystem {
            no_update_news = ${boolToString cfg.config.ecosystem.noUpdateNews}
            no_donation_nag = ${boolToString cfg.config.ecosystem.noDonationNag}
            enforce_permissions = ${boolToString cfg.config.ecosystem.enforcePermissions}
        }

        dwindle {
            pseudotile = ${boolToString cfg.config.dwindle.pseudotile}
            preserve_split = ${boolToString cfg.config.dwindle.preserveSplit}
        }

        master {
            new_status = ${toString cfg.config.master.newStatus}
        }

        ${concatStringsSep "\n" (map (mon: "monitor = ${mon.output}, ${mon.resolution}@${mon.refreshRate}, ${toString mon.x}x${toString mon.y}, ${floatToString mon.scale}, transform, ${toString mon.transform}") cfg.config.monitors.displays)}

        ${
          if cfg.config.monitors.defaultMonitor
          then "monitor = ,preferred, auto, auto"
          else ""
        }

        ${concatStringsSep "\n" (map (wr: "windowrule = " + wr) cfg.config.windowrules)}

        ${concatStringsSep "\n" (map (ws: "workspace = " + ws) cfg.config.workspaces)}

        ${
          concatStringsSep "\n" (
            if cfg.config.monitors.bindWorkspaces == "interlaced"
            then (map (x: "workspace = ${toString (x + 1)}, persistent:true, monitor:${(elemAt cfg.config.monitors.displays (x - ((length cfg.config.monitors.displays) * (x / (length cfg.config.monitors.displays))))).output}") (genList (x: x) 10))
            else []
          )
        }
      '';

      programs.waybar = {
        enable = true;

        settings = let
          outputMap = location: (
            remove null (
              map (disp:
                if (disp.bar == location)
                then disp.output
                else null)
              cfg.config.monitors.displays
            )
          );
        in {
          topBar =
            recursiveUpdate
            {
              layer = "top";
              position = "top";
              output = outputMap "top";

              modules-left = cfg.config.waybar.layout.horizontal.left;
              modules-center = cfg.config.waybar.layout.horizontal.center;
              modules-right = cfg.config.waybar.layout.horizontal.right;
            } (recursiveUpdate cfg.config.waybar.modules cfg.config.waybar.formats.horizontal);

          bottomBar =
            recursiveUpdate
            {
              layer = "top";
              position = "bottom";
              output = outputMap "bottom";

              modules-left = cfg.config.waybar.layout.horizontal.left;
              modules-center = cfg.config.waybar.layout.horizontal.center;
              modules-right = cfg.config.waybar.layout.horizontal.right;
            } (recursiveUpdate cfg.config.waybar.modules cfg.config.waybar.formats.horizontal);

          rightBar =
            recursiveUpdate
            {
              layer = "top";
              position = "right";
              output = outputMap "right";

              modules-left = cfg.config.waybar.layout.vertical.left;
              modules-center = cfg.config.waybar.layout.vertical.center;
              modules-right = cfg.config.waybar.layout.vertical.right;
            } (recursiveUpdate cfg.config.waybar.modules cfg.config.waybar.formats.vertical);

          leftBar =
            recursiveUpdate
            {
              layer = "top";
              position = "left";
              output = outputMap "left";

              modules-left = cfg.config.waybar.layout.vertical.left;
              modules-center = cfg.config.waybar.layout.vertical.center;
              modules-right = cfg.config.waybar.layout.vertical.right;
            } (recursiveUpdate cfg.config.waybar.modules cfg.config.waybar.formats.vertical);
        };
      };
      xdg.configFile."waybar/style.css".source = ./config/waybar/style.css;
    };
  };
}
