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

# TODO:
# * [x] ~~generate a ssh key if not existing~~
# * [ ] prompt to make a token using 'gh'?
# * [ ] possibly store some key using nix-sops
# * [ ] automatically pull the repo on first boot
# * [ ] customize the shit out of vscode
# * [ ] don't ignore PDFs
# * [ ] fix the taskrunner
# * [ ] fix the markdown preview not opening when prompted
# * [ ] run the whole thing in a xvfb? should enable drawio and curv
# * [ ] switch to openvscode-server? https://sourcegraph.com/github.com/bendlas/nixos-config/-/blob/code-server.container.nix?L39%3A26=

# https://github.com/coder/code-server/discussions/4267

let
  hostName = config.networking.hostName;
  subdomain = "code-server.${config.networking.fqdn}";
  container-name = "code-server-pandoc-papers";
  container = config.containers.${container-name}.config;
in {
  networking.nat.enable = true;
  networking.nat.internalInterfaces = ["ve-+"];
  networking.nat.externalInterface = "eno1"; # TODO: can i make this automatic?
  #networking.nat.enableIPv6 = true;

  #imports = [
  #  "/home/pbsds/repos/nixpkgs-trees/containers-mkdir/nixos/modules/virtualisation/nixos-containers.nix"
  #];
  #disabledModules = [
  #  "virtualisation/nixos-containers.nix"
  #];

  # data can be destroyed with `nixos-container destroy code-server-pandoc`
  containers.${container-name} = {
    autoStart = true;

    # container has no network access
    privateNetwork = true;
    hostAddress  = "10.240.100.2";
    localAddress = "10.240.100.3";

    #nixpkgs = inputs.unstable;
    config = let host-cfg = config; in { config, pkgs, lib, ... }: {
      nixpkgs.overlays = host-cfg.nixpkgs.overlays;
      system.stateVersion = "22.11";
      nixpkgs.config.permittedInsecurePackages = [
        "nodejs-16.20.0" # TODO: remove
      ];

      imports = [ inputs.home-manager.nixosModule ];
      home-manager.useGlobalPkgs = true; # brrr
      home-manager.useUserPackages = true; # required, installs user packages to /etc instead of ~/.nix-profile
      home-manager.users.${config.services.code-server.user} = { pkgs, config, ... }: {
        home.stateVersion = "22.11";
        programs.git.enable = true;
        programs.git.userName = "code-server";
        programs.git.userEmail = "pbsds@hotmail.com";
        #programs.vscode.extensions
        #programs.vscode.bindings
        #programs.vscode.userSettings
      };

      systemd.services.initial-setup = {
        enable   = true;
        wantedBy = [ "code-server.service" ];
        before   = [ "code-server.service" ];

        # TODO: run as the correct user
        serviceConfig.User  = config.services.code-server.user;
        serviceConfig.Group = config.services.code-server.group;

        # TODO: make the ssh key comment automatic
        script = ''
          test -s "$HOME/.ssh/id_ed25519.pub" || {
            test -d "$HOME/.ssh" || mkdir -p "$HOME/.ssh"
            echo "" | ${pkgs.openssh}/bin/ssh-keygen -t ed25519 -a 100 -C "code-server@code-server-pandoc-${hostName}" -f "$HOME/.ssh/id_ed25519"
            echo
          }
          echo "My pubkey is:"
          cat "$HOME/.ssh/id_ed25519.pub"

          #${pkgs.curl}/bin/curl "https://github.com/pbsds.keys" | grep "$(cat $HOME/.ssh/id_ed25519.pub | cut -d" " -f-2)"

          test -d "$HOME/repo" || (
            set -x
            cp -a ${inputs.pbsds-papers.outPath} "$HOME/repo"
            chmod -R +w "$HOME/repo"
          )
          test -e "$HOME/repo/neural-intersection-fields/.vscode" || (
            cd "$HOME/repo/neural-intersection-fields"
            ln -s ../.vscode .
          )

          if test -d "$HOME/repo/.git"; then
            ( cd $HOME/repo; git pull --rebase --autostash ) # TODO: somehow rollback if failed
          fi
        '';
      };

      services.code-server = {
        enable = true;
        host = "0.0.0.0"; # container
        port = 53754;
        #user  = "code-server";
        #group = "code.server";

        # a nice tool if you don't care about security: https://argon2.online/
        hashedPassword = "$argon2i$v=19$m=16,t=2,p=1$MHh5UGNtU1lWR1UySnhIZw$ITg8U7Gq2CXByuOOnrKVUg"; # hunter2

        extraArguments = [
          "${config.users.users.${config.services.code-server.user}.home}/repo/neural-intersection-fields"
        ];

        package = pkgs.vscode-with-extensions.override {
          #vscode = pkgs.code-server.overrideAttrs (old: {
          vscode = pkgs.unstable.code-server.overrideAttrs (old: {
            # vscode-with-extensions compatibility
            # https://github.com/NixOS/nixpkgs/pull/192889
            passthru.executableName = "code-server";
            passthru.longName = "Visual Studio Code Server";
          });
          #vscodeExtensions = with pkgs.unstable.vscode-extensions; [
          vscodeExtensions = with pkgs.vscode-extensions; [
            #shd101wyy.markdown-preview-enhanced
            sanaajani.taskrunnercode # doesn't work?
            tomoki1207.pdf # no firefox?
          ] ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [
            {
              name = "markdown-preview-enhanced";
              publisher = "shd101wyy";
              #version = "0.6.7";
              #sha256 = "5tgxpjkpbgv8HcfLBbDcOOEd8swinK5iHtnO34892ik=";
              version = "0.6.8";
              sha256 = "9NRaHgtyiZJ0ic6h1B01MWzYhDABAl3Jm2IUPogYWr0=";
            }
            /* === */
            {
              name = "new-railscasts";
              publisher = "carakan";
              version = "1.0.68";
              sha256 = "sha256-uZCAurvZu7QHjTR6ukmYbsI58GpfTo3shdoX/MH2ElA=";
            }
            {
              name = "theme-railscasts";
              publisher = "PaulOlteanu";
              version = "4.0.1";
              sha256 = "sha256-67RNcMr+hvzn2FvapkHLd8OdEBAz8w4cwsGlu0tbCNY=";
            }
            {
              name = "trailscasts";
              publisher = "mksafi";
              version = "1.2.3";
              sha256 = "sha256-mZ9I1BYf8x3lpl5/2sojk+5GMfhDqRBzs6nFkumlPKg=";
            }
            {
              name = "vscode-theme-railscasts-plus";
              publisher = "marlosirapuan";
              version = "0.0.6";
              sha256 = "sha256-8GyyxDeehFo/lGSmA6dfXZ3DMZ/B632ax+9q3+irjws=";
            }
            {
              name = "theme-railscast-next";
              publisher = "edus44";
              version = "0.0.2";
              sha256 = "sha256-RYk6X4iKoEQlKSVhydnwWQJqt884+HC9DZN2aqIbfNI=";
            }
            { # best, but no markdown
              name = "railscasts";
              publisher = "mrded";
              version = "0.0.4";
              sha256 = "sha256-vjfoeRW+rmYlzSuEbYJqg41r03zSfbfuNCfAhHYyjDc=";
            }
            {
              name = "beardedtheme";
              publisher = "BeardedBear";
              version = "7.4.0";
              sha256 = "sha256-8FY9my7v7bcfD0LH5AVNGI2dF1qMLnVp2LR/CiP01NQ=";
            }
          ];
        };
        extraPackages = (with pkgs; [
          git gh hub
          micro
        ]) ++ (let
            #shell = import "${inputs.pbsds-papers}/shell.nix" { inherit pkgs; };
            shell = inputs.pbsds-papers.devShells.${pkgs.system}.default;
        in
          (with pkgs; [ imagemagick librsvg ]) #  for some reason it isn't picked up from from shell.nix?
          ++ shell.buildInputs
          ++ shell.nativeBuildInputs
          ++ shell.propagatedBuildInputs
          ++ shell.propagatedNativeBuildInputs
        );
      };

      networking.firewall.enable = true;
      networking.firewall.allowedTCPPorts = [
        config.services.code-server.port
      ];
    };
  };

  services.nginx.virtualHosts.${subdomain} = {
    forceSSL = true; # addSSL = true;
    enableACME = true; #useACMEHost = acmeDomain;
    locations."/" = {
      #proxyPass = "http://127.0.0.1:${toString container.services.code-server.port}";
      #proxyPass = "http://10.240.100.3:${toString container.services.code-server.port}";
      proxyPass = "http://${config.containers.${container-name}.localAddress}:${toString container.services.code-server.port}";
      proxyWebsockets = true;
      # https://github.com/coder/code-server/issues/4443
      extraConfig = ''
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection upgrade;
        proxy_set_header Accept-Encoding gzip;
      '';
    };
  };

}
