#include <iostream>
#include "bsoncxx/builder/stream/document.hpp"
#include "bsoncxx/json.hpp"

#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

#include "INIReader.h"

#include "core/Solver.h"
#include "mtl/Vec.h"
#include "core/SolverTypes.h"

#include "util/minisatsolver.h"
#include "util/conversions.h"
#include "util/ksatinstance.h"

#include <string>
#include <cmath>
#include <vector>

std::string getDbConfigFilePath();
std::string getDBUrl();
mongocxx::client connectToDatabase();

int main(int argc, char** argv)
{
	mongocxx::instance inst{};
    
	mongocxx::client conn = connectToDatabase();
    
	mongocxx::database db = conn["experiments"];

	mongocxx::collection instances = db["instances"];
	
	mongocxx::cursor cursor = instances.find({});

    
	for(auto doc : cursor)
	{
        satlab::MinisatSolver solver(satlab::types::convert<satlab::KSATinstance>(doc));
        
        bool modelFound = solver.solve();
        
        
        auto result = satlab::convert<bsoncxx::builder::stream::document>(
                        solver.getResult()
                      );
        
        result << "instance" << doc["_id"].get_oid();
        
        db["minisat_runs"].insert_one(result.view());
        
	}	
	
	return 0;
}

mongocxx::client connectToDatabase()
{
    mongocxx::options::ssl sslOptions;
    sslOptions.allow_invalid_certificates(true);
     
	mongocxx::options::client clientOptions{};
	clientOptions.ssl_opts(sslOptions);
    
	return mongocxx::client{mongocxx::uri{getDBUrl()}, clientOptions};
}


std::string getDBUrl()
{
	INIReader iniReader(getDbConfigFilePath());

	std::string connUrl("mongodb://");
	connUrl.append(iniReader.Get("CONNECTION", "user", "NA") + ":");
	connUrl.append(iniReader.Get("CONNECTION", "pw", "NA") + "@");
	connUrl.append(iniReader.Get("CONNECTION", "url", "NA") + ":");
	connUrl.append(iniReader.Get("CONNECTION", "port", "NA") + "/");
	connUrl.append(iniReader.Get("CONNECTION", "database", "NA"));
	connUrl.append("?ssl=true");

	return connUrl;
}

std::string getDbConfigFilePath()
{
	std::cout << "Database config file: ";

	std::string path;

	std::cin >> path;

	return path;
}
