/*
 * Copyright 2024 Rive
 */

#pragma once

#include "common/tcp_client.hpp"
#include "common/queue.hpp"
#include "write_png_file.hpp"
#include <array>
#include <cassert>
#include <string>
#include <thread>
#include <vector>
#include <filesystem>

struct ImageSaveArgs
{
    std::string name;
    uint32_t width;
    uint32_t height;
    std::vector<uint8_t> pixels;
    bool quit = false;
};

// Attempts to connect to the python server, and if successful, pipes stdout and
// stderr to the server. Also provides utilities for encoding & uploading PNGs,
// and notifying the server when the application crashes.
class TestHarness
{
public:
    static TestHarness& Instance();
    ~TestHarness() { shutdown(); }

    bool initialized() const { return m_initialized; }
    void init(std::unique_ptr<TCPClient>, size_t pngThreadCount);
    void init(std::filesystem::path, size_t pngThreadCount);

    bool hasTCPConnection() const { return m_primaryTCPClient != nullptr; }

    void setPNGCompression(PNGCompression compression)
    {
        m_pngCompression = compression;
    }

    void savePNG(ImageSaveArgs args);

    // Only returns true the on the first server request for a given name.
    // Prevents gms from running more than once in a multi-process execution.
    bool claimGMTest(const std::string&);

    // Downloads the next .riv file to test. (Must only be run on the main
    // thread.)
    bool fetchRivFile(std::string& name, std::vector<uint8_t>& bytes);

    // Sends a message to be printed on the server's stdout, e.g., for
    // forwarding the client's stdout.
    void printMessageOnServer(const char* msg);

    // Returns true if there is an input character to process from the server.
    bool peekChar(char& key);

    void shutdown();

    void onApplicationCrash(const char* message);

private:
    TestHarness();

    // Pipe stdout & stderr and spin off a thread that forwards them to the test
    // harness and, on Android, the Android logs.
    void initStdioThread();

    // Adheres to a quick-and-dirty protocol for sending a PNG image back to the
    // python harness.
    void sendImage(const std::string& remoteDestination,
                   uint32_t width,
                   uint32_t height,
                   uint8_t* imageDataRGBA);

    // Print a message on the server-side console.
    void sendConsoleMessage(const char* message, uint32_t messageLength);

    void shutdownStdioThread();
    void shutdownInputPumpThread();

    // Forwards stdout and stderr to the server.
    static void MonitorStdIOThread(void* thisPtr)
    {
        reinterpret_cast<TestHarness*>(thisPtr)->monitorStdIOThread();
    }
    void monitorStdIOThread();

    // Encodes PNGS and sends them to the server.
    static void EncodePNGThread(void* thisPtr)
    {
        reinterpret_cast<TestHarness*>(thisPtr)->encodePNGThread();
    }
    void encodePNGThread();

    // Receives standard input from the server and queues it up.
    static void InputPumpThread(void* thisPtr)
    {
        reinterpret_cast<TestHarness*>(thisPtr)->inputPumpThread();
    }
    void inputPumpThread();

    bool m_initialized = false;
    std::unique_ptr<TCPClient> m_primaryTCPClient;
    std::filesystem::path m_outputDir;

    // Forwarding stdout and stderr to the server.
    int m_savedStdout = 0;
    int m_savedStderr = 0;
    std::array<int, 2> m_stdioPipe = {0, 0};
    std::thread m_stdioThread;

    // PNG image encode queue.
    queue<ImageSaveArgs> m_encodeQueue{1};
    PNGCompression m_pngCompression = PNGCompression::compact;
    std::vector<std::thread> m_encodeThreads;

    // Standard input from the server.
    queue<char> m_inputQueue{128};
    std::thread m_inputPumpThread;
};
