
#include "graph_handler.hpp"
#include "../data_handler/data_handler.hpp"
#include "../data_handler/answer_handler.hpp"
#include "../mqo/interface.hpp"
#include "../result_handler/saver.hpp"
#include "process.hpp"

#include <bits/stdc++.h>
#include <fstream>
using namespace std;

int main(int argc, char** argv)
{

    // Parse arguments
    string datapath = argv[1];
    string querypath = argv[2];
    string answerpath = argv[3];
    string gpath = argv[4];
    string savepath = argv[5];
    string approximation_method = argv[6];
    int M = stoi(argv[7]);
    int ef = stoi(argv[8]);
    int B = stoi(argv[9]);
    int minbeamsize = stoi(argv[10]);
    int maxbeamsize = stoi(argv[11]);
    float increment_ratio = stof(argv[12]);
    bool use_l2 = (stoi(argv[13]) != 0);
    int n_core = stoi(argv[14]);

    // Read query
    int n_query, dim;
    float * query = get_data(querypath, n_query, dim);
    int n_data;
    float * data = get_data(datapath, n_data, dim);
    // Read answer
    vector<vector<int>> answers;
    get_answers(answerpath, answers);
    //cout<<"reading done : "<<n_query<<" "<<dim<<endl;

    // Read graph
    // need fix : one more argument please
    efanna2e::IndexNSG* nsg;
    if(use_l2) nsg= read_nsg_l2(datapath, gpath);
    else nsg = read_nsg_ip(datapath, gpath);

    // Run MQO
    auto start = timing::now();
    std::map<std::string, int> params = {{"M", M}, {"ef", ef}, {"B", B}, {"base_only", 0}};

    int beamsize = minbeamsize;
    int topk = 1;

    double speedupsum = 0;
    double timesum = 0;
    int n_rep = 3;

    for(int rep = 0 ; rep < n_rep; rep++) {
        cout<<"rep : "<<rep<<endl;
        pair<vector<vector<pair<int, int>>>, pair<double, double>> trajectory = mqo_with_info_parallel(approximation_method, n_query, dim, query, use_l2, params, n_core, false);
        double pptime = trajectory.second.first;
        std::pair<double, double> resNormal;
        resNormal = get_recall_parallel(nsg, query, answers, n_query, dim, topk, beamsize, n_core);

        std::pair<double, double> resOpt;
        resOpt = get_recall_optimized_parallel(nsg, query, answers, trajectory.first, n_query, dim, topk, beamsize, n_core);

        speedupsum += resNormal.second / (pptime+resOpt.second) ;
        timesum += (pptime+resOpt.second) ;
    }
    cout<< "#thread : " <<n_core<< endl;
    cout<<" total time : "<<timesum/n_rep<<endl;
    cout<<"speedup : "<< speedupsum / n_rep <<endl;


    delete [] query;
}