#
# Our system configuration, as a Nix flake.
# Now with bonus packages!
#
# vim: et:ts=2:sw=2:
#
{
  #
  # The sources we depend on.
  #
  inputs = {
    # Core and utilities.
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";

    # Not nix -- lix!
    lix.url = "git+https://git@git.lix.systems/lix-project/lix";

    # Home-manager.
    home-manager = {
      url = "github:nix-community/home-manager/master";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # Styling!
    stylix = {
      url = "github:danth/stylix";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # Attic cache.
    attic = {
      url = "github:zhaofengli/attic";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # Talon voice.
    talon = {
      url = "github:nix-community/talon-nix/master";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # For our phone.
    nix-on-droid = {
      url = "github:nix-community/nix-on-droid/release-24.05";
      inputs.nixpkgs.follows = "nixpkgs";
      inputs.home-manager.follows = "home-manager";
    };

    # Flakes for packages.
    nil.url = "github:oxalica/nil";
    agenix.url = "github:ryantm/agenix";
    openxc7.url = "github:openXC7/toolchain-nix";
    niri.url = "github:sodiboo/niri-flake";
    waveforms.url = "github:liff/waveforms-flake";
    esp-dev.url = "github:mirrexagon/nixpkgs-esp-dev";

    # Flatpack support
    nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=v0.4.1";

    # Various system type support.
    darwin.url = "github:lnl7/nix-darwin/master";
    darwin.inputs.nixpkgs.follows = "nixpkgs";
    nix-hardware.url = "github:nixos/nixos-hardware";
  };

  #
  # Package definitions for each of our various types.
  # Used in the outputs section.
  #

  #
  # Our various products; mostly machine configurations.
  #
  outputs =
    {
      self,
      nixpkgs,
      flake-utils,
      home-manager,
      openxc7,
      darwin,
      agenix,
      nil,
      lix,
      niri,
      stylix,
      waveforms,
      esp-dev,
      attic,
      nix-flatpak,
      nix-on-droid,
      nixos-hardware,
      talon,
      ...
    }:

		#
		# Include our package repository.
		#
    (import ./packages.nix) {
      inherit flake-utils nixpkgs;
      deprekages = self.outputs.packages;
    }

    #
    # Our per-machine configurations.
    # Appeneded to the output of the packages generated by eachDefaultSystem.
    #
    // rec {

      #
      # Helpers.
      #

      # Common to all machines, Linux or macOS.
      commonModuleSet = [
        ./nixos/packages

        ./nixos/dotfiles

        ./nixos/configs/stylix
        ./nixos/configs/lix.nix
        ./nixos/configs/nix.nix
        ./nixos/configs/calendar.nix
        ./nixos/configs/syncthing.nix
        ./nixos/configs/include-conf.nix
        ./nixos/configs/flake-registry.nix
        ./nixos/configs/storage-optimization.nix

        ./nixos/services/tailscale.nix

        home-manager.nixosModules.home-manager
      ];

      # Modules for all linux machines.
      linuxModuleSet = [
        ./nixos/configuration.linux.nix

        ./nixos/configs/udev.nix
        ./nixos/configs/printing.nix
        ./nixos/configs/virt-host.nix
        ./nixos/configs/mount-rsync-kate.nix
        ./nixos/configs/mount-fastmail-tmllc.nix

        ./nixos/services/taskwarrior.nix

        ./nixos/overlays/fixup-canon.nix

        #
      ];

      # Modules for Linux machines with Wayland GUIs.
      linuxGuiModuleSet = [
        waveforms.nixosModule
        nix-flatpak.nixosModules.nix-flatpak

        ./nixos/dotfiles/vscode.nix

        ./nixos/packages/gui.nix
        ./nixos/packages/wine.nix
        ./nixos/packages/flatpak.nix
        ./nixos/packages/proprietary.nix

        ./nixos/configs/gui
        ./nixos/configs/flatpak.nix
        ./nixos/configs/fonts-linux.nix
        ./nixos/configs/music-server.nix

        #./nixos/overlays/fixup-signal
        ./nixos/overlays/fixup-imhex.nix
        ./nixos/overlays/customize-gajim
        ./nixos/overlays/sddm-no-vnc.nix
        ./nixos/overlays/fixup-armcord.nix
        ./nixos/overlays/jd-gui-wayland.nix
        ./nixos/overlays/fixup-mattermost.nix
        ./nixos/overlays/yubikey-touch-shitpost
        ./nixos/overlays/add-depends-calibre.nix
      ];

      # Modules for all darwin machines.
      darwinModuleSet = [
        ./nixos/configuration.darwin.nix

        ./nixos/packages/homebrew.nix
        ./nixos/packages/appstore.nix

        ./nixos/configs/fonts-darwin.nix
        ./nixos/configs/autosetup-darwin-aarch64.nix
      ];

      # Modules for offline linux machines.
      linuxOfflineModuleSet = [
        ./nixos/packages/offline.nix

        ./nixos/configs/waydroid.nix
      ];

      # Helper functions for creating modules in the defintions below.
      darwinModules = extraModules: commonModuleSet ++ darwinModuleSet ++ extraModules;
      linuxModules = extraModules: commonModuleSet ++ linuxModuleSet ++ extraModules;
      linuxGuiModules = extraModules: linuxModules (linuxGuiModuleSet ++ extraModules);
      linuxOfflineGuiModules = extraModules: linuxGuiModules (linuxOfflineModuleSet ++ extraModules);

      # Helper that populates all of our special arguments.
      mkSpecialArgsGeneric = (
        system: is-hm-standalone: is-droid: {
          inherit
            nixpkgs
            stylix
            is-hm-standalone
            is-droid
            ;

          niri = niri.outputs;
          nil = nil.outputs.packages.${system};
          deprekages = self.outputs.packages.${system};
          agenix = agenix.outputs.packages.${system};
          openxc7 = openxc7.outputs.packages.${system};
          attic = attic.outputs.packages.${system};
          esp-dev = esp-dev.outputs.packages.${system};
          lix = lix.outputs.packages.${system};
          talon = talon.outputs.packages.${system};

          # Helper to convert hm modules into NixOS or nix-on-droid modules.
          callHm = module: (specialArgs: (import module) specialArgs);
          normalizeModule =
            if is-hm-standalone then
              (module: module)
            else
              (
                if is-droid then
                  (
                    module:
                    (
                      { deprekages, ... }:
                      {
                        home-manager.config =
                          { pkgs, ... }@specialArgs: (import module) (specialArgs // { inherit deprekages; });
                      }
                    )
                  )
                else
                  (
                    module:
                    (
                      { deprekages, ... }:
                      {
                        home-manager.users.deprekated =
                          { pkgs, ... }@specialArgs: (import module) (specialArgs // { inherit deprekages; });
                      }
                    )
                  )
              );
        }
      );

      # Generic mkSpecialArgs for NixOS.
      mkSpecialArgs = system: (mkSpecialArgsGeneric system false false);

      # Specialized mkSpecialArgs for standalone home-manager.
      mkSpecialArgsHm = system: pkgs: ((mkSpecialArgsGeneric system true false) // { inherit pkgs; });
      mkSpecialArgsDroid = system: pkgs: ((mkSpecialArgsGeneric system false true) // { inherit pkgs; });

      #
      # Hosts!
      #

      # Trailblazer (main desktop).
      nixosConfigurations.trailblazer = nixpkgs.lib.nixosSystem rec {
        system = "x86_64-linux";
        specialArgs = mkSpecialArgs system;
        modules = linuxOfflineGuiModules [
          ./nixos/hosts/trailblazer
          ./nixos/configs/vmware.nix
        ];
      };

      # Valere (powerful laptop).
      nixosConfigurations.valere = nixpkgs.lib.nixosSystem rec {
        system = "x86_64-linux";
        specialArgs = mkSpecialArgs system;

        modules = linuxOfflineGuiModules [
          ./nixos/hosts/valere
          ./nixos/configs/steam.nix
          ./nixos/configs/vmware.nix
          ./nixos/configs/power-saving.nix
        ];
      };


      # Miko (mid-tier t2+x64 laptop that's nice and smol).
      nixosConfigurations.miko = nixpkgs.lib.nixosSystem rec {
        system = "x86_64-linux";
        specialArgs = mkSpecialArgs system;

        modules = linuxOfflineGuiModules [
          ./nixos/hosts/miko.nix

          ./nixos/configs/power-saving.nix
          ./nixos/configs/looking-glass.nix

          nixos-hardware.nixosModules.apple-t2
        ];
      };

      # Hinata (travel laptop).
      nixosConfigurations.hinata = nixpkgs.lib.nixosSystem rec {
        system = "x86_64-linux";
        specialArgs = mkSpecialArgs system;

        modules = linuxOfflineGuiModules [
          ./nixos/hosts/hinata.nix
          ./nixos/configs/vmware.nix
          ./nixos/configs/cellular.nix
          ./nixos/configs/power-saving.nix
        ];
      };

      # Veth (purse laptop).
      nixosConfigurations.veth = nixpkgs.lib.nixosSystem rec {
        system = "x86_64-linux";
        specialArgs = mkSpecialArgs system;

        modules = linuxGuiModules [
          ./nixos/hosts/veth
          ./nixos/configs/power-saving.nix
        ];
      };

      # Komashi (TMLLC T16 gen2).
      nixosConfigurations.komashi = nixpkgs.lib.nixosSystem rec {
        system = "x86_64-linux";
        specialArgs = mkSpecialArgs system;

        modules = linuxOfflineGuiModules [
          ./nixos/hosts/komashi

          ./nixos/configs/vmware.nix
          ./nixos/configs/cellular.nix
          ./nixos/configs/nfc-kernel.nix
          ./nixos/configs/power-saving.nix
        ];
      };

      #  Utol (TMLLC T14 Gen1)
      nixosConfigurations.utol = nixpkgs.lib.nixosSystem rec {
        system = "x86_64-linux";
        specialArgs = mkSpecialArgs system;

        modules = linuxGuiModules [
          ./nixos/hosts/utol

          ./nixos/configs/vmware.nix
          ./nixos/configs/cellular.nix
          ./nixos/configs/power-saving.nix

          ./nixos/packages/offline.nix
        ];
      };

      #  Aigis (aarch64-linux, apple-silicon, build machine).
      nixosConfigurations.aigis = nixpkgs.lib.nixosSystem rec {
        system = "aarch64-linux";
        specialArgs = mkSpecialArgs system;

        modules = linuxGuiModules [
          ./nixos/hosts/aigis.nix

          ./nixos/configs/power-saving.nix
        ];
      };

      # Nomon (TMLLC aarch64-linux, broadcom-silicon, test machine).
      nixosConfigurations.nomon = nixpkgs.lib.nixosSystem rec {
        system = "aarch64-linux";
        specialArgs = mkSpecialArgs system;

        modules = linuxModules [ ./nixos/hosts/salas.nix ];
      };

      # Roshar (TMLLC aarch64-darwin, apple-silicon build machine).
      darwinConfigurations.roshar = darwin.lib.darwinSystem rec {
        system = "aarch64-darwin";
        specialArgs = mkSpecialArgs system;

        modules = darwinModules [ ./nixos/hosts/roshar.nix ];
      };

      # Mako (x86_64-darwin, apple-silicon build machine).
      darwinConfigurations.mako = darwin.lib.darwinSystem rec {
        system = "x86_64-darwin";
        specialArgs = mkSpecialArgs system;

        modules = darwinModules [ ./nixos/hosts/mako.nix ];
      };

      # Design, our phone.
      nixOnDroidConfigurations.design = nix-on-droid.lib.nixOnDroidConfiguration rec {
        pkgs = import nixpkgs {
          system = "aarch64-linux";
          config.allowUnfree = true;
          config.permittedInsecurePackages = [ "olm-3.2.16" ];
        };
        extraSpecialArgs = mkSpecialArgsDroid "aarch64-linux" pkgs;

        modules = [
          ./nixos/hosts/design.nix
          ./nixos/configuration.droid.nix

          ./nixos/dotfiles/droid.nix

          ./nixos/configs/nix.droid.nix
          ./nixos/configs/droid-gui.nix
          ./nixos/configs/flake-registry.nix

          ./nixos/packages/droid.nix
          ./nixos/packages/offline.droid.nix
          ./nixos/packages/gui.droid.nix
        ];

      };

    };
}
