#include "FileDialog.h"
#include "Logger.h"
#include <commdlg.h>
#include <shobjidl.h>
#include <vector>

namespace UsdLayerManager {

std::string FileDialog::OpenFile(const char* filter, const char* title, HWND owner) {
    std::vector<char> filename(MAX_PATH_LENGTH, 0);
    
    OPENFILENAMEA ofn = {};
    ofn.lStructSize = sizeof(OPENFILENAMEA);
    ofn.hwndOwner = owner;
    ofn.lpstrFilter = filter;
    ofn.lpstrFile = filename.data();
    ofn.nMaxFile = MAX_PATH_LENGTH;
    ofn.lpstrTitle = title;
    ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR;
    
    if (GetOpenFileNameA(&ofn)) {
        return std::string(filename.data());
    }
    
    // User cancelled or error occurred
    DWORD error = CommDlgExtendedError();
    if (error != 0) {
        LOG_ERROR("File dialog error code: " + std::to_string(error));
    }
    
    return "";
}

std::string FileDialog::SaveFile(const char* filter, const char* title, const char* defaultExt, HWND owner) {
    std::vector<char> filename(MAX_PATH_LENGTH, 0);
    
    OPENFILENAMEA ofn = {};
    ofn.lStructSize = sizeof(OPENFILENAMEA);
    ofn.hwndOwner = owner;
    ofn.lpstrFilter = filter;
    ofn.lpstrFile = filename.data();
    ofn.nMaxFile = MAX_PATH_LENGTH;
    ofn.lpstrTitle = title;
    ofn.lpstrDefExt = defaultExt;
    ofn.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR;
    
    if (GetSaveFileNameA(&ofn)) {
        return std::string(filename.data());
    }
    
    // User cancelled or error occurred
    DWORD error = CommDlgExtendedError();
    if (error != 0) {
        LOG_ERROR("File dialog error code: " + std::to_string(error));
    }
    
    return "";
}

std::string FileDialog::BrowseFolder(const char* title, HWND owner) {
    IFileOpenDialog* pfd = nullptr;
    if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr,
                                CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd))))
        return "";

    DWORD opts = 0;
    pfd->GetOptions(&opts);
    pfd->SetOptions(opts | FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM);

    if (title) {
        int n = MultiByteToWideChar(CP_UTF8, 0, title, -1, nullptr, 0);
        std::vector<wchar_t> wt(n);
        MultiByteToWideChar(CP_UTF8, 0, title, -1, wt.data(), n);
        pfd->SetTitle(wt.data());
    }

    std::string result;
    if (SUCCEEDED(pfd->Show(owner))) {
        IShellItem* psi = nullptr;
        if (SUCCEEDED(pfd->GetResult(&psi))) {
            PWSTR path = nullptr;
            if (SUCCEEDED(psi->GetDisplayName(SIGDN_FILESYSPATH, &path)) && path) {
                int n = WideCharToMultiByte(CP_UTF8, 0, path, -1, nullptr, 0, nullptr, nullptr);
                result.resize(static_cast<size_t>(n) - 1);
                WideCharToMultiByte(CP_UTF8, 0, path, -1, result.data(), n, nullptr, nullptr);
                CoTaskMemFree(path);
            }
            psi->Release();
        }
    }
    pfd->Release();
    return result;
}

} // namespace UsdLayerManager
