#include "Arith_BlendMap.h"
#include "Arith_Utils.h"
#include "Arith_FrontStitch.h"

using std::max;
using std::min;

MapBlend::MapBlend(FileCache<FrameCache>* cache)
{
	_cache = cache;
}

MapBlend::~MapBlend()
{
}

void MapBlend::MapFrame(cv::Mat src, cv::Mat H_Geo, cv::Mat mapH, cv::Mat pan, cv::Mat pan_mask)
{
	// 与全景图的H相乘
	cv::Mat H = mapH * H_Geo;

	// 利用H投影当前帧到全景
	cv::Mat imagetmp(pan.size(), CV_8UC3, cv::Scalar(0, 0, 0));

	cv::warpPerspective(src, imagetmp, H, imagetmp.size(), cv::INTER_LINEAR, cv::BORDER_TRANSPARENT);

	cv::Mat mask = cv::Mat::ones(cv::Size(src.cols, src.rows), CV_8UC1);
	cv::Mat warped_mask;
	cv::warpPerspective(mask, warped_mask, H, imagetmp.size(), cv::INTER_LINEAR);
	imagetmp.copyTo(pan, warped_mask);

	// 保存遮罩
	warped_mask.copyTo(pan_mask, warped_mask);
}

void MapBlend::DirectMap(vector<KeyType> frameInd, cv::Mat mapH, cv::Mat pan, cv::Mat pan_mask)
{
	// 从文件缓存获取帧
	auto _t_frame_cache = std::make_shared<FrameCache>();
	for (size_t i = 0; i < frameInd.size(); i++)
	{
		KeyType key = frameInd[i];
		bool flag = _cache->get(key, _t_frame_cache);

		if (!flag)
		{
			continue;
		}

		// 读取当前H
		cv::Mat H1 = cv::Mat(3, 3, CV_64FC1, _t_frame_cache->H);

		// 与全景图的H相乘
		cv::Mat H = mapH * H1;

		// 利用H投影当前帧到全景
		cv::Mat imagetmp(pan.size(), CV_8UC3, cv::Scalar(0, 0, 0));

		// 获取图像数据
		cv::Mat src = getRGBAMatFromGDFrame(_t_frame_cache->_frame_info, _t_frame_cache->_data);

		cv::warpPerspective(src, imagetmp, H, imagetmp.size(), cv::INTER_LINEAR, cv::BORDER_TRANSPARENT);

		cv::Mat mask = cv::Mat::ones(cv::Size(src.cols - 200, src.rows - 200), CV_8UC1);
		cv::Mat warped_mask;
		cv::warpPerspective(mask, warped_mask, H, imagetmp.size(), cv::INTER_LINEAR);
		imagetmp.copyTo(pan, warped_mask);

		// 保存遮罩
		warped_mask.copyTo(pan_mask, warped_mask);

		//imshow("mask", pan_mask);
		//waitKey(1);

	}


}

void MapBlend::BlendMap(vector<KeyType> frameInd, cv::Mat mapH, cv::Mat pan, cv::Mat pan_mask)
{
}



FrontMapBlend::FrontMapBlend(FileCache<FrameCache>* cache)
{
	_cache = cache;
}

FrontMapBlend::~FrontMapBlend()
{
}

void FrontMapBlend::DirectMap(vector<KeyType> frameInd, FPanInfo _panPara, cv::Mat _panImage, cv::Mat pan_mask, cuda_Mem cuda_resor)
{
	_panImage.setTo(0);

	// 从文件缓存获取帧
	auto _t_frame_cache = std::make_shared<FrameCache>();
	for (size_t i = 0; i < frameInd.size(); i++)
	{
		KeyType key = frameInd[i];
		bool flag = _cache->get(key, _t_frame_cache);

		if (!flag)
		{
			continue;
		}

		// 读取当前H
		cv::Mat H = cv::Mat(3, 3, CV_64FC1, _t_frame_cache->H);

		auto info = _t_frame_cache->_para;

		float dep = info.nEvHeight;

		GD_VIDEO_FRAME_S img = _t_frame_cache->_frame_info;

		// 获取图像数据
		cv::Mat rgb = getRGBMatFromGDFrame(_t_frame_cache->_frame_info, _t_frame_cache->_data);


		//Pole CT_map = getPoleFromImgWithH(H, cv::Point2f(img.u32Width/2, img.u32Height/2), info.nEvHeight);

		// 计算帧的map四至，注意这里不是线性变化，不能完全保证四至约束下的原图能完全覆盖，即反采样后图像可能不完整
		Pole leftTop_map = getPoleFromImgWithH(H, cv::Point2f(0, 0), info.nEvHeight);
		Pole rightTop_map = getPoleFromImgWithH(H, cv::Point2f(img.u32Width, 0), info.nEvHeight);
		Pole rightBottom_map = getPoleFromImgWithH(H, cv::Point2f(img.u32Width, img.u32Height), info.nEvHeight);
		Pole leftBottom_map = getPoleFromImgWithH(H, cv::Point2f(0, img.u32Height), info.nEvHeight);

		//leftTop_map.beta = DEGLIM360(leftTop_map.beta);
		//rightTop_map.beta = DEGLIM360(rightTop_map.beta);
		//rightBottom_map.beta = DEGLIM360(rightBottom_map.beta);
		//leftBottom_map.beta = DEGLIM360(leftBottom_map.beta);

		// 转全景图的像方
		cv::Point2f p_leftTop_map = getFPanFromPole(leftTop_map, _panPara);
		cv::Point2f p_rightTop_map = getFPanFromPole(rightTop_map, _panPara);
		cv::Point2f p_rightBottom_map = getFPanFromPole(rightBottom_map, _panPara);
		cv::Point2f p_leftBottom_map = getFPanFromPole(leftBottom_map, _panPara);

		// 计算全景图上范围
		int right = max(max(max(p_leftTop_map.x, p_rightTop_map.x), p_rightBottom_map.x), p_leftBottom_map.x);
		int left = min(min(min(p_leftTop_map.x, p_rightTop_map.x), p_rightBottom_map.x), p_leftBottom_map.x);
		int top = min(min(min(p_leftTop_map.y, p_rightTop_map.y), p_rightBottom_map.y), p_leftBottom_map.y);
		int bottom = max(max(max(p_leftTop_map.y, p_rightTop_map.y), p_rightBottom_map.y), p_leftBottom_map.y);

		int xRange = right - left;
		int yRnage = bottom - top;

		//反映射到像素坐标
		MINMAXRECT32S RANGES = { 0 };
		RANGES.minY = std::max(0, top);
		RANGES.maxY = std::min(_panImage.rows - 1, bottom);

		RANGES.minX = std::max(0, left);
		RANGES.maxX = std::min(_panImage.cols - 1, right);

		cv::Rect2d roi(RANGES.minX, RANGES.minY, RANGES.maxX - RANGES.minX, RANGES.maxY - RANGES.minY);

		if (roi.width < 0)
		{
			int a = 0;
		}

		cv::Mat H_inv = H.inv();


#ifdef ENABLE_CUDA
		UpdatePan_CUDA(rgb, _panImage, roi, H_inv, _panPara, dep, cuda_resor);
#else
		UpdatePan_CPU(rgb, _panImage, roi, H_inv, _panPara, dep);
#endif


	}

}
