
#include "Config.h"

#include <fstream>
#include <iostream>
#include <sstream>

#include "Config_read_write.h"

namespace p2c
{

Config* Config::instance_ = nullptr;

Config* Config::instance()
{
    static Guard g;
    if (instance_ == nullptr)
    {
        instance_ = new Config;
    }
    return instance_;
}

Config::Config()
{
    //fetch environment variables

    const char* exec_env = getenv("METASHAPE_EXEC");
    if (exec_env != NULL)
    {
        metashape_exec_ = exec_env;
    }

    texture_generation_script_ = "./TextureGeneration";
    partial_texture_generation_script_ = "./PartialTextureGeneration";
    texture_merge_script_ = "./TextureMergeHalfscan";
}


bool Config::parse_cmd_line(int argc, char **argv)
{
    std::string tmp;
    int i;

    for (i = 0; i < argc; ++i)
    {
        argv_.push_back(argv[i]);
    }

    for (size_t i = 1; i < argv_.size(); ++i)
    {
        tmp = argv_[i];

        if (tmp.find("--") == 0)
        {
            if (tmp.find("--config=") == 0)
            {
                read_config_file(tmp.substr(9), data_);
            }
        }
        else if (tmp[0] == '-' && argv_.size() > i+1)
        {
            if (tmp == "-c")
            {
                tmp = argv_[i+1];
                read_config_file(tmp, data_);
            }

            ++i;
        }
        else
        {
            input_filenames_.push_back(tmp);
        }
    }

    //print_config_data("Full configuration:");

    if (data_.empty())
    {
        std::cerr << "Config::parse_cmd_line: [ERROR] Configuration is empty. Cannot proceed." << std::endl;
        return false;
    }

    //set metashape script dir (it should be relative to the executable)
    metashape_script_dir_ = argv_[0];
#ifdef _WIN32
    metashape_script_dir_ = metashape_script_dir_.substr(0, metashape_script_dir_.find_last_of('\\')+1);
#else
    metashape_script_dir_ = metashape_script_dir_.substr(0, metashape_script_dir_.find_last_of('/')+1);
#endif
    metashape_script_dir_ += "scripts/metashape/";

    general_config_.init(argv_, data_["general"]);
    tmpl_config_.init(argv_, data_["template"]);
    body_config_.init(argv_, data_["body"]);
    front_body_config_.init(argv_, data_["frontbody"]);
    back_body_config_.init(argv_, data_["backbody"]);
    left_body_config_.init(argv_, data_["leftbody"]);
    right_body_config_.init(argv_, data_["rightbody"]);
    face_config_.init(argv_, data_["face"]);
    left_hand_config_.init(argv_, data_["lefthand"], true);
    right_hand_config_.init(argv_, data_["righthand"], false);
    head_config_.init(argv_, data_["head"]);
    hand_config_.init(argv_, data_["hand"]);
    point_set_config_.init(argv_, data_["pointset"]);

    print_config_data("\nConfig::parse_cmd_line: [WARNING] Unused configuration parameters:");

    return true;
}


void Config::print_config_data(const std::string& msg)
{
    bool something_to_print = false;
    for (auto d1: data_)
    {
        if (! d1.second.empty())
        {
            something_to_print = true;
            break;
        }
    }

    if (something_to_print)
    {
        std::cout << msg << std::endl;
        for (auto d1: data_)
        {
            if (! d1.second.empty())
            {
                std::cout << "[" << d1.first << "]" << std::endl;
                for (auto d2: d1.second)
                {
                    std::cout << d2.first << "=" << d2.second << "\n";
                }
                std::cout << std::endl;
            }
        }
    }

}

}
