{ self }: final: prev:

with prev.lib;

let
  created =
    let
      fromDate = builtins.readFile (prev.runCommand "date" { nativeBuildInputs = with final; [ coreutils ]; } ''
        printf '%s' $(date -Is -d '@${toString self.lastModified}') > $out
      '');
    in if self ? lastModified then fromDate else "1970-01-01T00:00:01Z";
  
  mkUniworxDocker = { isDemo }: prev.dockerTools.buildImage {
    name = "uniworx${optionalString isDemo "-demo"}";
    tag =
      let
        versionFile = if isDemo then ./demo-version.json else ./version.json;
      in (builtins.fromJSON (prev.lib.readFile versionFile)).version;
    inherit created; 

    contents = with final; [
      uniworx.uniworx.components.exes.uniworx
      prev.dockerTools.binSh findutils coreutils
      cups # needed for interface with print center 
      # texlive.combined.scheme-medium # Causes container to be too large! However, might be needed by the pandoc library to produce PDFs, but nix ought to include the necessary parts already
      texlive.combined.scheme-basic # for PDFLaTeX for pandoc PDF creation
      # pandoc  # just for manual testing within the pod, remove for production, since we use the library instead!
      curl wget netcat # just for manual testing within the pod, remove for production!
      openldap  # just for manual testing within the pod, remove for production!
      iana-etc
      unixtools.netstat htop gnugrep
    ] ++ optionals isDemo [ postgresql_12 memcached uniworx.uniworx.components.exes.uniworxdb ];

    runAsRoot = ''
      #!${final.stdenv.shell}

      ${prev.dockerTools.shadowSetup}

      mkdir -p /var/lib

      groupadd -r uniworx
      useradd -r -g uniworx -d /var/lib/uniworx -M uniworx --uid 999
      install -d -g uniworx -o uniworx -m 0750 /var/lib/uniworx

      mkdir -p /var/log
      install -d -g uniworx -o uniworx -m 0755 /var/log/uniworx

      ${optionalString isDemo ''
          install -d -g uniworx -o uniworx -m 0750 /var/lib/postgres

          install -d -g uniworx -o uniworx -m 0750 /var/lib/memcached

          install -d -g uniworx -o uniworx -m 0755 /var/log/postgres
          install -d -g uniworx -o uniworx -m 0755 /var/log/memcached

          mkdir -p /run
          install -d -g uniworx -o uniworx -m 0755 /run/postgres
      ''}
    '';

    config =
      let
        entrypoint = prev.writeScriptBin "uniworx-entrypoint" ''
          #!${final.zsh}/bin/zsh -xe

          cTime=$(date -Is)

          ${optionalString isDemo ''
              pgDir=/var/lib/postgres
              pgSockDir=/run/postgres
              pgLogFile=/var/log/postgres/''${cTime}.log
              export PGHOST=''${pgSockDir}
              export PGLOG=''${pgLogFile}

              pgNew=
              if [[ -n "$(find ''${pgDir} -maxdepth 0 -type d -empty 2>/dev/null)" ]]; then
                pgNew=1
              fi

              [[ -z "''${pgNew}" ]] || initdb --no-locale --encoding=UTF8 --username postgres --pgdata ''${pgDir}
              pg_ctl start -D ''${pgDir} -l ''${pgLogFile} -w -o "-k ''${pgSockDir} -c listen_addresses= -c hba_file=${postgresHba} -c unix_socket_permissions=0777 -c max_connections=9990 -c shared_preload_libraries=pg_stat_statements -c auto_explain.log_min_duration=100ms"
              [[ -z "''${pgNew}" ]] || psql -f ${postgresSchema} postgres postgres

              ( cd /var/lib/memcached; memcached -p 11212 ) &>/var/log/memcached/''${cTime}.log &
              export SESSION_MEMCACHED_HOST=localhost
              export SESSION_MEMCACHED_PORT=11212
          ''}

          # export LOGDEST=/var/log/uniworx/''${cTime}.log # kubernetes prefers log via stdout
          typeset -a configs
          configs=()
          configDir=''${CONFIG_DIR-/cfg}
          if [[ -d "''${configDir}" ]]; then
            while IFS= read -d $'\0' cfg; do
              configs+=("''${(q)cfg}")
            done < <(find "''${configDir}" \( -name '*.yml' -o -name '*.yaml' \) -print0 | sort -rz)
          fi
          configs+=('${uniworxConfig}')
          cd /var/lib/uniworx
          ${optionalString isDemo ''
              [[ -z "''${pgNew}" ]] || uniworxdb -f ''${configs}
          ''}
          exec -- uniworx ''${configs}
        '';
        postgresSchema = prev.writeText "schema.sql" ''
          CREATE USER uniworx WITH SUPERUSER;
          CREATE DATABASE uniworx;
          GRANT ALL ON DATABASE uniworx TO uniworx;
        '';

        postgresHba = prev.writeText "hba_file" ''
          local all all trust
        '';
        uniworxConfig = prev.writeText "uni2work.yml" ''
          port: 8080
          approot: "_env:APPROOT:http://localhost:8080"
        '';
      in {
        Cmd = [ "${entrypoint}/bin/uniworx-entrypoint" ];
        User = "uniworx:uniworx";
        ExposedPorts = {
          "8080/tcp" = {};
        };
        Volumes = {
          "/var/lib/uniworx" = {};
          "/var/log" = {};
        } // optionalAttrs isDemo {
          "/var/lib/postgres" = {};
        };
      };
  };
in
{
  ciDocker = prev.dockerTools.buildImageWithNixDb rec {
    name = "uniworx-ci";
    inherit created;
    tag = (builtins.fromJSON (prev.lib.readFile ./ci-version.json)).version;
    fromImage = prev.docker-nixpkgs.nix-unstable;

    contents = with final; [
      bash coreutils
      minio-client
      xz
    ];
    
    runAsRoot = ''
      #!${final.stdenv.shell}

      ${final.coreutils}/bin/install -v -m 0777 -d /var/tmp
    '';
  };
} // mapAttrs (_name: mkUniworxDocker) {
  uniworxDemoDocker = { isDemo = true; };
  uniworxDocker = { isDemo = false; };
}
