///////////////////////////////////////////////////////////////////////
// RUNTIME CHECK for different system sizes
// main file to create the network
////////////////////////////////////////////////////////////////////////
// stl headers
#include <iostream>
#include <thread>
////////////////////////////////////////////////////////////////////////
// local headers
#include "header/network.hpp"
#include "header/ucomm.hpp"
#include "header/helper.hpp"
////////////////////////////////////////////////////////////////////////
const size_t runsN = 1;
const size_t dimension = 3;
const size_t nodes_total = 216;
//const bool crystallizability = true;
const double kappa = 0.1;
const double eta = 0.015;
const double defects = 0.0;
const bool save_positions = false;
const bool local_link_data = false;
const double cutoff = 7.0;
const bool hole = false;
const double hole_size = 7.0;
const bool rupture = true;
//const double rupture_energy = 0.8;
const double crystallinity_threshold = 1.0;
const bool filled = true;
//const double filler_content = 0.1;
const double filler_bonds = 10;
const bool energy_histogram = false;
const bool read_initial_network = false;
std::string initial_positions_file = "initialPositions.txt";
std::string initial_linkage_file = "initiallinkageSegments.txt";
std::string initial_filler_file = "initialFiller.txt";
const double max_stretch = 5.0;
const double stretch_increment = 0.01;
const size_t cycles = 1;
const bool stretching_only = false;

void simulate_network(const size_t _run_idx, const double _rupture_energy, const bool _crystallizability, const double _filler_content)
{
	/*fstream runtime;
	runtime.open("runtime.txt", ios::app);
	runtime << "# number of nodes				time" << endl;*/
	// iterate over number of nodes
	// for (size_t size = min_nodes_per_direc; size <= max_nodes_per_direc; size++) {
	// for (size_t size = 0; size <= nodes_vector.size(); size++) {
	// generate initial configuration
	// const size_t nodes_total = pow(size, dimension);
	// const size_t nodes_total = pow(nodes_vector[size], dimension);

	std::cout << "# Generating initial configuration in " << dimension << "D ..." << std::endl;
	tic();
	network elastomer(dimension);
	elastomer.set_approx_nodes(nodes_total);
	elastomer.set_kappa(kappa);						  // perturbation parameter for the lattice of nodes; homogenous lattice for kappa = 0.0
	elastomer.set_crystallization(_crystallizability); // set whether the links can crystallize or not
	elastomer.set_defects(defects);					  // fraction of non-crystallizable links
	elastomer.set_eta(eta);							  // set parameter for the strength of the enthalpic interaction od the crystals

	if (_run_idx == 0)
	{
		elastomer.set_data_saving(save_positions, local_link_data); // should save data for plotting of the network
	}
	else
	{
		elastomer.set_data_saving(false, false);
	}
	elastomer.set_cut_off(cutoff); // set cut-off radius for interaction of the links in units of r0 (characteristic distance for interaction)
	// elastomer.set_crack(false, 3.0);
	elastomer.set_crack_center(hole, hole_size);
	elastomer.set_rupture(rupture, _rupture_energy, crystallinity_threshold); // set whether the links are able to break and set the critical force on a link and the maximum crystallinity for rupture

	// elastomer.set_filler(filled, filler_content, filler_bonds); // set filler fraction and number of filler bonds
	size_t MC_attempts;
	if (dimension == 2)
	{
		MC_attempts = 0;
	}
	else
	{
		MC_attempts = 50;
	}
	elastomer.set_morphology_generator(filled, _filler_content, MC_attempts);

	elastomer.set_force_hist(energy_histogram, {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0});

	elastomer.save_Kuhn_segments(false); // set whether the number of Kuhn Segments in each link should be saved

	elastomer.initial_lattice(read_initial_network, initial_positions_file, initial_linkage_file, initial_filler_file); // set up the initial lattice of the nodes and decide whether they and the links should be read from a file
	// tac();
	////////////////////////////////////////////////////////////////////
	// run simulation
	// tic();
	elastomer.run_simulation(max_stretch, stretch_increment, _run_idx, cycles, stretching_only);
	tac();
	/*const double time = tac();
	runtime << nodes_total << "			" << time << endl;*/
	//}
	// runtime.close();
}

int main(const int argc, const char *argv[])
{
	userinput ui(argc,argv);
	const double rupture_energy{ui.parameter<double>("-gncrit","1.5")};
	const double filler_content{ui.parameter<double>("-phi","0.0")};
	const size_t cryst{ui.parameter<size_t>("-cryst","1")};
	const bool crystallizability = static_cast<bool>(cryst);

	std::vector<std::thread> threads(runsN);
	for (size_t run = 0; run < runsN; run++)
	{
		threads[run] = std::thread(simulate_network, run, rupture_energy, crystallizability, filler_content);
	}
	for (size_t run = 0; run < runsN; run++)
	{
		threads[run].join();
	}
	std::cout << "# All runs completed." << std::endl;
}