#include "../include/System/IO/DriveInfo.h"
#include <windows.h>

namespace System::IO {
    DriveType toDriveType(UINT type) {
        switch (type) {
            case DRIVE_REMOVABLE:    return DriveType::Removable;
            case DRIVE_FIXED:        return DriveType::Fixed;
            case DRIVE_REMOTE:       return DriveType::Remote;
            case DRIVE_CDROM:        return DriveType::CDROM;
            case DRIVE_RAMDISK:      return DriveType::RAM;
            case DRIVE_NO_ROOT_DIR:  return DriveType::NoRootDir;
            default:                 return DriveType::Unknown;
        }
    }

    DriveInfo::DriveInfo(const std::wstring& path)
        : rootPath(path)
    {
        Name = rootPath;
        UINT type = GetDriveTypeW(rootPath.c_str());
        DriveType = toDriveType(type);
        IsReady = (type != DRIVE_NO_ROOT_DIR);

        WCHAR fsName[MAX_PATH] = {0};
        if (GetVolumeInformationW(rootPath.c_str(), nullptr, 0, nullptr, nullptr, nullptr, fsName, MAX_PATH)) {
            DriveFormat = fsName;
        } else {
            DriveFormat.clear();
        }

        ULARGE_INTEGER total, free, available;
        if (GetDiskFreeSpaceExW(rootPath.c_str(), &available, &total, &free)) {
            TotalSize = total.QuadPart;
            AvailableFreeSpace = available.QuadPart;
        } else {
            TotalSize = 0;
            AvailableFreeSpace = 0;
        }
    }

    std::vector<DriveInfo> DriveInfo::GetDrives() {
        std::vector<DriveInfo> drives;
        WCHAR buffer[256] = {0};
        DWORD len = GetLogicalDriveStringsW(256, buffer);
        for (WCHAR* p = buffer; *p; p += wcslen(p) + 1) {
            drives.emplace_back(p);
        }
        return drives;
    }
}