// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <assert.h>
#include <launchpad/launchpad.h>
#include <launchpad/vmo.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/object.h>
#include <memory>
#include <lib/fdio/io.h>
#include <lib/fdio/util.h>
#include <string>
#include <unistd.h>

#include "deProcess.h"

#if (DE_OS != DE_OS_FUCHSIA)
#error DE_OS_FUCHSIA expected
#endif

#include "deCommandLine.h"

struct deProcess_s {
};

class DeProcess : public deProcess_s {
public:
    static std::unique_ptr<DeProcess> Create()
    {
      zx_handle_t job_copy = ZX_HANDLE_INVALID;
      zx_handle_duplicate(zx_job_default(), ZX_RIGHT_SAME_RIGHTS, &job_copy);

      launchpad_t *lp;
      zx_status_t status = launchpad_create(job_copy, "DeProcess", &lp);
      if (status != ZX_OK)
        return std::unique_ptr<DeProcess>();

      return std::unique_ptr<DeProcess>(new DeProcess(lp));
    }

    DeProcess(launchpad_t* lp)
        : lp_(lp), proc_(ZX_HANDLE_INVALID), fstdin_(nullptr), fstdout_(nullptr), fstderr_(nullptr)
    {
    }

    ~DeProcess()
    {
        if (lp_)
            launchpad_destroy(lp_);
        if (proc_ != ZX_HANDLE_INVALID)
            zx_handle_close(proc_);
        closeStdIn();
        closeStdOut();
        closeStdErr();
    }

    launchpad_t* launchpad() { return lp_; }

    bool start()
    {
        zx_status_t status;
        status = launchpad_add_pipe(launchpad(), &remote_stdin_fd_, STDIN_FILENO);
        assert(status == ZX_OK);

        int stdout_fd;
        status = launchpad_add_pipe(launchpad(), &stdout_fd, STDOUT_FILENO);
        assert(status == ZX_OK);

        int stderr_fd;
        status = launchpad_add_pipe(launchpad(), &stderr_fd, STDERR_FILENO);
        assert(status == ZX_OK);

        fstdin_ = deFile_createFromHandle(remote_stdin_fd_);
        fstdout_ = deFile_createFromHandle(stdout_fd);
        fstderr_ = deFile_createFromHandle(stderr_fd);

        const char* errmsg = NULL;
        status = launchpad_go(lp_, &proc_, &errmsg);
        lp_ = nullptr;

        if (status != ZX_OK)
            return false;

        return true;
    }

    bool IsRunning()
    {
        zx_signals_t pending = 0;
        zx_status_t status = zx_object_wait_one(proc_, ZX_TASK_TERMINATED, 0, &pending);
        if (pending & ZX_TASK_TERMINATED)
            return false;
        assert(status == ZX_ERR_TIMED_OUT);
        return true;
    }

    bool Wait()
    {
        zx_status_t status = zx_object_wait_one(proc_, ZX_TASK_TERMINATED, ZX_TIME_INFINITE, NULL);
        return status == ZX_OK;
    }

    int GetExitCode()
    {
        zx_info_process_t info;
        zx_status_t status =
            zx_object_get_info(proc_, ZX_INFO_PROCESS, &info, sizeof(info), NULL, NULL);
        assert(status == ZX_OK);
        return info.return_code;
    }

    static DeProcess* cast(deProcess* process) { return static_cast<DeProcess*>(process); }

    deFile* fstdin() { return fstdin_; }
    deFile* fstdout() { return fstdout_; }
    deFile* fstderr() { return fstderr_; }

    void closeStdIn()
    {
        if (fstdin_) {
            deFile_destroy(fstdin_);
            fstdin_ = nullptr;
        }
    }

    void closeStdOut()
    {
        if (fstdout_) {
            deFile_destroy(fstdout_);
            fstdout_ = nullptr;
        }
    }

    void closeStdErr()
    {
        if (fstderr_) {
            deFile_destroy(fstderr_);
            fstderr_ = nullptr;
        }
    }

private:
    launchpad_t* lp_;
    zx_handle_t proc_;
    int remote_stdin_fd_;
    deFile* fstdin_;
    deFile* fstdout_;
    deFile* fstderr_;
};

deProcess* deProcess_create()
{
    std::unique_ptr<DeProcess> process = DeProcess::Create();
    if (!process)
        return nullptr;

    return process.release();
}

void deProcess_destroy(deProcess* process) { delete DeProcess::cast(process); }

deBool deProcess_start(deProcess* de_process, const char* commandLine, const char* workingDirectory)
{
    (void)workingDirectory;

    DeProcess* process = DeProcess::cast(de_process);

    deCommandLine* cmdLine = deCommandLine_parse(commandLine);

    zx_status_t status;
    status = launchpad_set_args(process->launchpad(), cmdLine->numArgs - 1,
                                (const char *const *)&cmdLine->args[1]);
    if (status != ZX_OK)
      fprintf(stderr, "launcpad_set_args failed: %d\n", status);
    assert(status == ZX_OK);

    status = launchpad_clone(process->launchpad(), LP_CLONE_FDIO_NAMESPACE | LP_CLONE_ENVIRON);
    assert(status == ZX_OK);
    if (status != ZX_OK)
      fprintf(stderr, "launchpad_clone failed: %d\n", status);

    status = launchpad_load_from_file(process->launchpad(), cmdLine->args[0]);
    if (status != ZX_OK)
      fprintf(stderr, "launchpad_load_from_file failed: %d\n", status);
    assert(status == ZX_OK);

    if (!process->start())
        return false;

    return true;
}

deBool deProcess_isRunning(deProcess* process) { return DeProcess::cast(process)->IsRunning(); }

deBool deProcess_waitForFinish(deProcess* process)
{
    return DeProcess::cast(process)->Wait() ? DE_TRUE : DE_FALSE;
}

const char* deProcess_getLastError(const deProcess*) { return nullptr; }

int deProcess_getExitCode(const deProcess* process)
{
    return DeProcess::cast((deProcess*)process)->GetExitCode();
}

deBool deProcess_terminate(deProcess*)
{
    printf("%s:%d Not implemented\n", __FILE__, __LINE__);
    return DE_FALSE;
}

deBool deProcess_kill(deProcess*)
{
    printf("%s:%d Not implemented\n", __FILE__, __LINE__);
    return DE_FALSE;
}

deFile* deProcess_getStdIn(deProcess* process) { return DeProcess::cast(process)->fstdin(); }

deFile* deProcess_getStdOut(deProcess* process) { return DeProcess::cast(process)->fstdout(); }

deFile* deProcess_getStdErr(deProcess* process) { return DeProcess::cast(process)->fstderr(); }

deBool deProcess_closeStdIn(deProcess* process)
{
    DeProcess::cast(process)->closeStdIn();
    return DE_TRUE;
}

deBool deProcess_closeStdOut(deProcess* process)
{
    DeProcess::cast(process)->closeStdOut();
    return DE_TRUE;
}

deBool deProcess_closeStdErr(deProcess* process)
{
    DeProcess::cast(process)->closeStdErr();
    return DE_TRUE;
}
