/* This is a first attempt in implementation of plugins to Trisurf-ng. */

/*

Options for tape:

extra_plugin_path = "..." (OPTIONAL)

vesicle bipyramid {
	nshell=23	
}

vesicle vtufile {
	filename="filename"
}

vesicle vtudatabase {
	run_id=123
	timestep=999
}

vesicle properties {
	xk0=20
	dmax=1.7
	dmin_interspecies=1.2
	stepsize=0.15
}

space properties {
	nxmax=60
	nymax=60
	nzmax=60
}

loop control {
	inner=1000
	outer=1000
}

plugin pressure {
	pressure=10
}

plugin constant_volume {
	precision=1e14
}

plugin constant_area {

}

plugin confinement_plate {
	distance=5
	force=10
	coordinate=2 // 0=x,1=y,2=z
}

plugin spherical_harmonics {
	lmax=21
	filename="abc.csv"
}

plugin spontaneous_curvature {
	c0=2
	N=100
	w=10
	force=3
}

plugin filament {
	monomers=100
	xi=10
}

plugin polymer {
	polymers = 100
	monomers = 10
	elastic_coefficient=100
	is_internal = true
}

plugin nucleus {
	R_nucleus=10
	R_nucleusX=0
	R_nucleusY=0
	R_nucleusZ=0
}

*/
#include "plugins.h"
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include "general.h"

ts_plugin *init_plugin(ts_char *filename){
	ts_plugin *plugin = (ts_plugin *)calloc(1, sizeof(ts_plugin));
	plugin->filename=(ts_char *)calloc(strlen(filename),sizeof(ts_char));
	strcpy(plugin->filename,filename);
	plugin->libhandle = dlopen(plugin->filename, RTLD_NOW);
	if(!plugin->libhandle){
		ts_fprintf(stderr,"Error loading plugin: %s\n", filename);
		fatal("Exiting",235);
	}
	ts_plugin_details* (*get_plugin_details)(void) = dlsym(plugin->libhandle, "init");
	plugin->details = get_plugin_details();
	plugin->function = (ts_plugin_function *)calloc(1,sizeof(ts_plugin_function));
	
	plugin->function->cleanup = dlsym(plugin->libhandle, "cleanup");
	plugin->function->at_start = dlsym(plugin->libhandle, "at_start");
	plugin->function->after_vesicle_init = dlsym(plugin->libhandle, "after_vesicle_init");
	plugin->function->vm_hard_constraint = dlsym(plugin->libhandle, "vm_hard_constraint");
	plugin->function->vm_energy_before = dlsym(plugin->libhandle, "vm_energy_before");
	plugin->function->vm_energy_after = dlsym(plugin->libhandle, "vm_energy_after");
	plugin->function->vm_new_state_rejected = dlsym(plugin->libhandle, "vm_new_state_rejected");
	plugin->function->vm_new_state_accepted = dlsym(plugin->libhandle, "vm_new_state_accepted");

	return plugin;
}


ts_plugin_list *init_plugin_list(ts_char **plugin_filenames, ts_uint number_of_plugins){
	ts_plugin_list *plist=(ts_plugin_list *)calloc(1, sizeof(ts_plugin_list));
	plist->plugin=(ts_plugin **)calloc(number_of_plugins, sizeof(ts_plugin *));
	for(int i=0;i<number_of_plugins;i++){
		plist->plugin[i]=init_plugin(plugin_filenames[i]);
	}
	return plist;
}	

void free_plugin(ts_plugin *plugin){
	plugin->function->cleanup();
	free(plugin->function);
	free(plugin->details);
	free(plugin->filename);
	dlclose(plugin->libhandle);
	free(plugin);
}

void free_plugin_list(ts_plugin_list *plist){
	for(int i=0;i<plist->n;i++){
		free_plugin(plist->plugin[i]);
	}
	free(plist);
}