#include "neural_net.h"
#include "neuron.h"

#include <ctype.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

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


	cout << "Usage for " << argv[0] << ": <epochs> <topology> <inputfile> [-i]" << endl;

	stringstream ss;

	//number of epochs training should take
	int epochs = 20;

	if(argc >= 2){
		ss << argv[1];
		ss >> epochs;
	}


	NetTopology topology;
	topology.push_back(3);
	topology.push_back(2);
	topology.push_back(1);

	if(argc >= 3){
		topology.clear();
		int neuron_number = 0;
		istringstream iss(argv[2]);
		for(string tmp;getline(iss, tmp, ',');){
			ss.clear();
			ss << tmp;
			ss >> neuron_number;
			topology.push_back(neuron_number);
		}
	}
	NeuralNet nn(topology);

	vector<vector<double> > inputs;
	vector<double> current_input;

	inputs.push_back(current_input);
	inputs.back().push_back(3.0);
	inputs.back().push_back(6.0);
	inputs.back().push_back(2.0);

	vector<vector<double> > expected_outputs;
	vector<double> current_output;
	expected_outputs.push_back(current_output);
	expected_outputs.back().push_back(0.3124);

	if(argc >= 4){
		bool first = true;
		double neuron_value = 0.0f;
		inputs.clear();
		expected_outputs.clear();
		ifstream ifs(argv[3], ifstream::in);
		for(string line;getline(ifs, line);){
			istringstream iss(line);
			current_input.clear();
			current_output.clear();
			first = true;
			for(string tmp;getline(iss, tmp, ',');){
				ss.clear();
				ss << tmp;
				ss >> neuron_value;
				if(first){
					current_output.push_back(neuron_value);
					first = false;
				}else{
					current_input.push_back(neuron_value);
				}
			}
			//expected_outputs.push_back(current_output);
			//inputs.push_back(current_input);
			nn.add_training_set_entry(current_input, current_output[0]);
		}
	}



	cout << "outputs: ";
	for(auto tmp : expected_outputs){
		for(auto t: tmp){
			cout << t << ",";
		}
		cout << endl;
	}

	cout << "inputs: ";
	for(auto tmp : inputs){
		for(auto t: tmp){
			cout << t << ",";
		}
		cout << endl;
	}

	/*for(int i=0;i<epochs;i++){
		int k=0;
		for(auto tmp : inputs){
			nn.feed_forward(tmp);
			nn.get_results(outputs);
			nn.back_propagation(expected_outputs[k]);
			cout << "NN\tepoch: " << i << "\tinputs: ";
			for(auto d : tmp){
				cout << d << ",";
			}
			for(auto d : outputs){
				cout << "\tout:" << d;
			}
			for(auto d : expected_outputs[k]){
				cout << "\texpected:" << d;
			}
			cout <<"\terror:" << nn.get_error() << endl;
			k++;
		}
	}*/

	if(argc >= 5){
		ss.clear();
		ss << argv[4];
		ss >> Neuron::eta;
	}

	if(argc >= 6){
		ss.clear();
		ss << argv[5];
		ss >> Neuron::alpha;
	}

	nn.train_network(epochs);

	vector<double> outputs;

	if(argc >= 7){
		bool first = true;
		double neuron_value = 0.0;
		for (string line; getline(cin, line);) {
			istringstream iss(line);
			current_input.clear();
			current_output.clear();
			first = true;
			for(string tmp;getline(iss, tmp, ',');){
				ss.clear();
				ss << tmp;
				ss >> neuron_value;
				if(first){
					current_output.push_back(neuron_value);
					first = false;
				}else{
					current_input.push_back(neuron_value);
				}
			}
			nn.feed_forward(current_input);
			nn.get_results(outputs);
			nn.back_propagation(current_output);
			cout << "NN\tepoch: " << "after training" << "\tinputs: ";
			for(auto d : current_input){
				cout << d << ",";
			}
			for(auto d : outputs){
				cout << "\tout:" << d;
			}
			for(auto d : current_output){
				cout << "\texpected:" << d;
			}
			cout <<"\terror:" << nn.get_error() << endl;
		}
	}

	return 0;

}
