/*-------------------------------------------------------------------------
 * drawElements Quality Program Execution Server
 * ---------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief TestProcess implementation for Win32.
 *//*--------------------------------------------------------------------*/

#include "xsWin32TestProcess.hpp"
#include "deFilePath.hpp"
#include "deString.h"
#include "deMemory.h"
#include "deClock.h"
#include "deFile.h"

#include <sstream>
#include <string.h>

using std::string;
using std::vector;

namespace xs
{

enum
{
    MAX_OLD_LOGFILE_DELETE_ATTEMPTS = 20, //!< How many times execserver tries to delete old log file
    LOGFILE_DELETE_SLEEP_MS         = 50  //!< Sleep time (in ms) between log file delete attempts
};

namespace win32
{

// Error

static std::string formatErrMsg(DWORD error, const char *msg)
{
    std::ostringstream str;
    LPSTR msgBuf;

#if defined(UNICODE)
#error Unicode not supported.
#endif

    if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
                      error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msgBuf, 0, DE_NULL) > 0)
        str << msg << ", error " << error << ": " << msgBuf;
    else
        str << msg << ", error " << error;

    return str.str();
}

Error::Error(DWORD error, const char *msg) : std::runtime_error(formatErrMsg(error, msg)), m_error(error)
{
}

// Event

Event::Event(bool manualReset, bool initialState) : m_handle(0)
{
    m_handle = CreateEvent(NULL, manualReset ? TRUE : FALSE, initialState ? TRUE : FALSE, NULL);
    if (!m_handle)
        throw Error(GetLastError(), "CreateEvent() failed");
}

Event::~Event(void)
{
    CloseHandle(m_handle);
}

void Event::setSignaled(void)
{
    if (!SetEvent(m_handle))
        throw Error(GetLastError(), "SetEvent() failed");
}

void Event::reset(void)
{
    if (!ResetEvent(m_handle))
        throw Error(GetLastError(), "ResetEvent() failed");
}

// CaseListWriter

CaseListWriter::CaseListWriter(void) : m_dst(INVALID_HANDLE_VALUE), m_cancelEvent(true, false)
{
}

CaseListWriter::~CaseListWriter(void)
{
}

void CaseListWriter::start(const char *caseList, HANDLE dst)
{
    DE_ASSERT(!isStarted());

    m_dst = dst;

    int caseListSize = (int)strlen(caseList) + 1;
    m_caseList.resize(caseListSize);
    std::copy(caseList, caseList + caseListSize, m_caseList.begin());

    de::Thread::start();
}

void CaseListWriter::run(void)
{
    try
    {
        Event ioEvent(true, false); // Manual reset, non-signaled state.
        HANDLE waitHandles[] = {ioEvent.getHandle(), m_cancelEvent.getHandle()};
        OVERLAPPED overlapped;
        int curPos = 0;

        deMemset(&overlapped, 0, sizeof(overlapped));
        overlapped.hEvent = ioEvent.getHandle();

        while (curPos < (int)m_caseList.size())
        {
            const int maxWriteSize = 4096;
            const int numToWrite   = de::min(maxWriteSize, (int)m_caseList.size() - curPos);
            DWORD waitRes          = 0;

            if (!WriteFile(m_dst, &m_caseList[curPos], (DWORD)numToWrite, NULL, &overlapped))
            {
                DWORD err = GetLastError();
                if (err != ERROR_IO_PENDING)
                    throw Error(err, "WriteFile() failed");
            }

            waitRes = WaitForMultipleObjects(DE_LENGTH_OF_ARRAY(waitHandles), &waitHandles[0], FALSE, INFINITE);

            if (waitRes == WAIT_OBJECT_0)
            {
                DWORD numBytesWritten = 0;

                // \note GetOverlappedResult() will fail with ERROR_IO_INCOMPLETE if IO event is not complete (should be).
                if (!GetOverlappedResult(m_dst, &overlapped, &numBytesWritten, FALSE))
                    throw Error(GetLastError(), "GetOverlappedResult() failed");

                if (numBytesWritten == 0)
                    throw Error(GetLastError(), "Writing to pipe failed (pipe closed?)");

                curPos += (int)numBytesWritten;
            }
            else if (waitRes == WAIT_OBJECT_0 + 1)
            {
                // Cancel.
                if (!CancelIo(m_dst))
                    throw Error(GetLastError(), "CancelIo() failed");
                break;
            }
            else
                throw Error(GetLastError(), "WaitForMultipleObjects() failed");
        }
    }
    catch (const std::exception &e)
    {
        // \todo [2013-08-13 pyry] What to do about this?
        printf("win32::CaseListWriter::run(): %s\n", e.what());
    }
}

void CaseListWriter::stop(void)
{
    if (!isStarted())
        return; // Nothing to do.

    m_cancelEvent.setSignaled();

    // Join thread.
    join();

    m_cancelEvent.reset();

    m_dst = INVALID_HANDLE_VALUE;
}

// FileReader

FileReader::FileReader(ThreadedByteBuffer *dst)
    : m_dstBuf(dst)
    , m_handle(INVALID_HANDLE_VALUE)
    , m_cancelEvent(false, false)
{
}

FileReader::~FileReader(void)
{
}

void FileReader::start(HANDLE file)
{
    DE_ASSERT(!isStarted());

    m_handle = file;

    de::Thread::start();
}

void FileReader::run(void)
{
    try
    {
        Event ioEvent(true, false); // Manual reset, not signaled state.
        HANDLE waitHandles[] = {ioEvent.getHandle(), m_cancelEvent.getHandle()};
        OVERLAPPED overlapped;
        std::vector<uint8_t> tmpBuf(FILEREADER_TMP_BUFFER_SIZE);
        uint64_t offset = 0; // Overlapped IO requires manual offset keeping.

        deMemset(&overlapped, 0, sizeof(overlapped));
        overlapped.hEvent = ioEvent.getHandle();

        for (;;)
        {
            DWORD numBytesRead = 0;
            DWORD waitRes;

            overlapped.Offset     = (DWORD)(offset & 0xffffffffu);
            overlapped.OffsetHigh = (DWORD)(offset >> 32);

            if (!ReadFile(m_handle, &tmpBuf[0], (DWORD)tmpBuf.size(), NULL, &overlapped))
            {
                DWORD err = GetLastError();

                if (err == ERROR_BROKEN_PIPE)
                    break;
                else if (err == ERROR_HANDLE_EOF)
                {
                    if (m_dstBuf->isCanceled())
                        break;

                    deSleep(FILEREADER_IDLE_SLEEP);

                    if (m_dstBuf->isCanceled())
                        break;
                    else
                        continue;
                }
                else if (err != ERROR_IO_PENDING)
                    throw Error(err, "ReadFile() failed");
            }

            waitRes = WaitForMultipleObjects(DE_LENGTH_OF_ARRAY(waitHandles), &waitHandles[0], FALSE, INFINITE);

            if (waitRes == WAIT_OBJECT_0)
            {
                // \note GetOverlappedResult() will fail with ERROR_IO_INCOMPLETE if IO event is not complete (should be).
                if (!GetOverlappedResult(m_handle, &overlapped, &numBytesRead, FALSE))
                {
                    DWORD err = GetLastError();

                    if (err == ERROR_HANDLE_EOF)
                    {
                        // End of file - for now.
                        // \note Should check for end of buffer here, or otherwise may end up in infinite loop.
                        if (m_dstBuf->isCanceled())
                            break;

                        deSleep(FILEREADER_IDLE_SLEEP);

                        if (m_dstBuf->isCanceled())
                            break;
                        else
                            continue;
                    }
                    else if (err == ERROR_BROKEN_PIPE)
                        break;
                    else
                        throw Error(err, "GetOverlappedResult() failed");
                }

                if (numBytesRead == 0)
                    throw Error(GetLastError(), "Reading from file failed");
                else
                    offset += (uint64_t)numBytesRead;
            }
            else if (waitRes == WAIT_OBJECT_0 + 1)
            {
                // Cancel.
                if (!CancelIo(m_handle))
                    throw Error(GetLastError(), "CancelIo() failed");
                break;
            }
            else
                throw Error(GetLastError(), "WaitForMultipleObjects() failed");

            try
            {
                m_dstBuf->write((int)numBytesRead, &tmpBuf[0]);
                m_dstBuf->flush();
            }
            catch (const ThreadedByteBuffer::CanceledException &)
            {
                // Canceled.
                break;
            }
        }
    }
    catch (const std::exception &e)
    {
        // \todo [2013-08-13 pyry] What to do?
        printf("win32::FileReader::run(): %s\n", e.what());
    }
}

void FileReader::stop(void)
{
    if (!isStarted())
        return; // Nothing to do.

    m_cancelEvent.setSignaled();

    // Join thread.
    join();

    m_cancelEvent.reset();

    m_handle = INVALID_HANDLE_VALUE;
}

// TestLogReader

TestLogReader::TestLogReader(void)
    : m_logBuffer(LOG_BUFFER_BLOCK_SIZE, LOG_BUFFER_NUM_BLOCKS)
    , m_logFile(INVALID_HANDLE_VALUE)
    , m_reader(&m_logBuffer)
{
}

TestLogReader::~TestLogReader(void)
{
    if (m_logFile != INVALID_HANDLE_VALUE)
        CloseHandle(m_logFile);
}

void TestLogReader::start(const char *filename)
{
    DE_ASSERT(m_logFile == INVALID_HANDLE_VALUE && !m_reader.isStarted());

    m_logFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, DE_NULL,
                           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, DE_NULL);

    if (m_logFile == INVALID_HANDLE_VALUE)
        throw Error(GetLastError(), "Failed to open log file");

    m_reader.start(m_logFile);
}

void TestLogReader::stop(void)
{
    if (!m_reader.isStarted())
        return; // Nothing to do.

    m_logBuffer.cancel();
    m_reader.stop();

    CloseHandle(m_logFile);
    m_logFile = INVALID_HANDLE_VALUE;

    m_logBuffer.clear();
}

// Process

Process::Process(void)
    : m_state(STATE_NOT_STARTED)
    , m_exitCode(0)
    , m_standardIn(INVALID_HANDLE_VALUE)
    , m_standardOut(INVALID_HANDLE_VALUE)
    , m_standardErr(INVALID_HANDLE_VALUE)
{
    deMemset(&m_procInfo, 0, sizeof(m_procInfo));
}

Process::~Process(void)
{
    try
    {
        if (isRunning())
        {
            kill();
            waitForFinish();
        }
    }
    catch (...)
    {
    }

    cleanupHandles();
}

void Process::cleanupHandles(void)
{
    DE_ASSERT(!isRunning());

    if (m_standardErr != INVALID_HANDLE_VALUE)
        CloseHandle(m_standardErr);

    if (m_standardOut != INVALID_HANDLE_VALUE)
        CloseHandle(m_standardOut);

    if (m_standardIn != INVALID_HANDLE_VALUE)
        CloseHandle(m_standardIn);

    if (m_procInfo.hProcess)
        CloseHandle(m_procInfo.hProcess);

    if (m_procInfo.hThread)
        CloseHandle(m_procInfo.hThread);

    m_standardErr = INVALID_HANDLE_VALUE;
    m_standardOut = INVALID_HANDLE_VALUE;
    m_standardIn  = INVALID_HANDLE_VALUE;

    deMemset(&m_procInfo, 0, sizeof(m_procInfo));
}

__declspec(thread) static int t_pipeNdx = 0;

static void createPipeWithOverlappedIO(HANDLE *readHandleOut, HANDLE *writeHandleOut, uint32_t readMode,
                                       uint32_t writeMode, SECURITY_ATTRIBUTES *securityAttr)
{
    const int defaultBufSize = 4096;
    char pipeName[128];
    HANDLE readHandle;
    HANDLE writeHandle;

    DE_ASSERT(((readMode | writeMode) & ~FILE_FLAG_OVERLAPPED) == 0);

    deSprintf(pipeName, sizeof(pipeName), "\\\\.\\Pipe\\dEQP-ExecServer-%08x-%08x-%08x", GetCurrentProcessId(),
              GetCurrentThreadId(), t_pipeNdx++);

    readHandle = CreateNamedPipe(pipeName,                       /* Pipe name.                */
                                 PIPE_ACCESS_INBOUND | readMode, /* Open mode.                */
                                 PIPE_TYPE_BYTE | PIPE_WAIT,     /* Pipe flags.                */
                                 1,                              /* Max number of instances.    */
                                 defaultBufSize,                 /* Output buffer size.        */
                                 defaultBufSize,                 /* Input buffer size.        */
                                 0,                              /* Use default timeout.        */
                                 securityAttr);

    if (readHandle == INVALID_HANDLE_VALUE)
        throw Error(GetLastError(), "CreateNamedPipe() failed");

    writeHandle = CreateFile(pipeName, GENERIC_WRITE,           /* Access mode.                */
                             0,                                 /* No sharing.                */
                             securityAttr, OPEN_EXISTING,       /* Assume existing object.    */
                             FILE_ATTRIBUTE_NORMAL | writeMode, /* Open mode / flags.        */
                             DE_NULL /* Template file.            */);

    if (writeHandle == INVALID_HANDLE_VALUE)
    {
        DWORD openErr = GetLastError();
        CloseHandle(readHandle);
        throw Error(openErr, "Failed to open created pipe, CreateFile() failed");
    }

    *readHandleOut  = readHandle;
    *writeHandleOut = writeHandle;
}

void Process::start(const char *commandLine, const char *workingDirectory)
{
    // Pipes.
    HANDLE stdInRead   = INVALID_HANDLE_VALUE;
    HANDLE stdInWrite  = INVALID_HANDLE_VALUE;
    HANDLE stdOutRead  = INVALID_HANDLE_VALUE;
    HANDLE stdOutWrite = INVALID_HANDLE_VALUE;
    HANDLE stdErrRead  = INVALID_HANDLE_VALUE;
    HANDLE stdErrWrite = INVALID_HANDLE_VALUE;

    if (m_state == STATE_RUNNING)
        throw std::runtime_error("Process already running");
    else if (m_state == STATE_FINISHED)
    {
        // Process finished, clean up old cruft.
        cleanupHandles();
        m_state = STATE_NOT_STARTED;
    }

    // Create pipes
    try
    {
        SECURITY_ATTRIBUTES securityAttr;
        STARTUPINFO startInfo;

        deMemset(&startInfo, 0, sizeof(startInfo));
        deMemset(&securityAttr, 0, sizeof(securityAttr));

        // Security attributes for inheriting handle.
        securityAttr.nLength              = sizeof(SECURITY_ATTRIBUTES);
        securityAttr.bInheritHandle       = TRUE;
        securityAttr.lpSecurityDescriptor = DE_NULL;

        createPipeWithOverlappedIO(&stdInRead, &stdInWrite, 0, FILE_FLAG_OVERLAPPED, &securityAttr);
        createPipeWithOverlappedIO(&stdOutRead, &stdOutWrite, FILE_FLAG_OVERLAPPED, 0, &securityAttr);
        createPipeWithOverlappedIO(&stdErrRead, &stdErrWrite, FILE_FLAG_OVERLAPPED, 0, &securityAttr);

        if (!SetHandleInformation(stdInWrite, HANDLE_FLAG_INHERIT, 0) ||
            !SetHandleInformation(stdOutRead, HANDLE_FLAG_INHERIT, 0) ||
            !SetHandleInformation(stdErrRead, HANDLE_FLAG_INHERIT, 0))
            throw Error(GetLastError(), "SetHandleInformation() failed");

        // Startup info for process.
        startInfo.cb         = sizeof(startInfo);
        startInfo.hStdError  = stdErrWrite;
        startInfo.hStdOutput = stdOutWrite;
        startInfo.hStdInput  = stdInRead;
        startInfo.dwFlags |= STARTF_USESTDHANDLES;

        if (!CreateProcess(DE_NULL, (LPTSTR)commandLine, DE_NULL, DE_NULL, TRUE /* inherit handles */, 0, DE_NULL,
                           workingDirectory, &startInfo, &m_procInfo))
            throw Error(GetLastError(), "CreateProcess() failed");
    }
    catch (...)
    {
        if (stdInRead != INVALID_HANDLE_VALUE)
            CloseHandle(stdInRead);
        if (stdInWrite != INVALID_HANDLE_VALUE)
            CloseHandle(stdInWrite);
        if (stdOutRead != INVALID_HANDLE_VALUE)
            CloseHandle(stdOutRead);
        if (stdOutWrite != INVALID_HANDLE_VALUE)
            CloseHandle(stdOutWrite);
        if (stdErrRead != INVALID_HANDLE_VALUE)
            CloseHandle(stdErrRead);
        if (stdErrWrite != INVALID_HANDLE_VALUE)
            CloseHandle(stdErrWrite);
        throw;
    }

    // Store handles to be kept.
    m_standardIn  = stdInWrite;
    m_standardOut = stdOutRead;
    m_standardErr = stdErrRead;

    // Close other ends of handles.
    CloseHandle(stdErrWrite);
    CloseHandle(stdOutWrite);
    CloseHandle(stdInRead);

    m_state = STATE_RUNNING;
}

bool Process::isRunning(void)
{
    if (m_state == STATE_RUNNING)
    {
        int exitCode;
        BOOL result = GetExitCodeProcess(m_procInfo.hProcess, (LPDWORD)&exitCode);

        if (result != TRUE)
            throw Error(GetLastError(), "GetExitCodeProcess() failed");

        if (exitCode == STILL_ACTIVE)
            return true;
        else
        {
            // Done.
            m_exitCode = exitCode;
            m_state    = STATE_FINISHED;
            return false;
        }
    }
    else
        return false;
}

void Process::waitForFinish(void)
{
    if (m_state == STATE_RUNNING)
    {
        if (WaitForSingleObject(m_procInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
            throw Error(GetLastError(), "Waiting for process failed, WaitForSingleObject() failed");

        if (isRunning())
            throw std::runtime_error("Process is still alive");
    }
    else
        throw std::runtime_error("Process is not running");
}

void Process::stopProcess(bool kill)
{
    if (m_state == STATE_RUNNING)
    {
        if (!TerminateProcess(m_procInfo.hProcess, kill ? -1 : 0))
            throw Error(GetLastError(), "TerminateProcess() failed");
    }
    else
        throw std::runtime_error("Process is not running");
}

void Process::terminate(void)
{
    stopProcess(false);
}

void Process::kill(void)
{
    stopProcess(true);
}

} // namespace win32

Win32TestProcess::Win32TestProcess(void)
    : m_process(DE_NULL)
    , m_processStartTime(0)
    , m_infoBuffer(INFO_BUFFER_BLOCK_SIZE, INFO_BUFFER_NUM_BLOCKS)
    , m_stdOutReader(&m_infoBuffer)
    , m_stdErrReader(&m_infoBuffer)
{
}

Win32TestProcess::~Win32TestProcess(void)
{
    delete m_process;
}

void Win32TestProcess::start(const char *name, const char *params, const char *workingDir, const char *caseList)
{
    bool hasCaseList = strlen(caseList) > 0;

    XS_CHECK(!m_process);

    de::FilePath logFilePath = de::FilePath::join(workingDir, "TestResults.qpa");
    m_logFileName            = logFilePath.getPath();

    // Remove old file if such exists.
    // \note Sometimes on Windows the test process dies slowly and may not release handle to log file
    //         until a bit later.
    // \todo [2013-07-15 pyry] This should be solved by improving deProcess and killing all child processes as well.
    {
        int tryNdx = 0;
        while (tryNdx < MAX_OLD_LOGFILE_DELETE_ATTEMPTS && deFileExists(m_logFileName.c_str()))
        {
            if (deDeleteFile(m_logFileName.c_str()))
                break;
            deSleep(LOGFILE_DELETE_SLEEP_MS);
            tryNdx += 1;
        }

        if (deFileExists(m_logFileName.c_str()))
            throw TestProcessException(string("Failed to remove '") + m_logFileName + "'");
    }

    // Construct command line.
    string cmdLine =
        de::FilePath(name).isAbsolutePath() ? name : de::FilePath::join(workingDir, name).normalize().getPath();
    cmdLine += string(" --deqp-log-filename=") + logFilePath.getBaseName();

    if (hasCaseList)
        cmdLine += " --deqp-stdin-caselist";

    if (strlen(params) > 0)
        cmdLine += string(" ") + params;

    DE_ASSERT(!m_process);
    m_process = new win32::Process();

    try
    {
        m_process->start(cmdLine.c_str(), strlen(workingDir) > 0 ? workingDir : DE_NULL);
    }
    catch (const std::exception &e)
    {
        delete m_process;
        m_process = DE_NULL;
        throw TestProcessException(e.what());
    }

    m_processStartTime = deGetMicroseconds();

    // Create stdout & stderr readers.
    m_stdOutReader.start(m_process->getStdOut());
    m_stdErrReader.start(m_process->getStdErr());

    // Start case list writer.
    if (hasCaseList)
        m_caseListWriter.start(caseList, m_process->getStdIn());
}

void Win32TestProcess::terminate(void)
{
    if (m_process)
    {
        try
        {
            m_process->kill();
        }
        catch (const std::exception &e)
        {
            printf("Win32TestProcess::terminate(): Failed to kill process: %s\n", e.what());
        }
    }
}

void Win32TestProcess::cleanup(void)
{
    m_caseListWriter.stop();

    // \note Buffers must be canceled before stopping readers.
    m_infoBuffer.cancel();

    m_stdErrReader.stop();
    m_stdOutReader.stop();
    m_testLogReader.stop();

    // Reset buffers.
    m_infoBuffer.clear();

    if (m_process)
    {
        try
        {
            if (m_process->isRunning())
            {
                m_process->kill();
                m_process->waitForFinish();
            }
        }
        catch (const std::exception &e)
        {
            printf("Win32TestProcess::cleanup(): Failed to kill process: %s\n", e.what());
        }

        delete m_process;
        m_process = DE_NULL;
    }
}

int Win32TestProcess::readTestLog(uint8_t *dst, int numBytes)
{
    if (!m_testLogReader.isRunning())
    {
        if (deGetMicroseconds() - m_processStartTime > LOG_FILE_TIMEOUT * 1000)
        {
            // Timeout, kill process.
            terminate();
            return 0; // \todo [2013-08-13 pyry] Throw exception?
        }

        if (!deFileExists(m_logFileName.c_str()))
            return 0;

        // Start reader.
        m_testLogReader.start(m_logFileName.c_str());
    }

    DE_ASSERT(m_testLogReader.isRunning());
    return m_testLogReader.read(dst, numBytes);
}

bool Win32TestProcess::isRunning(void)
{
    if (m_process)
        return m_process->isRunning();
    else
        return false;
}

int Win32TestProcess::getExitCode(void) const
{
    if (m_process)
        return m_process->getExitCode();
    else
        return -1;
}

} // namespace xs
