#include "File.h"
#include "FileLogger.h"
#include <streambuf>
#include <fstream>

File::File(std::filesystem::path path)
    : mFullPath(path),
      mInHandle(),
      mOutHandle(),
      mAccessMode(AccessMode::Read)
{

}

std::string File::GetExtension() const
{
    return mFullPath.extension().string();
}

void File::SetAccessMode(AccessMode mode)
{
    mAccessMode = mode;
}

std::ifstream* File::GetInHandle() const
{
    return mInHandle.get();
}

std::ofstream* File::GetOutHandle() const
{
    return mOutHandle.get();
}

void File::Open(bool asBinary)
{
    if(mAccessMode == AccessMode::Read)
    {
        auto flags = std::ifstream::in;
        if (asBinary)
        {
            //flags |= std::ifstream::binary;
        }
        mInHandle = std::make_unique<std::ifstream>();
        mInHandle->open(mFullPath, flags);
    }
    else
    {
        auto flags = std::ofstream::out;
        if (asBinary)
        {
            //flags |= std::ofstream::binary;
        }
        mOutHandle = std::make_unique<std::ofstream>();
        mOutHandle->open(mFullPath, flags);
    }
}

void File::Close()
{
    if(mOutHandle)
    {
        mOutHandle->close();
    }
    if(mInHandle)
    {
        mInHandle->close();
    }
}

FileFormat::Format File::InferFormat() const
{
    const auto extension = GetExtension();
    return FileFormat::InferFormat(extension);
}

void File::WriteText(const std::string& text)
{
    bool had_to_open{ false };
    if (!mOutHandle)
    {
        had_to_open = true;
        SetAccessMode(File::AccessMode::Write);
        Open();
    }

    (*mOutHandle) << text;

    if (had_to_open)
    {
        Close();
    }
}

std::vector<std::string> File::readLines()
{
    std::vector<std::string> content;

    if (!PathExists())
    {
        return content;
    }

    Open(false);

    std::string str;
    while(std::getline(*mInHandle, str))
    {
        content.push_back(str);
    }

    Close();
    return content;
}

std::string File::getBaseFilename(const Path& path)
{
    return path.stem().string();
}

std::string File::ReadText()
{
    std::string str((std::istreambuf_iterator<char>(*mInHandle)),
                     std::istreambuf_iterator<char>());
    return str;
}

bool File::PathExists() const
{
    return std::filesystem::exists(mFullPath);
}
