#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <commdlg.h>
#include <fstream>
#include <unordered_map>
#include <string>
#include <filesystem>
#include "FileDialog.h"

// Correctly null-terminated filter strings
static std::unordered_map<FileDialogType, const char*> filters = {
    { FileDialogType::Images,  "Image Files\0*.png;*.jpg;*.jpeg;*.bmp;*.tga;*.gif;*.dds\0All Files\0*.*\0" },
    { FileDialogType::Scenes,  "CreateScene Files\0*.cene;*.cscene;*.yaml\0All Files\0*.*\0" },
    { FileDialogType::Audio,   "Audio Files\0*.mp3;*.wav;*.ogg;*.flac;*.aac\0All Files\0*.*\0" },
    { FileDialogType::Scripts, "Lua Scripts\0*.lua\0All Files\0*.*\0" },
    { FileDialogType::Shaders, "Shader Files\0*.glsl;*.vert;*.frag;*.hlsl\0All Files\0*.*\0" },
    { FileDialogType::Fonts,   "Font Files\0*.ttf;*.otf;*.fnt\0All Files\0*.*\0" },
    { FileDialogType::Models,  "3D Models\0*.obj;*.fbx;*.gltf;*.dae\0All Files\0*.*\0" },
    { FileDialogType::All,     "All Files\0*.*\0" }
};



std::string OpenFileDialog(FileDialogType type) {
    char file[260] = { 0 };
    OPENFILENAMEA ofn = {};
    ofn.lStructSize = sizeof(ofn);

    const char* filterStr = filters.count(type) ? filters[type] : filters[FileDialogType::All];
    ofn.lpstrFilter = filterStr;
    ofn.lpstrFile = file;
    ofn.nMaxFile = sizeof(file);
    ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;

    auto originalPath = std::filesystem::current_path();
    bool result = GetOpenFileNameA(&ofn);
    std::filesystem::current_path(originalPath);

    return result ? std::string(file) : "";
}

std::string SaveFileDialog(FileDialogType type) {
    char file[260] = { 0 };
    OPENFILENAMEA ofn = {};
    ofn.lStructSize = sizeof(ofn);

    const char* filterStr = filters.count(type) ? filters[type] : filters[FileDialogType::All];
    ofn.lpstrFilter = filterStr;
    ofn.lpstrFile = file;
    ofn.nMaxFile = sizeof(file);
    ofn.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR;

    auto originalPath = std::filesystem::current_path();
    bool result = GetSaveFileNameA(&ofn);
    std::filesystem::current_path(originalPath);

    return result ? std::string(file) : "";
}

std::string CreateFileDialog(FileDialogType type) {
    char file[260] = { 0 };
    OPENFILENAMEA ofn = {};
    ofn.lStructSize = sizeof(ofn);

    const char* filterStr = filters.count(type) ? filters[type] : filters[FileDialogType::All];
    ofn.lpstrFilter = filterStr;
    ofn.lpstrFile = file;
    ofn.nMaxFile = sizeof(file);
    ofn.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR;

    
    const char* defaultExt = nullptr;
    switch (type) {
        case FileDialogType::Images:  defaultExt = "png"; break;
        case FileDialogType::Scenes:  defaultExt = "cene"; break;
        case FileDialogType::Audio:   defaultExt = "mp3"; break;
        case FileDialogType::Scripts: defaultExt = "lua"; break;
        case FileDialogType::Shaders: defaultExt = "glsl"; break;
        case FileDialogType::Fonts:   defaultExt = "ttf"; break;
        case FileDialogType::Models:  defaultExt = "obj"; break;
        default:                      defaultExt = "txt"; break;
    }
    ofn.lpstrDefExt = defaultExt;

    auto originalPath = std::filesystem::current_path();
    bool result = GetSaveFileNameA(&ofn);
    std::filesystem::current_path(originalPath);

    if (result && file[0] != '\0') {
        std::filesystem::path filePath(file);

        if (!std::filesystem::exists(filePath)) {
            std::ofstream outFile(filePath, std::ios::out | std::ios::trunc);
            outFile.close();
        }

        return filePath.string();
    }

    return "";
}

