{ stdenv
, lib
, fetchFromGitHub
, meson
, cmake
, ninja
, pkg-config
, flex
, bison
, lksctp-tools
, talloc
, mongoc
, libyaml
, libmicrohttpd_1_0
, libgcrypt
, libidn
, gnutls
, openssl
, nghttp2
, curl

# webui
, buildNpmPackage
, jq
}:

let
  subprojects = {
    prometheus-client-c = fetchFromGitHub {
      owner = "open5gs";
      repo = "prometheus-client-c";
      rev = "a58ba25bf87a9b1b7c6be4e6f4c62047d620f402";  # open5gs branch
      hash = "sha256-COZV4UeB7YRfpLwloIfc/WdlTP9huwVfXrJWH4jmvB8=";
    };
    freeDiameter = fetchFromGitHub {
      owner = "open5gs";
      repo = "freeDiameter";
      rev = "20196a265aecb7b1573ceb526bb619e092c1fd3f";  # r1.5.0
      hash = "sha256-0sxzQtKBx313+x3TRsmeswAq90Vk5jNA//rOJcEZJTQ=";
    };
    libtins = fetchFromGitHub {
      owner = "open5gs";
      repo = "libtins";
      rev = "bf22438172d269e6db70e27246dffd8e1f0b96e3";  # r4.5
      hash = "sha256-BxSBNKI+jwI33lN+vmYCYSDAxsVDXS190byAzq6lB/A=";
    };
    usrsctp = fetchFromGitHub {
      owner = "sctplab";
      repo = "usrsctp";
      rev = "refs/tags/0.9.5.0";
      hash = "sha256-Sengtkg4UoA03cPy5+dRSr5qKIttWHEKn48udOP8zYI=";
    };
  };

  version = "2.7.2";
  src = fetchFromGitHub {
    owner = "open5gs";
    repo = "open5gs";
    rev = "v${version}";
    hash = "sha256-XSDjVW+5l2trrilKMcSfX6QIfh/ijWxjoJg33Bn1DBU=";
  };

  webui = buildNpmPackage {
    pname = "open5gs-webui";
    inherit version src;
    sourceRoot = "source/webui";

    nativeBuildInputs = [ jq ];
    postPatch = ''
      jq '. * {"bin": {"open5gs-webui": "server/index.js"}}' package.json > package.json.new
      mv package.json.new package.json
    '';
    postInstall = ''
      wrapProgram "$out/bin/open5gs-webui" \
        --chdir "$out/lib/node_modules/open5gs" \
        --set NODE_ENV production
    '';

    npmDepsHash = "sha256-IpqineYa15GBqoPDJ7RpaDsq+MQIIDcdq7yhwmH4Lzo=";
  };
in
stdenv.mkDerivation {
  pname = "open5gs";
  inherit version src;

  postPatch = ''
    ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: ''
      ln -s "${value}" "subprojects/${name}"
    '') subprojects)}
  '';

  nativeBuildInputs = [
    meson
    cmake
    ninja
    pkg-config
    flex
    bison
  ];

  buildInputs = [
    lksctp-tools
    talloc
    mongoc
    libyaml
    libmicrohttpd_1_0
    libgcrypt
    libidn
    gnutls
    openssl
    nghttp2
    curl
  ];

  passthru = {
    inherit subprojects webui;
  };
}