#include <iostream>
#include <opencv2/core/core.hpp>
#include "../SummarizationFramework/Model/Tube.h"
#include "../SummarizationFramework/Model/TubeCollection.h"
#include "../SummarizationFramework/Model/NullVideoSequence.h"
#include "../SummarizationFramework/Model/VideoSequence.h"
#include "../SummarizationFramework/Optimization/ScenarioSolver/StaticScenarioSolver.h"
#include "../SummarizationFramework/Persistence/MatrixCsvDataSource.h"
#include "../SummarizationFramework/TubeFeatures/Features/ITubeFeature.h"
#include "../SummarizationFramework/TubeFeatures/Segmentation/CoverageDrivenLmFeatureSegmentator.h"
#include "../SummarizationFramework/TubeFeatures/Segmentation/FixedLengthIntervalLmFeatureSegmentator.h"
#include "../SummarizationFramework/Presentation/StaticRenderer.h"

using namespace std;
using namespace cv;
using namespace SummarizationFramework;
using namespace SummarizationFramework::Model;
using namespace SummarizationFramework::Optimization::ScenarioSolver;
using namespace SummarizationFramework::Persistence;
using namespace SummarizationFramework::Presentation;
using namespace SummarizationFramework::TubeFeatures::Features;
using namespace SummarizationFramework::TubeFeatures::Segmentation;

int main(int argc, char *argv[])
{
	if(argc == 7)
	{
		// command line arguments
		string featureFilename = argv[1];
		int featureRowIndex = atoi(argv[2]);
		int segmentLength = atoi(argv[3]);
		int segmentsCount = atoi(argv[4]);
		string inputVideoFilename = argv[5];
		string outputVideoFilename = argv[6];

		// load feature matrix
		MatrixCsvDataSource<double> featureDataSource(featureFilename);
		ITubeFeature::FeatureData featureData = *featureDataSource.Load();

		// select one row
		CV_Assert(featureRowIndex < featureData.rows);
		ITubeFeature::FeatureData featureRoi = featureData.row(featureRowIndex);

		// get a single tube for the whole video sequence
		VideoSequencePtr videoSequence = new VideoSequence(inputVideoFilename);
		TubePtr videoTube = new Tube(NULL, FrameSpan(1,videoSequence->GetLength()), inputVideoFilename);
		
		// segment tube
		//CoverageDrivenLmFeatureSegmentator segmentator(segmentLength);
		FixedLengthIntervalLmFeatureSegmentator segmentator(segmentLength);
		segmentator.SetMaxSegmentsCount(segmentsCount);
		segmentator.SetIntervalMerging(true, segmentLength/2 - 1);
		TubeCollectionPtr allTubes = segmentator.SegmentTubes(featureRoi, videoTube);

		// select some tubes
		//TubeCollectionPtr tubes = allTubes->Head(segmentsCount);
		TubeCollectionPtr tubes = allTubes;
		tubes->Sort(new TubeCollection::ByOriginalStartSortPredicate());

		// get scenario		
		StaticScenarioSolverPtr scenarioSolver = new StaticScenarioSolver(tubes);
		scenarioSolver->SetMaxTubeLength(segmentLength);
		scenarioSolver->Execute();	
		ScenarioPtr scenario = scenarioSolver->GetScenario();

		// get empty background video
		IVideoSourcePtr background = new NullVideoSequence(videoSequence);

		// render output video
		IRenderer::Params rendererParams;
		rendererParams.fps = 1;

		StaticRendererPtr renderer = new StaticRenderer(rendererParams);
		renderer->Render(scenario, background, outputVideoFilename);
	}
	else
	{
		std::cerr << "Bad command line arguments." << std::endl
				  << std::endl
		          << "Usage: EntropySumarizer.exe feature.csv feature_index segment_length max_segments_count in_video.avi out_video.avi" << std::endl
				  << std::endl
				  << "feature.csv.........Extracted features obtained from FeatureExtractor." << std::endl
				  << "feature_index.......Select one column of feature.csv to work with" << std::endl
				  << "segment_length......Length of video segments that the summarization consists of." << std::endl
				  << "max_segments_count..Maximum number of segments to use." << std::endl
				  << "in_video.avi........Input video filename." << std::endl
				  << "out_video.avi.......Output summarized video filename." << std::endl;

		return 1;
	}

	return 0;
}