// PictureElement.cpp: implementation of the CReportElement class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
#include "ReportDict.h"
#include "PropertyDlg.h"
#include <math.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

CPictureElement::CPictureElement(CaplReportMgr* dict) : CReportElement(dict, E_PICTURE)
{
	CString sExePath;
	GetExePath(sExePath);
	m_mode = AfxGetApp()->GetProfileInt(_T("DefaultSettings"),_T("PictureDrawMode"),0);
	m_image = new CaplImage(sExePath+_T("empty.bmp"),APLIMAGE_FORMAT_BMP);
	m_fictive_image = new CaplImage(sExePath+_T("empty.bmp"),APLIMAGE_FORMAT_BMP);

	m_name = APL_T("Эскиз");
}

CPictureElement::~CPictureElement()
{
	if(m_image)
		delete m_image;
	if(m_fictive_image)
		delete m_fictive_image;
}

BOOL CPictureElement::Draw(CDC *pDC, double scale, int draw_mode, UINT flag)
{
	if(pDC==NULL) return FALSE;
	if(scale==0) return FALSE;
	CRect rect;
	GetRect(rect,scale,pDC->IsPrinting());
	CRect draw_rect = rect;
	if(m_image!=NULL)
	{
		if(!(m_mode&DM_FIT_TO_RECT))
		{
			int cx, cy, rcx, rcy;
			cx = m_image->GetWidth();
			cy = m_image->GetHeight();
			rcx = rect.Width();
			rcy = rect.Height();
			double p1 = double(cx)/double(cy);
			double p2 = double(rcx)/double(-rcy);
			if(p1!=p2)
			{
				CRect tmp;
				GetRect(tmp,scale,1);
				tmp.top = tmp.bottom - int(rcx/p1);
				if(tmp.Height()>rcy)
				{
					GetRect(tmp,scale,1);
					tmp.right = tmp.left - int(rcy*p1);
				}
				SetRect(tmp,scale);
				GetRect(rect,scale,pDC->IsPrinting());
			}
			draw_rect = rect;
		}
		else if((m_mode&DM_FIT_SCALE && m_mode&DM_FIT_TO_RECT))
		{
			int cx, cy, rcx, rcy;
			cx = m_image->GetWidth();
			cy = m_image->GetHeight();
			rcx = rect.Width();
			rcy = rect.Height();
			double p1 = double(cx)/double(cy);
			double p2 = double(rcx)/double(-rcy);
			if(p1!=p2)
			{
				int tmp_cy = int(rcx/p1);
				int tmp_cx = rcx;
				if(tmp_cy>-rcy)
				{
					tmp_cy = -rcy;
					tmp_cx = int(-rcy*p1);
				}
				draw_rect.left = rect.left + (rcx-tmp_cx)/2;
				draw_rect.right = draw_rect.left + tmp_cx;
				draw_rect.bottom = rect.bottom + (-rcy+tmp_cy)/2;
				draw_rect.top = draw_rect.bottom - tmp_cy;
			}
		}
	}
	draw_rect.NormalizeRect();
	int tmp = draw_rect.top;
	draw_rect.top = draw_rect.bottom;
	draw_rect.bottom = tmp;
	if(flag&DRAW_PICTURE)
	{
		if(m_image!=0)
		{
			m_image->Stretch(pDC->m_hDC, draw_rect);
		}
		else
		{
			m_fictive_image->Stretch(pDC->m_hDC, rect);
		}
	}
	else
	{
		m_fictive_image->Stretch(pDC->m_hDC, rect);
	}
	if(m_line_width>0)
	{
		CPen pen, *old;
		pen.CreatePen(PS_SOLID,m_line_width,OBJ_COLOR);
		old = pDC->SelectObject(&pen);
		DrawRect(pDC,rect);
		pDC->SelectObject(old);
		pen.DeleteObject();
	}
	if(flag&DRAW_SEL && !pDC->IsPrinting() && m_select)
		DrawSelPoints(pDC,scale);

	return TRUE;
}

void CPictureElement::Update(bool set)
{
	if(set)
	{
		if(m_inst==0)
			m_inst = m_ReportMgr->m_data->CreateInstance(m_ReportMgr->e_report_pic);
		m_ReportMgr->m_data->PutAttr(m_inst,m_ReportMgr->a_pic_mode,m_mode);
		CString tmp; tmp.GetEnvironmentVariable(_T("temp"));
		TCHAR* fbuf = new TCHAR[2048];
		GetTempFileName(tmp, _T("rep_pic_"), 0, fbuf);
		tmp=fbuf;
		delete []fbuf;
		if(m_image)
			m_image->Save(tmp,  APLIMAGE_FORMAT_BMP);
		else
			m_fictive_image->Save(tmp, APLIMAGE_FORMAT_BMP);
		m_ReportMgr->m_data->PutIntegratedBlob(m_inst,m_ReportMgr->a_pic_picture,tmp);
		try{DeleteFile(tmp);}
		catch (...) {TRACE(APL_T("Ошибка при удалении файла"));}
		m_ReportMgr->m_data->PutAttr(m_inst,m_ReportMgr->a_elem_text_val, (CaplInstance*)NULL);
		m_ReportMgr->m_data->PutAttr(m_inst,m_ReportMgr->a_elem_name,m_name);
		m_ReportMgr->PutPoint(m_inst,m_ReportMgr->a_elem_org_pt,m_org_pt);
		m_ReportMgr->PutPoint(m_inst,m_ReportMgr->a_elem_size,m_size);
		m_ReportMgr->m_data->PutAttr(m_inst,m_ReportMgr->a_elem_line_width,m_line_width);
		m_ReportMgr->m_data->PutAttr(m_inst,m_ReportMgr->a_elem_fixed,m_fixed);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_id, m_pictureId);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_textcolor, (int)m_color);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_backgroundcolor, (int)m_background_color);
	}
	else
	{
		if(m_inst==0) return;
		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_pic_mode,m_mode);
		CString tmp; tmp.GetEnvironmentVariable(_T("temp"));
		TCHAR* fbuf = new TCHAR[2048];
		GetTempFileName(tmp, _T("rep"), 0, fbuf);
		tmp=fbuf;
		delete []fbuf;
		if(m_image)
			DELETE_OBJECT(m_image);
		m_image = NULL;
		if(m_ReportMgr->m_data->GetIntegratedBlob(m_inst,m_ReportMgr->a_pic_picture,tmp))
			m_image = new CaplImage(tmp, APLIMAGE_FORMAT_BMP);
		try{DeleteFile(tmp);}
		catch (...) {TRACE(APL_T("Ошибка при удалении файла"));}
		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_elem_name,m_name);
		m_ReportMgr->GetPoint(m_inst,m_ReportMgr->a_elem_org_pt,m_org_pt);
		m_ReportMgr->GetPoint(m_inst,m_ReportMgr->a_elem_size,m_size);
		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_elem_line_width,m_line_width);
		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_elem_fixed,m_fixed);
		m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_id, m_pictureId);

		int tmp_color;
		m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_textcolor, tmp_color);
		m_color = (COLORREF)tmp_color;
		m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_backgroundcolor, tmp_color);
		m_background_color= (COLORREF)tmp_color;
	}
}

BOOL CPictureElement::LoadPicture(CString pathname)
{
	if(pathname.IsEmpty()) return FALSE;
	if(m_image!=0)
		DELETE_OBJECT(m_image);
	m_image = NULL;

	CString ext;
	int ind = pathname.ReverseFind(_T('.'));
	if(ind<0) return FALSE;
	ext = pathname.Right(pathname.GetLength()-ind-1);
	ext.MakeLower();
	int type = 0;
	if (ext == _T("bmp"))					type = APLIMAGE_FORMAT_BMP;
	else if (ext==_T("jpg")||ext==_T("jpeg"))	type = APLIMAGE_FORMAT_JPG;
	else if (ext == _T("gif"))				type = APLIMAGE_FORMAT_GIF;
	else if (ext == _T("png"))				type = APLIMAGE_FORMAT_PNG;
	else if (ext == _T("ico"))				type = APLIMAGE_FORMAT_ICO;
	else if (ext==_T("tiff")||ext==_T("tif"))	type = APLIMAGE_FORMAT_TIF;
	else return FALSE;
	m_image = new CaplImage(pathname,type);
	if(m_image==0) return FALSE;
	if (m_image->GetWidth() <= 0 || m_image->GetHeight() <= 0)
	{
		AfxMessageBox((LPCTSTR)CaplStringAdapter(m_image->GetLastError()));
		DELETE_OBJECT(m_image);
		m_image = NULL;
		return FALSE;
	}
	return TRUE;
}

int CPictureElement::GetMemSize()
{
	int size = CReportElement::GetMemSize();
	size+=sizeof(int)*2;
	CString tmp; tmp.GetEnvironmentVariable(_T("temp"));
	TCHAR* fbuf = new TCHAR[2048];
	GetTempFileName(tmp, _T("rep_pic_"), 0, fbuf);
	tmp=fbuf;
	delete []fbuf;
	if(m_image)
		m_image->Save(tmp, APLIMAGE_FORMAT_BMP);
	CFileStatus fs;
	CFile::GetStatus(tmp,fs);
	size += (int)fs.m_size;
	try{DeleteFile(tmp);}
	catch (...) {TRACE(APL_T("Ошибка при удалении файла"));}
	return size;
}

bool CPictureElement::LoadDataFromMem(BYTE *pByte, int &ind)
{
	CReportElement::LoadDataFromMem(pByte, ind);
	int* pInt = (int*)&pByte[ind];
	m_mode = *pInt;
	ind+=sizeof(int);
	
	pInt = (int*)&pByte[ind];
	int fsize = *pInt;
	ind+=sizeof(int);

	CString tmp; tmp.GetEnvironmentVariable(_T("temp"));
	TCHAR* fbuf = new TCHAR[2048];
	GetTempFileName(tmp, _T("rep_pic_"), 0, fbuf);
	tmp=fbuf;
	delete []fbuf;
	
	BYTE *arr = new BYTE[fsize];
	for(int i=0; i<fsize;i++)
	{
		arr[i] = pByte[ind];
		ind++;
	}
	CFile f;
	if(f.Open(tmp,CFile::modeCreate|CFile::modeWrite))
	{
		f.Write(arr,fsize);
		f.Close();
	}
	if(m_image)
		DELETE_OBJECT(m_image);
	m_image = new CaplImage(tmp, APLIMAGE_FORMAT_BMP);
	try{DeleteFile(tmp);}
	catch (...) {TRACE_TO_FILE(APL_T("Ошибка при удалении файла"));}
	delete []arr;
	return true;
}

void CPictureElement::CopyToMem(BYTE* pByte, int &ind)
{
	CReportElement::CopyToMem(pByte, ind);
	
	int* pInt = (int*)&pByte[ind];
	*pInt = m_mode;
	ind+=sizeof(int);


	CString tmp; tmp.GetEnvironmentVariable(_T("temp"));
	TCHAR* fbuf = new TCHAR[2048];
	GetTempFileName(tmp, _T("rep_pic_"), 0, fbuf);
	tmp=fbuf;
	delete []fbuf;
	if(m_image)
		m_image->Save(tmp, APLIMAGE_FORMAT_BMP);
	CFileStatus fs;
	CFile::GetStatus(tmp,fs);
	BYTE *arr = new BYTE[(unsigned int)fs.m_size];
	CFile f;
	
	pInt = (int*)&pByte[ind];
	*pInt = (int)fs.m_size;
	ind+=sizeof(int);

	if(f.Open(tmp,CFile::modeRead))
	{
		int size=(int)fs.m_size;
		int r = f.Read(arr,size);
		if(r!=fs.m_size)
			AfxMessageBox(APL_T("Ошибка чтения данных."));
		f.Close();
		try{DeleteFile(tmp);}
		catch (...) {TRACE_TO_FILE(APL_T("Ошибка при удалении файла"));}
		
	}

	for(int i=0; i<fs.m_size;i++)
	{
		pByte[ind]=arr[i];
		ind++;
	}

	delete []arr;
}

CReportElement* CPictureElement::CreateClon()
{
	CPictureElement* elem = new CPictureElement(m_ReportMgr);
	elem->m_org_pt = m_org_pt;
	elem->m_name = m_name;
	elem->m_size = m_size;
	elem->m_type = m_type;
	elem->m_fixed = m_fixed;
	elem->m_line_width = m_line_width;
	elem->m_mode = m_mode;
	elem->m_color = m_color;
	if(m_image)
	{
/*
		CString tmp = getenv(_T("tmp"));
		tmp+=_T("\\Temp_pic.tif");
		m_image->Save(tmp,APLIMAGE_FORMAT_TIF);
		elem->LoadPicture(tmp);
		try{DeleteFile(tmp);}
		catch (...) {TRACE_TO_FILE(APL_T("Ошибка при удалении файла"));}
*/

		if(elem->m_image)
			delete elem->m_image;
		elem->m_image = new CaplImage();
		elem->m_image->Copy(*m_image);
	}

	return elem;
}

void CPictureElement::Delete()
{
	if(m_inst)
		m_ReportMgr->m_data->DelIntegratedBlob(m_inst, m_ReportMgr->a_pic_picture);
	
	if(m_inst==0) return;
	
	CaplInstance* inst;
	//Удаление точек
	m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_org_pt, inst);
	if(inst)
		m_ReportMgr->m_data->DeleteInstance(inst);
	m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_size, inst);
	if(inst)
		m_ReportMgr->m_data->DeleteInstance(inst);
}

int CPictureElement::ShowContextMenu(CPoint pt, CWnd * wnd, int mode)
{
	if(wnd == NULL) return false;
	
	HINSTANCE hInst = AfxGetResourceHandle();
	AfxSetResourceHandle(dllInst);
	wnd->ClientToScreen(&pt);
	
	CMenu menu;
	CMenu *pPopup;
	menu.LoadMenu(IDR_CONTEXT_MENU);
	pPopup = menu.GetSubMenu(5);
	
	if(m_fixed && mode==0)
		pPopup->ModifyMenu(ID_FIXED,MF_BYCOMMAND|MF_STRING, ID_FIXED,APL_T("Раcфиксировать"));
	
	BOOL res = pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD,pt.x, pt.y, wnd);
	
	AfxSetResourceHandle(hInst);
	if(res == 0) return false;
	
	switch(res)
	{
	case ID_FIXED :
		if(m_fixed>0) m_fixed = 0;
		else m_fixed = 1;
		break;
	case ID_ALIGN :
		Align();
		break;
	default : 
		return ExecuteCmd(res);
	}
	return 0;
}
