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

with lib;

let

  # monitor options

  monitorOpts = self: {
    options = {

      name = mkOption {
        type = types.str;
        description = "Name of the monitor.";
      };

      scale = mkOption {
        type = types.float;
        description = "Scaling factor of the monitor.";
        default = 1.0;
      };

    };
  };

  # base16 theme color options
  # https://github.com/chriskempson/base16/blob/main/styling.md

  base16Opts = self: {
    options = {

      name = mkOption {
        type = types.str;
        description = "Name of the theme";
      };

      author = mkOption {
        type = types.str;
        description = "Author of the theme";
      };

      base00 = mkOption {
        type = types.str;
        description = "Default Background.";
      };

      base01 = mkOption {
        type = types.str;
        description = "Lighter Background (Used for status bars, line number and folding marks).";
      };

      base02 = mkOption {
        type = types.str;
        description = "Selection Background.";
      };

      base03 = mkOption {
        type = types.str;
        description = "Comments, Invisibles, Line Highlighting.";
      };

      base04 = mkOption {
        type = types.str;
        description = "Dark Foreground (Used for status bars).";
      };

      base05 = mkOption {
        type = types.str;
        description = "Default Foreground, Caret, Delimiters, Operators.";
      };

      base06 = mkOption {
        type = types.str;
        description = "Light Foreground (Not often used).";
      };

      base07 = mkOption {
        type = types.str;
        description = "Light Background (Not often used).";
      };

      base08 = mkOption {
        type = types.str;
        description = "Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted.";
      };

      base09 = mkOption {
        type = types.str;
        description = "Integers, Boolean, Constants, XML Attributes, Markup Link Url.";
      };

      base0A = mkOption {
        type = types.str;
        description = "Classes, Markup Bold, Search Text Background.";
      };

      base0B = mkOption {
        type = types.str;
        description = "Strings, Inherited Class, Markup Code, Diff Inserted.";
      };

      base0C = mkOption {
        type = types.str;
        description = "Support, Regular Expressions, Escape Characters, Markup Quotes.";
      };

      base0D = mkOption {
        type = types.str;
        description = "Functions, Methods, Attribute IDs, Headings.";
      };

      base0E = mkOption {
        type = types.str;
        description = "Keywords, Storage, Selector, Markup Italic, Diff Changed.";
      };

      base0F = mkOption {
        type = types.str;
        description = "Deprecated, Opening/Closing Embedded Language Tags.";
      };

      accent = mkOption {
        type = types.str;
        description = "Accent color.";
        default = config.theme.colors.base0D;
      };

    };
  };

  stateVersion = "25.05";

in

{

  imports = [
    ./programs
    ./home
    ./system
  ];

  options = {

    #
    # System information
    #
    hostName = mkOption {
      type = types.str;
      description = "Hostname of the system.";
    };

    #
    # Primary user of the system
    #
    user = mkOption {
      type = types.str;
      description = "Primary user of the system";
    };
    fullName = mkOption {
      type = types.str;
      description = "Human readable name of the user";
    };
    email = mkOption {
      type = types.str;
      description = "Primary email of the user";
    };
    homePath = mkOption {
      type = types.path;
      description = "Home directory path of the user";
      default = builtins.toPath "/home/${config.user}";
    };
    dotfilesPath = mkOption {
      type = types.path;
      description = "Dotfiles path inside the users home dir";
      default = builtins.toPath "${config.homePath}/.config/nix";
    };

    #
    # Monitors of the system
    #
    monitors = mkOption {
      default = [];
      description = "Monitors of the system.";
      type = with types; listOf (submodule monitorOpts);
    };

    #
    # Theme of the system
    #
    theme = {
      colors = mkOption {
        type = with types; (submodule base16Opts);
        description = "Base16 color scheme";
        default = (import ./themes).catppuccin.mocha;
      };

      opacity = mkOption {
        type = types.float;
        description = "Window opacity.";
        default = 1.0;
      };

      # theme fonts
      font = {
        size = mkOption {
          type = types.int;
          description = "Theme primary font size.";
          default = 14;
        };

        regular = mkOption {
          type = types.str;
          description = "Regular system font.";
          default = "JetBrains Mono";
        };

        monospace = mkOption {
          type = types.str;
          description = "Monospace system font.";
          default = "monospace";
        };

        header = mkOption {
          type = types.str;
          description = "Header system font.";
          default = "JetBrains Mono ExtraBold";
        };

        icon = mkOption {
          type = types.str;
          description = "Icon system font.";
          default = "Font Awesome 6 Pro";
        };

      };

      borderWidth = mkOption {
        type = types.int;
        description = "Theme border width";
        default = 3;
      };

      outerRadius = mkOption {
        type = types.int;
        description = "Theme outer border radius.";
        default = 5;
      };

      innerRadius = mkOption {
        type = types.int;
        description = "Theme inner border radius.";
        default = 2;
      };

      outerGap = mkOption {
        type = types.int;
        description = "Theme outer gap/spacing.";
        default = 10;
      };

      innerGap = mkOption {
        type = types.int;
        description = "Theme inner gap/spacing.";
        default = 3;
      };

      wallpaper = mkOption {
        type = types.str;
        description = "Path to wallpaper image";
        default = "";
      };

      avatar = mkOption {
        type = types.str;
        description = "Path to avatar image";
        default = "";
      };
    };

    #
    # Default programs
    #
    default = {
      browser = mkOption {
        type = types.str;
        description = "Default browser launch command.";
      };
      appLauncher = mkOption {
        type = types.str;
        description = "Default application launcher launch command.";
      };
      lockScreen = mkOption {
        type = types.str;
        description = "Default lock screen launch command.";
      };
      terminal = mkOption {
        type = types.str;
        description = "Default terminal launch command.";
      };
    };

    #
    # Programs to auto start on launch
    #
    autoRun = mkOption {
      type = with types; listOf str;
      description = "List of programs to auto run in a graphical environment.";
      default = [];
    };

  };

  config = {
    # use system packages in home manager
    home-manager.useGlobalPkgs = true;

    # install user packages to /etc/profiles and not home directory
    home-manager.useUserPackages = true;

    # allow unfree packages
    nixpkgs.config.allowUnfree = true;

    # set state version
    home-manager.users.${config.user}.home.stateVersion = stateVersion;
    home-manager.users.root.home.stateVersion = stateVersion;
    system.stateVersion = stateVersion;
  };

}