//===-- SBPlatform.cpp ------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/API/SBPlatform.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBUnixSignals.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/File.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Platform.h"

#include <functional>

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// PlatformConnectOptions
//----------------------------------------------------------------------
struct PlatformConnectOptions {
    PlatformConnectOptions(const char *url = NULL) :
        m_url(),
        m_rsync_options(),
        m_rsync_remote_path_prefix(),
        m_rsync_enabled(false),
        m_rsync_omit_hostname_from_remote_path(false),
        m_local_cache_directory ()
    {
        if (url && url[0])
            m_url = url;
    }
    
    ~PlatformConnectOptions()
    {
    }

    std::string m_url;
    std::string m_rsync_options;
    std::string m_rsync_remote_path_prefix;
    bool m_rsync_enabled;
    bool m_rsync_omit_hostname_from_remote_path;
    ConstString m_local_cache_directory;
};

//----------------------------------------------------------------------
// PlatformShellCommand
//----------------------------------------------------------------------
struct PlatformShellCommand {
    PlatformShellCommand(const char *shell_command = NULL) :
        m_command(),
        m_working_dir(),
        m_status(0),
        m_signo(0),
        m_timeout_sec(UINT32_MAX)
    {
        if (shell_command && shell_command[0])
            m_command = shell_command;
    }
    
    ~PlatformShellCommand()
    {
    }
    
    std::string m_command;
    std::string m_working_dir;
    std::string m_output;
    int m_status;
    int m_signo;
    uint32_t m_timeout_sec;
};
//----------------------------------------------------------------------
// SBPlatformConnectOptions
//----------------------------------------------------------------------
SBPlatformConnectOptions::SBPlatformConnectOptions (const char *url) :
    m_opaque_ptr(new PlatformConnectOptions(url))
{
    
}

SBPlatformConnectOptions::SBPlatformConnectOptions(const SBPlatformConnectOptions &rhs) :
    m_opaque_ptr(new PlatformConnectOptions())
{
    *m_opaque_ptr = *rhs.m_opaque_ptr;
}
    
SBPlatformConnectOptions::~SBPlatformConnectOptions ()
{
    delete m_opaque_ptr;
}

void
SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs)
{
    *m_opaque_ptr = *rhs.m_opaque_ptr;
}

const char *
SBPlatformConnectOptions::GetURL()
{
    if (m_opaque_ptr->m_url.empty())
        return NULL;
    return m_opaque_ptr->m_url.c_str();
}
    
void
SBPlatformConnectOptions::SetURL(const char *url)
{
    if (url && url[0])
        m_opaque_ptr->m_url = url;
    else
        m_opaque_ptr->m_url.clear();
}

bool
SBPlatformConnectOptions::GetRsyncEnabled()
{
    return m_opaque_ptr->m_rsync_enabled;
}
    
void
SBPlatformConnectOptions::EnableRsync (const char *options,
                                       const char *remote_path_prefix,
                                       bool omit_hostname_from_remote_path)
{
    m_opaque_ptr->m_rsync_enabled = true;
    m_opaque_ptr->m_rsync_omit_hostname_from_remote_path = omit_hostname_from_remote_path;
    if (remote_path_prefix && remote_path_prefix[0])
        m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
    else
        m_opaque_ptr->m_rsync_remote_path_prefix.clear();

    if (options && options[0])
        m_opaque_ptr->m_rsync_options = options;
    else
        m_opaque_ptr->m_rsync_options.clear();

}

void
SBPlatformConnectOptions::DisableRsync ()
{
    m_opaque_ptr->m_rsync_enabled = false;
}
    
const char *
SBPlatformConnectOptions::GetLocalCacheDirectory()
{
    return m_opaque_ptr->m_local_cache_directory.GetCString();
}
    
void
SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path)
{
    if (path && path[0])
        m_opaque_ptr->m_local_cache_directory.SetCString(path);
    else
        m_opaque_ptr->m_local_cache_directory = ConstString();
}

//----------------------------------------------------------------------
// SBPlatformShellCommand
//----------------------------------------------------------------------
SBPlatformShellCommand::SBPlatformShellCommand (const char *shell_command) :
    m_opaque_ptr(new PlatformShellCommand(shell_command))
{
}

SBPlatformShellCommand::SBPlatformShellCommand (const SBPlatformShellCommand &rhs) :
    m_opaque_ptr(new PlatformShellCommand())
{
    *m_opaque_ptr = *rhs.m_opaque_ptr;
}

SBPlatformShellCommand::~SBPlatformShellCommand()
{
    delete m_opaque_ptr;
}

void
SBPlatformShellCommand::Clear()
{
    m_opaque_ptr->m_output = std::move(std::string());
    m_opaque_ptr->m_status = 0;
    m_opaque_ptr->m_signo = 0;
}

const char *
SBPlatformShellCommand::GetCommand()
{
    if (m_opaque_ptr->m_command.empty())
        return NULL;
    return m_opaque_ptr->m_command.c_str();
}

void
SBPlatformShellCommand::SetCommand(const char *shell_command)
{
    if (shell_command && shell_command[0])
        m_opaque_ptr->m_command = shell_command;
    else
        m_opaque_ptr->m_command.clear();
}

const char *
SBPlatformShellCommand::GetWorkingDirectory ()
{
    if (m_opaque_ptr->m_working_dir.empty())
        return NULL;
    return m_opaque_ptr->m_working_dir.c_str();
}

void
SBPlatformShellCommand::SetWorkingDirectory (const char *path)
{
    if (path && path[0])
        m_opaque_ptr->m_working_dir = path;
    else
        m_opaque_ptr->m_working_dir.clear();
}

uint32_t
SBPlatformShellCommand::GetTimeoutSeconds ()
{
    return m_opaque_ptr->m_timeout_sec;
}

void
SBPlatformShellCommand::SetTimeoutSeconds (uint32_t sec)
{
    m_opaque_ptr->m_timeout_sec = sec;
}

int
SBPlatformShellCommand::GetSignal ()
{
    return m_opaque_ptr->m_signo;
}

int
SBPlatformShellCommand::GetStatus ()
{
    return m_opaque_ptr->m_status;
}

const char *
SBPlatformShellCommand::GetOutput ()
{
    if (m_opaque_ptr->m_output.empty())
        return NULL;
    return m_opaque_ptr->m_output.c_str();
}

//----------------------------------------------------------------------
// SBPlatform
//----------------------------------------------------------------------
SBPlatform::SBPlatform () :
    m_opaque_sp ()
{
    
}

SBPlatform::SBPlatform (const char *platform_name) :
    m_opaque_sp ()
{
    Error error;
    if (platform_name && platform_name[0])
        m_opaque_sp = Platform::Create (ConstString(platform_name), error);
}

SBPlatform::~SBPlatform()
{
}

bool
SBPlatform::IsValid () const
{
    return m_opaque_sp.get() != NULL;
}

void
SBPlatform::Clear ()
{
    m_opaque_sp.reset();
}

const char *
SBPlatform::GetName ()
{
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
        return platform_sp->GetName().GetCString();
    return NULL;
}

lldb::PlatformSP
SBPlatform::GetSP () const
{
    return m_opaque_sp;
}

void
SBPlatform::SetSP (const lldb::PlatformSP& platform_sp)
{
    m_opaque_sp = platform_sp;
}

const char *
SBPlatform::GetWorkingDirectory()
{
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
        return platform_sp->GetWorkingDirectory().GetCString();
    return NULL;
}

bool
SBPlatform::SetWorkingDirectory(const char *path)
{
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
    {
        if (path)
            platform_sp->SetWorkingDirectory(FileSpec{path, false});
        else
            platform_sp->SetWorkingDirectory(FileSpec{});
        return true;
    }
    return false;
}

SBError
SBPlatform::ConnectRemote (SBPlatformConnectOptions &connect_options)
{
    SBError sb_error;
    PlatformSP platform_sp(GetSP());
    if (platform_sp && connect_options.GetURL())
    {
        Args args;
        args.AppendArgument(connect_options.GetURL());
        sb_error.ref() = platform_sp->ConnectRemote(args);
    }
    else
    {
        sb_error.SetErrorString("invalid platform");
    }
    return sb_error;
}

void
SBPlatform::DisconnectRemote ()
{
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
        platform_sp->DisconnectRemote();
}

bool
SBPlatform::IsConnected()
{
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
        platform_sp->IsConnected();
    return false;
}

const char *
SBPlatform::GetTriple()
{
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
    {
        ArchSpec arch(platform_sp->GetSystemArchitecture());
        if (arch.IsValid())
        {
            // Const-ify the string so we don't need to worry about the lifetime of the string
            return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
        }
    }
    return NULL;
}

const char *
SBPlatform::GetOSBuild()
{
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
    {
        std::string s;
        if (platform_sp->GetOSBuildString(s))
        {
            if (!s.empty())
            {
                // Const-ify the string so we don't need to worry about the lifetime of the string
                return ConstString(s.c_str()).GetCString();
            }
        }
    }
    return NULL;
}

const char *
SBPlatform::GetOSDescription()
{
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
    {
        std::string s;
        if (platform_sp->GetOSKernelDescription(s))
        {
            if (!s.empty())
            {
                // Const-ify the string so we don't need to worry about the lifetime of the string
                return ConstString(s.c_str()).GetCString();
            }
        }
    }
    return NULL;
}

const char *
SBPlatform::GetHostname ()
{
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
        return platform_sp->GetHostname();
    return NULL;
}

uint32_t
SBPlatform::GetOSMajorVersion ()
{
    uint32_t major, minor, update;
    PlatformSP platform_sp(GetSP());
    if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
        return major;
    return UINT32_MAX;
    
}

uint32_t
SBPlatform::GetOSMinorVersion ()
{
    uint32_t major, minor, update;
    PlatformSP platform_sp(GetSP());
    if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
        return minor;
    return UINT32_MAX;
}

uint32_t
SBPlatform::GetOSUpdateVersion ()
{
    uint32_t major, minor, update;
    PlatformSP platform_sp(GetSP());
    if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
        return update;
    return UINT32_MAX;
}

SBError
SBPlatform::Get (SBFileSpec &src,
                 SBFileSpec &dst)
{
    SBError sb_error;
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
    {
        sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());
    }
    else
    {
        sb_error.SetErrorString("invalid platform");
    }
    return sb_error;
}

SBError
SBPlatform::Put (SBFileSpec &src,
                 SBFileSpec &dst)
{
  return ExecuteConnected(
      [&](const lldb::PlatformSP& platform_sp)
      {
          if (src.Exists())
          {
              uint32_t permissions = src.ref().GetPermissions();
              if (permissions == 0)
              {
                  if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory)
                      permissions = eFilePermissionsDirectoryDefault;
                  else
                      permissions = eFilePermissionsFileDefault;
              }

              return platform_sp->PutFile(src.ref(), dst.ref(), permissions);
          }

          Error error;
          error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
          return error;
      });
}

SBError
SBPlatform::Install (SBFileSpec &src,
                     SBFileSpec &dst)
{
  return ExecuteConnected(
      [&](const lldb::PlatformSP& platform_sp)
      {
          if (src.Exists())
              return platform_sp->Install(src.ref(), dst.ref());

          Error error;
          error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
          return error;
      });
}


SBError
SBPlatform::Run (SBPlatformShellCommand &shell_command)
{
    return ExecuteConnected(
        [&](const lldb::PlatformSP& platform_sp)
        {
            const char *command = shell_command.GetCommand();
            if (!command)
                return Error("invalid shell command (empty)");

            const char *working_dir = shell_command.GetWorkingDirectory();
            if (working_dir == NULL)
            {
                working_dir = platform_sp->GetWorkingDirectory().GetCString();
                if (working_dir)
                    shell_command.SetWorkingDirectory(working_dir);
            }
            return platform_sp->RunShellCommand(command,
                                                FileSpec{working_dir, false},
                                                &shell_command.m_opaque_ptr->m_status,
                                                &shell_command.m_opaque_ptr->m_signo,
                                                &shell_command.m_opaque_ptr->m_output,
                                                shell_command.m_opaque_ptr->m_timeout_sec);
        });
}

SBError
SBPlatform::Launch (SBLaunchInfo &launch_info)
{
    return ExecuteConnected(
        [&](const lldb::PlatformSP& platform_sp)
        {
            return platform_sp->LaunchProcess(launch_info.ref());
        });
}

SBError
SBPlatform::Kill (const lldb::pid_t pid)
{
    return ExecuteConnected(
        [&](const lldb::PlatformSP& platform_sp)
        {
            return platform_sp->KillProcess(pid);
        });
}

SBError
SBPlatform::ExecuteConnected (const std::function<Error(const lldb::PlatformSP&)>& func)
{
    SBError sb_error;
    const auto platform_sp(GetSP());
    if (platform_sp)
    {
        if (platform_sp->IsConnected())
            sb_error.ref() = func(platform_sp);
        else
            sb_error.SetErrorString("not connected");
    }
    else
        sb_error.SetErrorString("invalid platform");

  return sb_error;
}

SBError
SBPlatform::MakeDirectory (const char *path, uint32_t file_permissions)
{
    SBError sb_error;
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
    {
        sb_error.ref() = platform_sp->MakeDirectory(FileSpec{path, false}, file_permissions);
    }
    else
    {
        sb_error.SetErrorString("invalid platform");
    }
    return sb_error;
}

uint32_t
SBPlatform::GetFilePermissions (const char *path)
{
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
    {
        uint32_t file_permissions = 0;
        platform_sp->GetFilePermissions(FileSpec{path, false}, file_permissions);
        return file_permissions;
    }
    return 0;
    
}

SBError
SBPlatform::SetFilePermissions (const char *path, uint32_t file_permissions)
{
    SBError sb_error;
    PlatformSP platform_sp(GetSP());
    if (platform_sp)
    {
        sb_error.ref() = platform_sp->SetFilePermissions(FileSpec{path, false}, file_permissions);
    }
    else
    {
        sb_error.SetErrorString("invalid platform");
    }
    return sb_error;
    
}

SBUnixSignals
SBPlatform::GetUnixSignals() const
{
    if (auto platform_sp = GetSP())
        return SBUnixSignals{platform_sp};

    return {};
}
