#include "_scriptapi_function.h"
#include "_scriptapi_module.h"
#include "function.h"

SCRIPT_EXPORT bool Script::Function::Add(duint start, duint end, bool manual, duint instructionCount)
{
    return FunctionAdd(start, end, manual, instructionCount);
}

SCRIPT_EXPORT bool Script::Function::Add(const FunctionInfo* info)
{
    if(!info)
        return false;
    auto base = Module::BaseFromName(info->mod);
    if(!base)
        return false;
    return Add(base + info->rvaStart, base + info->rvaEnd, info->manual, info->instructioncount);
}

SCRIPT_EXPORT bool Script::Function::Get(duint addr, duint* start, duint* end, duint* instructionCount)
{
    return FunctionGet(addr, start, end, instructionCount);
}

SCRIPT_EXPORT bool Script::Function::GetInfo(duint addr, FunctionInfo* info)
{
    FUNCTIONSINFO function;
    if(!FunctionGetInfo(addr, function))
        return false;
    if(info)
    {
        strcpy_s(info->mod, function.mod().c_str());
        info->rvaStart = function.start;
        info->rvaEnd = function.end;
        info->manual = function.manual;
        info->instructioncount = function.instructioncount;
    }
    return true;
}

SCRIPT_EXPORT bool Script::Function::Overlaps(duint start, duint end)
{
    return FunctionOverlaps(start, end);
}

SCRIPT_EXPORT bool Script::Function::Delete(duint address)
{
    return FunctionDelete(address);
}

SCRIPT_EXPORT void Script::Function::DeleteRange(duint start, duint end, bool deleteManual)
{
    FunctionDelRange(start, end, deleteManual);
}

SCRIPT_EXPORT void Script::Function::DeleteRange(duint start, duint end)
{
    DeleteRange(start, end, false);
}

SCRIPT_EXPORT void Script::Function::Clear()
{
    FunctionClear();
}

SCRIPT_EXPORT bool Script::Function::GetList(ListOf(FunctionInfo) list)
{
    std::vector<FUNCTIONSINFO> functionList;
    FunctionGetList(functionList);
    std::vector<FunctionInfo> functionScriptList;
    functionScriptList.reserve(functionList.size());
    for(const auto & function : functionList)
    {
        FunctionInfo scriptFunction;
        strcpy_s(scriptFunction.mod, function.mod().c_str());
        scriptFunction.rvaStart = function.start;
        scriptFunction.rvaEnd = function.end;
        scriptFunction.manual = function.manual;
        scriptFunction.instructioncount = function.instructioncount;
        functionScriptList.push_back(scriptFunction);
    }
    return BridgeList<FunctionInfo>::CopyData(list, functionScriptList);
}
