#pragma once

#include <fstream>

#include "nlohmann/json.hpp"

#include "DebugLog.h"

template <typename T>
class CJsonParser
{
public:
    bool Deserialize(const std::string& strFile, T& myOption)
    {
        try
        {
            // load json file
            std::ifstream infile(strFile);
            if (!infile.is_open())
            {
                return false;
            }

            nlohmann::json jf;

            // parse string into json
            infile >> jf;

            // deserialize json into object
            myOption = jf.template get<T>();

            infile.close();

            return true;
        }
        catch (nlohmann::json::exception& e)
        {
            std::string ss = e.what();
            DebugLog("nlohmann {} : {}", strFile, ss);
            return false;
        }
        catch (std::exception& e)
        {
            std::string ss = e.what();
            DebugLog("CJsonParser::Deserialize(const std::string& strFile, T& myOption) {} : {}", strFile, ss);
            return false;
        }
    }

    bool Serialize(const std::string& strFile, const T& myOption)
    {
        // convert object into json
        nlohmann::json jf(myOption);

        // persist to file
        std::ofstream outfile(strFile, std::ofstream::trunc);

        outfile << std::setw(4) << jf;

        outfile.close();

        return false;
    }

    bool Deserialize(const std::string& strFile, std::vector<T>& myOption)
    {
        try
        {
            // load json file
            std::ifstream infile(strFile);
            if (!infile.is_open())
            {
                return false;
            }

            nlohmann::json jf;

            // parse string into json
            infile >> jf;

            // deserialize json into object
            myOption = jf.template get<std::vector<T>>();

            infile.close();

            return true;
        }
        catch (nlohmann::json::exception& e)
        {
            std::string ss = e.what();
            DebugLog("nlohmann {} : {}", strFile, ss);
            return false;
        }
        catch (std::exception& e)
        {
            std::string ss = e.what();
            DebugLog("CJsonParser::Deserialize(const std::string& strFile, std::vector<T>& myOption) {} : {}", strFile, ss);
            return false;
        }
    }

    bool Serialize(const std::string& strFile, const std::vector<T>& myOption)
    {
        // convert object into json
        nlohmann::json jf(myOption);

        // persist to file
        std::ofstream outfile(strFile, std::ofstream::trunc);

        outfile << std::setw(4) << jf;

        outfile.close();

        return false;
    }
};