#include <ctime>
#include <memory>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include "common/parser/depgraph.h"
#include "graphparsing_1ec_n5_run.h"
#include "graphparsing_1ec_n5_depparser.h"

namespace graphparsing_1ec_n5 {
	Run::Run() = default;

	Run::~Run() = default;

	void Run::train(const std::string & sInputFile, const std::string & sFeatureInput, const std::string & sFeatureOutput) const {
		int nRound = 0;
		int inRound = 0;
		int twodirRound = 0;
		int oneringRound = 0;
		int tailRound = 0;
		DependencyGraph ref_sent;
		int onecutRound = 0;
		int twocutRound = 0;
		int threecutRound = 0;
		int overthreecutRound = 0;
		int sumedge = 0;
		int sumedge2 = 0;

		std::vector<DependencyGraph> treevector;
		std::vector<int> ran;
		std::cout << "Graphcjj1_oneendpoint Training iteration is started..." << std::endl;

		std::unique_ptr<DepParser> parser(new DepParser(sFeatureInput, sFeatureOutput, ParserState::TRAIN));
		std::ifstream input(sInputFile);
		int idx = 0;
		treevector.clear();
		ran.clear();
		if (input)
		{
			while (input >> ref_sent)
			{
				inRound++;
				//if (ref_sent.IsProjective() || ref_sent.OneEdgeCut_Plannar(1) || ref_sent.TwoEdgeCut_Plannar(1) || ref_sent.ThreeEdgeCut_Plannar(1))
				{
					treevector.push_back(ref_sent); 
					ran.push_back(idx++);
				}
				
			}
		}
		srand(time(0));
		random_shuffle(ran.begin(), ran.end());

		if (idx) {
			while (idx) {
				idx--;
				++nRound;
				//if (treevector[ran[idx]].IsOneEndPoint())
				parser->train(treevector[ran[idx]], nRound);
			}
			parser->outans();
			parser->finishtraining();
		}
		input.close();
		std::cout << inRound << std::endl;
		std::cout << "Total edge" << ' ' << sumedge << std::endl;
		std::cout << "Project% " << nRound << " / " << inRound << ' ' << 1.0 * nRound / inRound << std::endl;
		//std::cout << "Edge% " <<sumedge2<<' '<<sumedge<<' '<< 1.0*sumedge2 / sumedge << std::endl;
		//system("pause");
		std::cout << "Done." << std::endl;
	}

	void Run::parse(const std::string & sInputFile, const std::string & sOutputFile, const std::string & sFeatureFile) const {

		DependencyGraph graph,retv;

		std::cout << "Parsing started" << std::endl;

		std::unique_ptr<DepParser> parser(new DepParser(sFeatureFile, sFeatureFile, ParserState::PARSE));
		std::ifstream input(sInputFile);
		std::ofstream output(sOutputFile);
		int round = 0;
		time_t b = clock();
		if (input) {
			while (input >> graph) {
				if (graph.getSentence().size() < MAX_SENTENCE_SIZE) {
					parser->parse(graph, &retv);
					output << retv;
					retv.clear();
					if (++round % 100 == 0) std::cout << round << std::endl;
				}
			}
		}
		std::cout << round <<" have done"<< std::endl;
		std::cout << "time " << 0.001* (clock() - b) / round << std::endl;
		input.close();
		output.close();
	}

	void Run::goldtest(const std::string & sInputFile, const std::string & sFeatureInput) const {
		int nRound = 0;
		int inRound = 0;
		DependencyGraph ref_sent;

		std::cout << "GoldTest iteration is started..." << std::endl;
		auto time_begin = time(NULL);

		std::unique_ptr<DepParser> parser(new DepParser(sFeatureInput, "", ParserState::GOLDTEST));
		std::ifstream input(sInputFile);
		if (input) {
			while (input >> ref_sent) {
				
				++nRound;
				parser->train(ref_sent, nRound);
			
			}
			parser->outans();
		}
		input.close();

		std::cout << "total " << nRound << " round" << std::endl;
		//std::cout << "Project% " << nRound << " / " << inRound << ' ' << 1.0 * nRound / inRound << std::endl;

		auto time_end = time(NULL);

		std::cout << "Done." << std::endl;

		std::cout << "Training has finished successfully. Total time taken is: " << difftime(time_end, time_begin) << "s" << std::endl;
	}
}
