# SPDX-FileCopyrightText: 2020 Luke Granger-Brown <depot@lukegb.com>
#
# SPDX-License-Identifier: Apache-2.0

{ depot, lib, pkgs, ... }@args:

let
  DateTime = ps: ps.buildPythonPackage rec {
    pname = "DateTime";
    version = "4.4";

    propagatedBuildInputs = with ps; [
      zope_interface
      pytz
    ];

    src = pkgs.fetchFromGitHub {
      owner = "zopefoundation";
      repo = "DateTime";
      rev = version;
      hash = "sha256:04p8sl4djygismc4mxgh4llgvw91b3a0hpal7rcc2hxl4hwasa3r";
    };
  };

  icalevents = ps: ps.buildPythonPackage rec {
    pname = "icalevents";
    version = "0.1.26";
    format = "pyproject";

    prePatch = ''
      substituteInPlace pyproject.toml \
        --replace 'pytz = "==2021.3"' 'pytz = "*"' \
        --replace '= "==' '= "^'
    '';

    nativeBuildInputs = with ps; [ poetry-core ];

    propagatedBuildInputs = with ps; [
      httplib2
      icalendar
      python-dateutil
      pytz
      (DateTime ps)
    ];

    src = pkgs.fetchFromGitHub {
      owner = "jazzband";
      repo = pname;
      rev = "v${version}";
      hash = "sha256:06mq3nzn7vipmb1jvw3c05cw3k3bgvkgs02xqzry94pjvbn0nmiz";
    };
  };

  quart = ps: ps.buildPythonPackage rec {
    pname = "quart";
    version = "0.17.0";
    format = "pyproject";

    nativeBuildInputs = with ps; [ poetry-core ];

    propagatedBuildInputs = with ps; [
      aiofiles
      blinker
      click
      hypercorn
      itsdangerous
      jinja2
      markupsafe
      toml
      werkzeug
    ];

    src = pkgs.fetchFromGitLab {
      owner = "pgjones";
      repo = "quart";
      rev = version;
      hash = "sha256:19f11i2lvbsfxk1hhbm6xwmxw2avwb6jx9z2nyi9njk8w442z4y6";
    };
  };

  python = pkgs.python3.withPackages (ps: with ps; [
    attrs
    (quart ps)
    aiohttp
    icalendar
    gunicorn
    uvicorn
    (icalevents ps)
  ]);

  filterSourcePred = (path: type: (type == "regular" &&
      lib.hasSuffix ".py" path ||
      lib.hasSuffix ".html" path
    ) || (
      type == "directory" &&
      baseNameOf path != "__pycache__" &&
      baseNameOf path != "node_modules" &&
      baseNameOf path != "config" &&
      baseNameOf path != "web" &&
      true));

  web = import ./web args;

  icalfilter = pkgs.stdenvNoCC.mkDerivation rec {
    name = "icalfilter";

    src = builtins.filterSource filterSourcePred ./.;
    inherit web;

    buildInputs = with pkgs; [ makeWrapper ];
    propagatedBuildInputs = [ python ];

    installPhase = ''
      sitepkgdir="$out/lib/${python.libPrefix}/site-packages"
      pkgdir="$sitepkgdir/icalfilter"
      mkdir -p $pkgdir
      cp -R \
        *.py \
        $pkgdir

      cp -R $src/templates $pkgdir/templates
      cp -R $web $pkgdir/static

      mkdir "$out/bin"
      makeWrapper "${python}/bin/gunicorn" "$out/bin/icalfilter" \
        --add-flags "-w" \
        --add-flags "4" \
        --add-flags "-k" \
        --add-flags "uvicorn.workers.UvicornWorker" \
        --add-flags "icalfilter.app:app" \
        --suffix PYTHONPATH : "$sitepkgdir"
    '';

    passthru.pythonEnv = python;
  };
in
  icalfilter // rec {
    gcloudRegion = "europe-west1";
    gcloudProject = "icalfilter-350303";
    imageName = "${gcloudRegion}-docker.pkg.dev/${gcloudProject}/icalfilter/icalfilter";

    dockerImage = pkgs.dockerTools.buildImage {
      name = imageName;
      config = {
        Entrypoint = [ "${icalfilter}/bin/icalfilter" ];
        Env = [
          "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
        ];
      };
    };

    uploadCmd = pkgs.writeShellApplication {
      name = "upload-icalfilter";

      runtimeInputs = with pkgs; [ skopeo google-cloud-sdk ];

      text = ''
        echo
        echo Uploading ${imageName}
        skopeo copy docker-archive:${dockerImage} docker://${imageName}:v1

        echo
        echo Switching Cloud Run over
        gcloud --project ${gcloudProject} run deploy icalfilter --region ${gcloudRegion} --image ${imageName}:v1
      '';
    };
  }