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

with lib;

let

  cfg = config.services.lektor;

in {

  options.services.lektor = {
    enable = mkEnableOption "enable services.lektor";
    user = mkOption {
      default = "lektor";
      type = with types; str;
      description = ''
        name of the lektor service
      '';
    };
    home = mkOption {
      default = "/home/${cfg.user}";
      type = with types; str;
      description = ''
        home of the service
      '';
    };
    repository = mkOption {
      type = with types; str;
      description = ''
        Repository to get the lektor project from.
      '';
      example = "git@github.com:lektor/lektor-website.git";
    };
    bind = mkOption {
      default = "0.0.0.0";
      type = with types; str;
      description = ''
        Host to bind the lektor service to.
      '';
    };
    serviceName = mkOption {
      default = "lektor";
      type = with types; str;
      description = ''
        name of the system service (without the .service suffix)
      '';
    };
    port = mkOption {
      default = 5000;
      type = with types; int;
      description = ''
        Port to bind the lektor service to.
      '';
    };
    additionalScript = mkOption {
      default = null;
      type = with types; nullOr path;
      description = ''
        A script you can us as a hook before the lektor server start
        (for example to creat your css or javascript files)
      '';
      example = pkgs.writeShellScript "build" ''
        ${pkgs.nix}/bin/nix-shell --run build";
      '';
    };
    #sshMatchBlocks = mkOption {
    #  default = [];
    #  type = with types; listOf attrs;
    #  description = ''
    #    a matchBlock from home-manager.users.<name>.programs.ssh.matchBlocks;
    #  '';
    #};
    host = mkOption {
      type = with types; str;
      description = ''
        ssh host to pull from and push to
      '';
    };
    sshKey = mkOption {
      type = with types; str;
      description = ''
        todo : avoid this, or make sure the home folder is crypted
        Warning the key will be copied into the home folder of the user
        ssh key to use
      '';
    };
  };

  config = mkIf cfg.enable {

    # create User
    users.users."${cfg.user}" = {
      home = cfg.home;
      createHome = true;
      isSystemUser = true;
    };

    # create systemd service to start service
    systemd.services."${cfg.serviceName}" = {
      enable = true;
      wantedBy = [ "multi-user.target" ];

      environment.NIX_PATH = config.environment.variables.NIX_PATH;
      serviceConfig = {
        User = cfg.user;
        # todo : this is not working properly
        TimeoutStartSec =
          "infinity"; # it might take some time will this thing is up

        ExecStartPre = let

          sshKeyTarget = "/run/keys.lektor/id_rsa";

          sshConfig = pkgs.writeText "sshconfig" ''
            Host ${cfg.host}
              IdentityFile ${sshKeyTarget}

            Host *
              ForwardAgent no
              Compression no
              ServerAliveInterval 0
              HashKnownHosts no
              UserKnownHostsFile ~/.ssh/known_hosts
              ControlMaster no
              ControlPath ~/.ssh/master-%r@%n:%p
              ControlPersist no
          '';

          sshKeyScript = pkgs.writers.writeDash "keyfile-gen" # sh
            ''
              set -x

              # setup ~/.ssh
              mkdir -p ${cfg.home}/.ssh
              chown ${cfg.user} ${cfg.home}/.ssh
              chmod 700 ${cfg.home}/.ssh

              cp ${sshConfig} ${cfg.home}/.ssh/config
              chown ${cfg.user} ${cfg.home}/.ssh/config
              chmod 500 ${cfg.home}/.ssh/config

              mkdir -p ${dirOf sshKeyTarget}
              chmod 700 ${dirOf sshKeyTarget}
              chown ${cfg.user} ${dirOf sshKeyTarget}
              cp ${toString cfg.sshKey} ${sshKeyTarget}
              chown ${cfg.user} ${sshKeyTarget}
              chmod 500 ${sshKeyTarget}
            '';

          cloneScript = pkgs.writers.writeDash "clone" # sh
            ''
              set -x
              if [[ `ls ~/${cfg.user} | wc -l` == 0 ]]
              then
                rm ~/${cfg.user}
              fi
              ${pkgs.git}/bin/git clone ${cfg.repository} ~/${cfg.user}
            '';

        in [ "+${sshKeyScript}" "-${cloneScript}" ];
      };

      # todo : add restart ruling

      script = # sh
        ''
          cd ~/${cfg.user} && \
          ${pkgs.git}/bin/git pull && \
          ${
            optionalString (cfg.additionalScript != null)
            "${cfg.additionalScript} &&"
          } \
          ${pkgs.python36Packages.lektor}/bin/lektor server \
            --host ${cfg.bind} \
            --port ${toString cfg.port}
        '';
    };
  };
}