#include <windows.h>
#include <stdexcept>

#include "../include/System/IO/File.h"

namespace System::IO {
    File::File(const std::wstring& filePath) : path(filePath) { }

    std::wstring File::GetPath() const {
        return path;
    }

    DWORD File::GetAttributes(const std::wstring& path) {
        return GetFileAttributesW(path.c_str());
    }

    bool File::SetAttributes(const std::wstring& path, DWORD attributes) {
        return SetFileAttributesW(path.c_str(), attributes) != FALSE;
    }

    bool File::Exists(const std::wstring& path) {
        DWORD attributes = GetFileAttributesW(path.c_str());
        return (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY));
    }

    bool File::Copy(const std::wstring& source, const std::wstring& destination, bool overwrite) {
        return CopyFileW(source.c_str(), destination.c_str(), overwrite ? FALSE : TRUE) != 0;
    }

    bool File::Delete(const std::wstring& path) {
        return DeleteFileW(path.c_str()) != 0;
    }

    bool File::Move(const std::wstring& source, const std::wstring& destination) {
        return MoveFileExW(source.c_str(), destination.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
    }
    
    uint64_t File::GetSize(const std::wstring& path) {
        HANDLE hFile = CreateFileW(
            path.c_str(),
            GENERIC_READ,
            FILE_SHARE_READ,
            nullptr,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            nullptr
        );

        if (hFile == INVALID_HANDLE_VALUE) {
            throw std::runtime_error("Unable to open file to get its size.");
        }

        LARGE_INTEGER size;
        if (!GetFileSizeEx(hFile, &size)) {
            CloseHandle(hFile);
            throw std::runtime_error("Unable to get file size.");
        }

        CloseHandle(hFile);
        return static_cast<uint64_t>(size.QuadPart);
    }
} 