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

{ pkgs, lib, ... }:

let
  spchapi = pkgs.fetchurl {
    url = "https://www.htmlbible.com/MicrosoftSpeechComponents/SAPI4point0aRuntimeBinaries/spchapi.exe";
    hash = "sha256:1pb3wcv80g0kk3q94rfr29spxa8asd8qzrc05yg57hkv441ywmc9";
  };
  tv_enua = pkgs.fetchurl {
    url = "https://www.htmlbible.com/MicrosoftSpeechComponents/TextToSpeechEngines/AmericanEnglish/tv_enua.exe";
    hash = "sha256:0cckcpmndnq9d0r0vmpch5pmw76lgzxn3983196niysi5683d6bh";
  };
  msam = pkgs.fetchurl {
    url = "https://archive.org/download/Sam_mike_and_mary/microsoft_sam%2C_mike%2C_and_mary.exe";
    hash = "sha256:0pixa50v5lyhv7i6d8p2b6lb2pf38gr4lmym9v5m1ljkkr49lzy8";
  };

  wineprefix = pkgs.runCommand "sapi-wineprefix" {
    nativeBuildInputs = [ pkgs.wine pkgs.xvfb-run ];
    stampVersion = "1";
  } ''
    mkdir $out
    echo "$stampVersion" > $out/version
    mkdir $out/home
    export HOME=$out/home
    export WINEPREFIX=$out/wineprefix
    xvfb-run -a wine ${spchapi} || true
    xvfb-run -a wine ${tv_enua} /q || true
    xvfb-run -a wine ${msam} /q || true
    xvfb-run -a wine ${sapi4src}/SAPI4SDK.exe /q || true
  '';

  sapi4src = pkgs.fetchFromGitHub {
    owner = "TETYYS";
    repo = "SAPI4";
    rev = "23b0dd17083cc2fd7d5656d2996640a90cb58ea0";
    hash = "sha256:1yjjfhbs6d29vyvi2bs96mhr0zmjlyf8m8snrxiq0c5z5f4imfzb";
  };
  w32pkgs = pkgs.pkgsCross.mingw32;
  w32BuildPackages = w32pkgs.buildPackages;
  gcc = w32BuildPackages.wrapCC (w32BuildPackages.gcc-unwrapped.override ({
    threadsCross = {
      model = "win32";
      package = null;
    };
  }));
  stdenv' = w32pkgs.overrideCC w32pkgs.stdenv gcc;
  sapi4 = stdenv'.mkDerivation {
    pname = "sapi4";
    version = "0.0.1";
    src = sapi4src;

    buildPhase = ''
      export CC=i686-w64-mingw32-g++
      export MSSPEECH="${wineprefix}/wineprefix/drive_c/Program Files/Microsoft Speech SDK/Include/"

      cat ${./mysapi4.cpp} >> sapi4.cpp

      echo sapi4
      "$CC" -shared -Wl,--out-implib,sapi4.lib -o sapi4.dll sapi4.cpp -I "$MSSPEECH" -lole32 -luser32 -luuid
      # echo sapi4limits
      # "$CC" -o sapi4limits.exe sapi4limits.cpp -I "$MSSPEECH" -lole32 -luser32 -luuid -L. -lsapi4
      # echo sapi4out
      # "$CC" -o sapi4out.exe sapi4out.cpp -I "$MSSPEECH" -lole32 -luser32 -luuid -L. -lsapi4

      mkdir -p $out/bin
      cp sapi4.dll $out/bin
    '';
  };
  sayit = pkgs.writeShellApplication {
    name = "sayit-sapi";

    runtimeInputs = [ pkgs.wine ];

    text = ''
      prefixStampVersion="0"
      export WINEPREFIXBASE="''${CACHE_DIRECTORY:-$HOME/.cache}/sayit-sapi-wineprefix"
      if [[ -f "$WINEPREFIXBASE/version" ]]; then
        prefixStampVersion="$(cat "$WINEPREFIXBASE/version")"
      fi
      if [[ "$prefixStampVersion" != "${wineprefix.stampVersion}" ]]; then
        rm -rf "$WINEPREFIXBASE"
        cp -R "${wineprefix}" "$WINEPREFIXBASE"
        chmod -R u+w "$WINEPREFIXBASE"
      fi

      export WINEPREFIX="$WINEPREFIXBASE/wineprefix"
      export WINEDEBUG="''${WINEDEBUG:--all}"
      exec wine ${sapi4}/bin/sapi4out.exe Sam 100 150 "$1"
    '';
  };
  sapid = pkgs.buildGoModule {
    name = "sapid";
    src = lib.sourceByRegex ./. [".*\.go$" "go.mod"];
    vendorHash = null;

    postInstall = ''
      for f in ${sapi4}/bin/*.dll; do
        ln -s "$f" $out/bin
      done
      mv $out/bin/windows_386/*.exe $out/bin
      rmdir $out/bin/windows_386
    '';

    preBuild = ''
      export GOOS=windows GOARCH=386
    '';
  };
  sapid-wrapper = pkgs.writeShellApplication {
    name = "sapid-wrapper";

    runtimeInputs = [ pkgs.xvfb-run pkgs.wine ];

    text = ''
      prefixStampVersion="0"
      export WINEPREFIXBASE="''${CACHE_DIRECTORY:-$HOME/.cache}/sayit-sapi-wineprefix"
      if [[ -f "$WINEPREFIXBASE/version" ]]; then
        prefixStampVersion="$(cat "$WINEPREFIXBASE/version")"
      fi
      if [[ "$prefixStampVersion" != "${wineprefix.stampVersion}" ]]; then
        rm -rf "$WINEPREFIXBASE"
        cp -R "${wineprefix}" "$WINEPREFIXBASE"
        chmod -R u+w "$WINEPREFIXBASE"
      fi

      export WINEPREFIX="$WINEPREFIXBASE/wineprefix"
      export WINEDEBUG="''${WINEDEBUG:--all}"
      exec xvfb-run -a wine "${sapid}/bin/sapi.exe" "$@"
    '';
  };
in
  {
    inherit spchapi tv_enua msam wineprefix sapi4src sapi4 sayit sapid sapid-wrapper;
  }