#include <windows.h>

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

namespace System::IO {
    Directory::Directory(const std::wstring& directoryPath) : path(directoryPath) { }

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

    DWORD Directory::GetAttributes() const {
        return GetFileAttributesW(path.c_str());
    }

    bool Directory::SetAttributes(DWORD attributes) {
        return SetFileAttributesW(path.c_str(), attributes) != 0;
    }

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

    bool Directory::CreateDirectory(const std::wstring& path) {
        return CreateDirectoryW(path.c_str(), nullptr) != 0;
    }

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

    bool Directory::Move(const std::wstring& source, const std::wstring& destination) {
        return MoveFileExW(source.c_str(), destination.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
    }    

    std::vector<std::wstring> Directory::GetFiles(const std::wstring& path) {
        std::vector<std::wstring> files;
        std::wstring searchPath = path + L"\\*";
        WIN32_FIND_DATAW findData;
        HANDLE hFind = FindFirstFileW(searchPath.c_str(), &findData);
        if (hFind == INVALID_HANDLE_VALUE)
            return files;
        do {
            if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
                files.push_back(findData.cFileName);
        } while (FindNextFileW(hFind, &findData) != 0);
        FindClose(hFind);
        return files;
    }

    std::vector<std::wstring> Directory::GetDirectories(const std::wstring& path) {
        std::vector<std::wstring> directories;
        std::wstring searchPath = path + L"\\*";
        WIN32_FIND_DATAW findData;
        HANDLE hFind = FindFirstFileW(searchPath.c_str(), &findData);
        if (hFind == INVALID_HANDLE_VALUE)
            return directories;
        do {
            if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                std::wstring dirName = findData.cFileName;
                if (dirName != L"." && dirName != L"..")
                    directories.push_back(dirName);
            }
        } while (FindNextFileW(hFind, &findData) != 0);
        FindClose(hFind);
        return directories;
    }
}