{ stdenv, mkYarnPackage, mkYarnModules, fetchFromGitHub, libsass, python, python3, pkg-config, libusb, fetchurl, nodejs, electron, writeText, makeWrapper, udev, nodePackages, libvips }:

let
  version = "2.1.3";
  source = fetchFromGitHub {
    owner = "bitfocus";
    repo = "companion";
#   rev = "v${version}";
    rev = "1cc51029a19d7263a09058f73922277ca53a1583";
    sha256 = "0305wwdic3n20whzhh9zqcd3dwj7hc4fpycs645ncc3sk48azmj0";
  };
  nodeHeaders = fetchurl {
    url = "https://nodejs.org/download/release/v${nodejs.version}/node-v${nodejs.version}-headers.tar.gz";
    sha256 = "19b0dg8292cjx758wlrvpb3jf520bpyvjal2n7r4fyvk38x9flik";
  };
  webui = mkYarnPackage rec {
    inherit version;
    pname = "bitfocus-companion-webui";

    src = "${source}/webui";

    configurePhase = "
      cp -r $node_modules node_modules
      chmod -R u+w node_modules
    ";
    buildPhase = "PUBLIC_URL=. yarn build";
    installPhase = "mv build $out";
    distPhase = "true";

    yarnNix = ./yarn-webui.nix;

    pkgConfig = {
      node-sass = {
        buildInputs = [ libsass python ];
        postInstall = "node scripts/build.js --tarball=${nodeHeaders}";
      };
    };
  };

  yarnModulesNoWorkspace = args: (mkYarnModules args).overrideAttrs(old: {
    buildPhase = builtins.replaceStrings [" ./package.json"] [" /dev/null; cp deps/*/package.json ."] old.buildPhase;
  });

  modules = yarnModulesNoWorkspace rec {
    inherit version;
    pname = "companion-modules";
    name = "${pname}-${version}";
    yarnNix = ./yarn.nix;
    packageJSON = "${source}/package.json";
    yarnLock = "${source}/yarn.lock";

    pkgConfig = {
      node-hid = {
        buildInputs = [ udev libusb python3 pkg-config ];
        postInstall = "${nodePackages.node-gyp}/bin/node-gyp rebuild --tarball=${nodeHeaders}";
      };
      sharp = {
        buildInputs = [ libvips pkg-config ];
        postInstall = ''
          sed -i "s|<!(node -p \"require(\\\\'./lib/libvips\\\\').minimumLibvipsVersion\")|${libvips.version}|" binding.gyp
          sed -i "s|<!(node -p \"require(\\\\'./lib/libvips\\\\').pkgConfigPath()\")||" binding.gyp
          sed -i "s|<!(node -p \"Boolean(require(\\\\'./lib/libvips\\\\').useGlobalLibvips()).toString()\")|true|" binding.gyp
          sed -i "s|PKG_CONFIG_PATH=\"<(pkg_config_path)\" ||" binding.gyp
          ${nodePackages.node-gyp}/bin/node-gyp rebuild --tarball=${nodeHeaders}
        '';
      };
    };
  };
in stdenv.mkDerivation rec {
  inherit version webui modules;
  pname = "bitfocus-companion";

  src = source;

  nativeBuildInputs = [ makeWrapper ];

  configurePhase = "";
  buildPhase = "";
  installPhase = ''
    mkdir -p $out/share
    cp --no-preserve=mode -r $src "$out/share/companion"
    echo "nixos-f00baa-0" > $out/share/companion/BUILD
    ln -s '${webui}' "$out/share/companion/static"
    cp -r '${modules}/node_modules' "$out/share/companion/node_modules"

    sed -i "s|process.resourcesPath|\"$out/share/companion\"|" $out/share/companion/lib/server_http.js
    sed -i "s|require('app-root-path')|\"$out/share/companion\"|" $out/share/companion/{app,lib/{schedule,help,instance}}.js

    makeWrapper '${electron}/bin/electron' "$out/bin/companion" \
      --add-flags "$out/share/companion"
  '';
}
