//#include "stdafx.h"
#include "ImageProc.h"
#include "helpfunc.h"
#include <fstream>
#include <bitset>
#include <algorithm>
#include <sstream>

ImageProc::ImageProc()
{
	_enable_cache = 1;
}

ImageProc::~ImageProc()
{
}

long ImageProc::Capture(const TString& file)
{
	TString fpath = file;
	if (fpath.find(_T('\\')) == -1)
		fpath = _curr_path + _T("\\") + fpath;

	return _src.write(fpath.c_str());
}

long ImageProc::CmpColor(long x, long y, const TString& scolor, double sim)
{
	std::vector<color_df_t> vcolor;
	str2colordfs(scolor, vcolor);
	return ImageBase::CmpColor(_src.at<color_t>(0, 0), vcolor, sim);
}

long ImageProc::FindColor(const TString& color, double sim, long dir, long& x, long& y)
{
	std::vector<color_df_t> colors;
	str2colordfs(color, colors);
	//setlog("%s cr size=%d",colors[0].color.tostr().data(), colors.size());
	//setlog("sim:,dir:%d", dir);
	return ImageBase::FindColor(colors, dir, x, y);
}

long ImageProc::FindColoEx(const TString& color, double sim, long dir, TString& retstr)
{
	std::vector<color_df_t> colors;
	str2colordfs(color, colors);
	return ImageBase::FindColorEx(colors, retstr);
}

long ImageProc::FindMultiColor(const TString& first_color, const TString& offset_color, double sim, long dir, long& x, long& y)
{
	std::vector<color_df_t> vfirst_color;
	str2colordfs(first_color, vfirst_color);
	std::vector<TString> vseconds;
	split(offset_color, vseconds, _T(","));
	std::vector<pt_cr_df_t> voffset_cr;
	pt_cr_df_t tp;
	for (auto& it : vseconds)
	{
		size_t id1, id2;
		id1 = it.find(_T('|'));
		id2 = (id1 == TString::npos ? TString::npos : it.find(L'|', id1));
		if (id2 != TString::npos)
		{
			sscanf(it.c_str(), _T("%d|%d"), &tp.x, &tp.y);
			if (id2 + 1 != it.length())
				str2colordfs(it.substr(id2 + 1), tp.crdfs);
			else
				break;
			voffset_cr.push_back(tp);
		}
	}
	return ImageBase::FindMultiColor(vfirst_color, voffset_cr, sim, dir, x, y);
}

long ImageProc::FindMultiColorEx(const TString& first_color, const TString& offset_color, double sim, long dir, TString& retstr)
{
	std::vector<color_df_t> vfirst_color;
	str2colordfs(first_color, vfirst_color);
	std::vector<TString> vseconds;
	split(offset_color, vseconds, _T(","));
	std::vector<pt_cr_df_t> voffset_cr;
	pt_cr_df_t tp;
	for (auto& it : vseconds)
	{
		size_t id1, id2;
		id1 = it.find(_T('|'));
		id2 = (id1 == TString::npos ? TString::npos : it.find(_T('|'), id1));
		if (id2 != TString::npos)
		{
			_stscanf(it.c_str(), _T("%d|%d"), &tp.x, &tp.y);
			if (id2 + 1 != it.length())
				str2colordfs(it.substr(id2 + 1), tp.crdfs);
			else
				break;
			voffset_cr.push_back(tp);
		}
	}
	return ImageBase::FindMultiColorEx(vfirst_color, voffset_cr, sim, dir, retstr);
}
//图形定位
long ImageProc::FindPic(const TString& files, const TString& delta_colors, double sim, long dir, long& x, long& y)
{
	vector<Image*> vpic;
	//vector<color_t> vcolor;
	color_t dfcolor;
	vector<TString> vpic_name;
	files2mats(files, vpic, vpic_name);
	dfcolor.str2color(delta_colors);
	//str2colors(delta_colors, vcolor);
	sim = 0.5 + sim / 2;
	//long ret = ImageBase::FindPic(vpic, dfcolor, sim, x, y);
	long ret = ImageBase::FindPicTh(vpic, dfcolor, sim, x, y);
	//清理缓存
	if (!_enable_cache)
		_pic_cache.clear();
	return ret;
}
//
long ImageProc::FindPicEx(const TString& files, const TString& delta_colors, double sim, long dir, TString& retstr, bool returnID)
{
	vector<Image*> vpic;
	vpoint_desc_t vpd;
	//vector<color_t> vcolor;
	color_t dfcolor;
	vector<TString> vpic_name;
	files2mats(files, vpic, vpic_name);
	dfcolor.str2color(delta_colors);
	sim = 0.5 + sim / 2;
	long ret = ImageBase::FindPicExTh(vpic, dfcolor, sim, vpd);
#ifdef UNICODE
	std::wstringstream ss(std::wstringstream::in | std::wstringstream::out);
#else
	std::stringstream ss(std::stringstream::in | std::stringstream::out);
#endif
	if (returnID)
	{
		for (auto& it : vpd)
		{
			ss << it.id << _T(",") << it.pos << _T("|");
		}
	}
	else
	{
		for (auto& it : vpd)
		{
			ss << vpic_name[it.id] << _T(",") << it.pos << _T("|");
		}
	}
	//清理缓存
	if (!_enable_cache)
		_pic_cache.clear();
	retstr = ss.str();
	if (vpd.size())
		retstr.pop_back();
	return ret;
}

long ImageProc::FindColorBlock(const TString& color, double sim, long count, long height, long width, long& x, long& y)
{
	vector<color_df_t> colors;
	if (str2colordfs(color, colors) == 0)
	{
		bgr2binary(colors);
	}
	else
	{
		bgr2binarybk(colors);
	}
	return ImageBase::FindColorBlock(sim, count, height, width, x, y);
}

long ImageProc::FindColorBlockEx(const TString& color, double sim, long count, long height, long width, TString& retstr)
{
	vector<color_df_t> colors;
	if (str2colordfs(color, colors) == 0)
	{
		bgr2binary(colors);
	}
	else
	{
		bgr2binarybk(colors);
	}
	return ImageBase::FindColorBlockEx(sim, count, height, width, retstr);
}

TString ImageProc::GetColor(long x, long y)
{
	color_t cr;
	if (ImageBase::GetPixel(x, y, cr))
	{
		return cr.tostr();
	}
	else
	{
		return _T("");
	}
}

int ImageProc::str2colordfs(const TString& color_str, std::vector<color_df_t>& colors)
{
	std::vector<TString> vstr, vstr2;
	color_df_t cr;
	colors.clear();
	int ret = 0;
	if (color_str.empty())
	{ //default
		return 1;
	}
	if (color_str[0] == _T('@'))
	{ //bk color info
		ret = 1;
	}
	split(ret ? color_str.substr(1) : color_str, vstr, _T("|"));
	for (auto& it : vstr)
	{
		split(it, vstr2, _T("-"));
		cr.color.str2color(vstr2[0]);
		cr.df.str2color(vstr2.size() == 2 ? vstr2[1] : _T("000000"));
		colors.push_back(cr);
	}
	return ret;
}

void ImageProc::str2colors(const TString& color, std::vector<color_t>& vcolor)
{
	std::vector<TString> vstr, vstr2;
	color_t cr;
	vcolor.clear();
	split(color, vstr, _T("|"));
	for (auto& it : vstr)
	{
		cr.str2color(it);
		vcolor.push_back(cr);
	}
}

long ImageProc::LoadPic(const TString& files)
{
	//std::vector<TString>vstr, vstr2;
	std::vector<TString> vstr;
	int loaded = 0;
	split(files, vstr, _T("|"));
	TString tp;
	for (auto& it : vstr)
	{
		//路径转化
		if (!Path2GlobalPath(it, _curr_path, tp))
			continue;
		//先在缓存中查找
		if (!_pic_cache.count(tp))
		{
			_pic_cache[tp].read(tp.data());
		}
		//已存在于缓存中的文件也算加载成功
		loaded++;
	}
	return loaded;
}

long ImageProc::FreePic(const TString& files)
{
	std::vector<TString> vstr;
	int loaded = 0;
	split(files, vstr, _T("|"));
	TString tp;
	for (auto& it : vstr)
	{
		//看当前目录
		auto cache_it = _pic_cache.find(it);
		//没查到再看一下资源目录
		if (cache_it == _pic_cache.end())
		{
			cache_it = _pic_cache.find(_curr_path + _T("\\") + it);
		}
		//查到了就释放
		if (cache_it != _pic_cache.end())
		{
			cache_it->second.release();
			_pic_cache.erase(cache_it);
			loaded++;
		}
	}
	return loaded;
}

long ImageProc::LoadMemPic(const TString& file_name, void* data, long size)
{
	try
	{
		if (!_pic_cache.count(file_name))
		{
			_pic_cache[file_name].read(data, size);
		}
	}
	catch (...)
	{
		return 0;
	}
	return 1;
}

void ImageProc::files2mats(const TString& files, std::vector<Image*>& vpic, std::vector<TString>& vstr)
{
	//std::vector<TString>vstr, vstr2;
	Image* pm;
	vpic.clear();
	split(files, vstr, _T("|"));
	TString tp;
	for (auto& it : vstr)
	{
		//先在缓存中查找是否已加载，包括从内存中加载的文件
		if (_pic_cache.count(it))
		{
			pm = &_pic_cache[it];
		}
		else
		{
			//路径转化
			if (!Path2GlobalPath(it, _curr_path, tp))
				continue;
			//再检测一次，包括绝对路径的文件
			if (_pic_cache.count(tp))
			{
				pm = &_pic_cache[tp];
			}
			else
			{
				_pic_cache[tp].read(tp.data());
				pm = &_pic_cache[tp];
			}
		}
		vpic.push_back(pm);
	}
}

long ImageProc::FindLine(const TString& color, double sim, TString& retStr)
{
	retStr.clear();
	vector<color_df_t> colors;
	if (str2colordfs(color, colors) == 0)
	{
		bgr2binary(colors);
	}
	else
	{
		bgr2binarybk(colors);
	}
	if (sim < 0. || sim > 1.)
		sim = 1.;

	_src.write(_T("_src.bmp"));
	_gray.write(_T("gray.bmp"));
	_binary.write(_T("_binary.bmp"));
	return ImageBase::FindLine(sim, retStr);
}
