#pragma once

#include <sstream>
#include <iomanip>
#include <numeric>
#include <algorithm>
#include <vector>
#include <set>
#include <filesystem>
#include <iostream>

namespace filepath
{
    std::tuple<std::filesystem::path, std::filesystem::file_status> getFileInfo(const std::filesystem::directory_entry& entry)
    {
        const auto file_status (std::filesystem::status(entry));
        return {entry.path(), file_status};
    }

    bool endsWith(const std::string& string, const std::string& ending)
    {
        if (ending.size() > string.size())
            return false;

        return std::equal(ending.rbegin(), ending.rend(), string.rbegin());
    }

    std::tuple<int, std::string> parsePath(const std::string &argv)
    {
        std::filesystem::path path(argv);
        if (!std::filesystem::exists(path))
        {
            std::cout << "Path " << path << " does not exist.\n";
            return {EXIT_FAILURE, {}};
        }

        // Maybe user chose a specific image, not a folder
        if (std::filesystem::is_regular_file(path))
            return {EXIT_SUCCESS, path.string()};
                                                            // TO DO : I KNOW THIS PART IS BAD! I have never worked with ::filesystem before,
        // So... it is a folder                                                            i will rewrite it when the prject works and is done
        // Creating a vector of everything in the given directory
        std::vector<std::tuple<std::filesystem::path, std::filesystem::file_status>> dir_items;
        std::transform(std::filesystem::directory_iterator(path), {}, std::back_inserter(dir_items), filepath::getFileInfo);

        std::set<std::string> allowed_ext = {".bmp", ".dds", ".jpg", ".png", ".tga", ".psd"};

        // Now getting images
        std::vector<std::string> dir_image_items;
        for (const auto &[local_path, status] : dir_items)
        {
            const std::string str_path = local_path.string();
            if (std::filesystem::is_regular_file(local_path) &&
                    std::any_of(allowed_ext.begin(), allowed_ext.end(), [&](const std::string& e) { return filepath::endsWith(str_path, e); }))
            {
                dir_image_items.emplace_back(str_path);
            }
        }

        if (dir_image_items.empty())
        {
            std::cout << "No images found at " << path << "\n--help for more information.\n";
            return {EXIT_FAILURE, {}};
        }

        std::cout << "Loading random image file from " << path << "\n";
        srand(static_cast<unsigned int>(time(nullptr)));
        return {EXIT_SUCCESS, dir_image_items[rand() & (dir_image_items.size() - 1)]};
    }

    std::vector<std::string> split(const std::string &s, char delim)
    {
        std::vector<std::string> result;
        std::stringstream ss (s);
        std::string item;

        while (getline(ss, item, delim))
            result.push_back(item);

        return result;
    }
}