//
// Created by caleb on 3/26/18.
//

#include <iostream>
#include <vector>
#include <cmath>
#include <TSystem.h>

#include "filval.hpp"
#include "root_filval.hpp"

#include "analysis/TrackingNtupleObjs.hpp"

#include <memory>
#include <iostream>
#include <string>
#include <cstdio>


template<typename ... Args>
string fmt( const std::string& format, Args ... args ) {
    using namespace std;
    size_t size = snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0'
    unique_ptr<char[]> buf( new char[ size ] );
    snprintf( buf.get(), size, format.c_str(), args ... );
    return string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
}


SimTrackCollection sim_tracks;
SimVertexCollection sim_vertices;

void register_objects(TrackingDataSet& tds){
    sim_tracks.init(tds);
    sim_vertices.init(tds);
}

void run(bool silent) {
    using namespace std;
    using namespace fv;
    using namespace fv_root;
    auto file_list = the_config->get_source_files();
    string output_filename = the_config->get_output_filename();
    TrackingDataSet tds(output_filename, file_list, "trackingNtuple/tree");
    register_objects(tds);


    while (tds.next(!silent)) {


        auto print_vtx_pos = [](int vtx_idx) {
            const SimVertex vtx = sim_vertices[vtx_idx];
            cout << fmt("(%.3f, %.3f, %.3f)", vtx.x(), vtx.y(), vtx.z());
        };

//        cout << tds.get_current_event();
        for (const SimTrack sim_track : sim_tracks) {
            if (sim_track.decayVtxIdx().size() <= 1) continue;
            cout << fmt("  %d: %d \n", sim_track.pdgId(), sim_track.parentVtxIdx());
            for (const auto vtx_idx : sim_track.decayVtxIdx()) {
                cout << "    " << vtx_idx ;
                print_vtx_pos(vtx_idx);
                cout << ": ";
                for (const auto simtrk_idx : sim_vertices[vtx_idx].sourceSimIdx())
                    cout << sim_tracks[simtrk_idx].pdgId() << " ";
                cout << " -> " << vtx_idx << ": ";
                for (const auto simtrk_idx : sim_vertices[vtx_idx].daughterSimIdx())
                    cout << sim_tracks[simtrk_idx].pdgId() << " ";
                cout << endl;
            }
        }
    }

    tds.save_all();
}

int main(int argc, char * argv[]){
    using namespace fv_util;
    ArgParser args(argc, argv);
    bool silent = args.cmd_option_exists("-s");
    if(args.cmd_option_exists("-c")) {
        init_config(args.get_cmd_option("-c"));
        args.update_config();
        init_log(LogPriority::kLogInfo);
//        gSystem->Load("libfilval.so");
        run(silent);
    } else {
        cout << "Usage: ./" << argv[0] << " (-s) -c config_file.yaml" << endl;
    }
    return 0;
}

