#pragma once

#include <aplAggr.h>

#ifdef APL_REPORT_IMPL
#define CLASS_DECL_APL_REPORT  _declspec(dllexport)
#else
#define CLASS_DECL_APL_REPORT  _declspec(dllimport)
#ifdef _DEBUG
#ifdef UNICODE
#pragma comment (lib,"aplReport_ud.lib")
#else
#pragma comment (lib,"aplReportD.lib")
#endif
#else
#ifdef UNICODE
#pragma comment (lib,"aplReport_u.lib")
#else
#pragma comment (lib,"aplReport.lib")
#endif
#endif
#endif



class CaplReportFont;
class CaplReportLineStyle;
class CaplReportField;
class CaplReportPage;
class CaplReport;
class CaplReportDataRow;
class CaplReportImage;
class CaplReportTableColumn;
class CaplReportTable;

class CaplPdf;
class CaplPdfPage;

typedef CaplTAggr <CaplReportField*, CaplReportField*,  /*APLAGGR_UNIQUE|*/APLAGGR_LIST|APLAGGR_AUTOKILLREF> T_LIST_CaplReportField;
typedef CaplTAggr <CaplReportDataRow*, CaplReportDataRow*,  /*APLAGGR_UNIQUE|*/APLAGGR_LIST|APLAGGR_AUTOKILLREF> T_LIST_CaplReportDataRow;
typedef CaplTAggr <CaplReportTableColumn*, CaplReportTableColumn*,  /*APLAGGR_UNIQUE|*/APLAGGR_LIST|APLAGGR_AUTOKILLREF> T_LIST_CaplReportTableColumn;


//**************************************************************
class CaplReportFont
{
public:
	CaplReportFont(){m_size=0; m_bBold=false; m_bUnderline=false; m_bItalic=false;};
	CString m_id;     // Обозначение для ссылок
 	CString m_name;   // Шрифт
 	float m_size;    // Размер
	bool m_bBold;
	bool m_bUnderline;
	bool m_bItalic;
};
//**************************************************************
class CaplReportPen
{
public:
	CaplReportPen(){m_width=0; m_color=RGB(0,0,0);};
	CString m_id; // Обозначение для ссылок
	float m_width;
	COLORREF m_color;
};
//**************************************************************
class CLASS_DECL_APL_REPORT CaplReportField
{
public:
	CaplReportField();
	CaplReportField(LPCTSTR text, float cx, float cy, LPCTSTR pen_id, LPCTSTR font_id, TCHAR h_align, TCHAR v_align) ;
	CaplReportField(CaplReportField *src_field);
	CaplReportField(LPCTSTR text, CaplReportTableColumn *src_column, bool bCopyPen=false);
	~CaplReportField();

	float m_x, m_y, m_cx, m_cy, m_ident_x, m_ident_y;
	int m_angle;

	TCHAR m_v_allign;  // вертикальное выравнивание t - top,  m - middle (по умолчанию)  b - bottom
	TCHAR m_h_allign;  // горизонтальное выравнивание l - left (по умолчанию),  с - center  r - right

	CString m_field;  // название поля которое передается в иточнике данных
	CString m_text;   // текст, котороый отрисовывается

	CaplReportImage *m_image;
 
	int m_font_index;
	int m_pen_index;
	int m_top_pen_index;
	CString m_font_id; // При генерации должен быть переделан в m_font_index и очищен
	CString m_pen_id;  // При генерации должен быть переделан в m_pen_index и очищен
	CString m_top_pen_id;  // При генерации должен быть переделан в m_top_pen_index и очищен

	float m_top_line;

	void *m_inst;  // при отображении подписи сюда будет писаться approval
	CString m_data; // Данные сохранаяемые в отчете (в т.ч. ссылка на объект)

	CString *m_sCondition;	// Условие отрисовки (для того, чтобы можно было скрыть галочками в интерфейсе)
							// Функции отрисовки передается строка - условия. Поле отображается только если
							// m_sCondition есть в этой строке

protected:
	void Init(); // Чтобы первоначальное обновление было 1 раз
};

//**************************************************************
//**************************************************************
//**************************************************************
class CLASS_DECL_APL_REPORT CaplReportDataRow
{
public:
	CaplReportDataRow(){m_cy=0; m_bKeepWithNext=false; m_top_indent=0; m_bCopyToNextPage=false;};

	int m_cy;
	bool m_bKeepWithNext; //Не отрывать от следующего
	float m_top_indent;  // отсуп сверху перед строкой

	bool m_bCopyToNextPage; // Эта строка будет продублирована на след. страницах

	CString m_top_line_pen; // Перо для выделения верхней границы

	T_LIST_CaplReportField m_data_fields; // Поля  c данными и треб. разметкой
	T_LIST_CaplReportField m_report_fields;   // Полученные поля

};

class CLASS_DECL_APL_REPORT CaplReportSignType
{
public:
	CaplReportSignType(){m_inst=0;};
	CaplReportSignType(CaplReportSignType *src)	{m_id=src->m_id; m_role=src->m_role;   m_status=src->m_status;  m_name=src->m_name; m_inst=0;};


	CString m_id;
	CString m_role;
	CString m_status;
	CString m_name;

	//Используется только при отображении
	CString m_sPerson;
	CString m_sDate;

	void *m_inst; // Ссылка на отображаемый Instance (определяется при отображении)
};


//**************************************************************
class CLASS_DECL_APL_REPORT CaplReportPage
{
public:
	CaplReportPage(CaplReport *report){m_report=report; m_cx_mm=0; m_cy_mm=0; m_cx=0; m_cy=0; m_cur_angle=0; m_strech_k=0; m_table=0;} 
	CaplReportPage(CaplReportPage *src_page); // Делает копию, но не заносит ее в CaplReport::m_pages
	~CaplReportPage(){Clear();}

	void Clear();

	int m_num; // № страницы (c 0) Заполняется при открытии файла, используется при отображении текущего номера при листании
	float m_cx_mm, m_cy_mm;  // ширина и высота в мм
	CString m_name;
	T_LIST_CaplReportField m_fields;

	CaplReportTable *m_table;

	CString m_sLog; // Строка для записив лог

	// Готовит в памяти битовую матрицу шириной сх пикселей ; 
	// dc - совместимый с тем, в который будет отрисовываться
	// rotate - угол в градусах на который повернуть по час. срелке
	// при больших сх (зависит от pdf, примерно сх>4743) не рисует через BitBlt. 
	// (Из Pixmap рисует.) Возможно, это ограничение mfc или экрана. (4743 на 30 см - это 395 dpi)
	// start_strech_k - начальный коэфф уменьшения картинки (для упрощенной печати)
	// sCondition - условие отрисовки полей. Поле отрисовывается только, если его m_sCondition есть в sCondition
	bool Make2Cx(CDC *dc, int cx, int rotation=0, int start_strech_k=0, CString *sCondition=0); 
	void FreeBitmap();  // Удаляет bitmap из памяти 

	// Отрисовка
	//x0,y0 - угол изображения, x1, y1 - угол в окне
	// dc4draw - если не 0, то рисует не свое, а это. Используется для отрисовки результатов сравнения
	bool Draw(CDC *dc, int x0, int y0, int cx, int cy, int x1, int y1, CDC *dc4draw=0); 

	bool GetOriginalSizeIn_mm(float &cx, float &cy); // Возвращает размер страницы в мм
	bool GetCurImageSize(int &cx, int &cy); // Возвращает размер свформированного в память ихображения (сх - последний вызов Make2Cx)

	bool ConvertPointFromOrigUnit(float  x0, float y0, int &x1, int &y1); // преобразует коодинаты из 72dpi в пикселы
	bool ConvertPointToOrigUnit(int  x0, int y0, float &x1, float &y1);  // преобразует коодинаты из пикселов в 72dpi

	int GetStrechK(){return m_strech_k;};

	CBitmap *GetCurBitmap(){return &m_bitmap;} // Для служебных целей

protected:
	CaplReport *m_report;
	CDC m_comp_dc;
	CBitmap m_bitmap;
	int m_cx; // Размер подготовленной матрицы в пикселах (как думают снаружи. на самом деле ширина bmp m_cx/m_strech_k
	int m_cy; // Размер подготовленной матрицы в пикселах
	int m_cur_angle; // текущий угол поворота в градусах
	int m_strech_k; // Во сколько раз матрица в памяти меньше выводимой (если bitmap не влазит в память)

	void DrawConrent(CDC &dc,float k, CString *sCondition); // Рисует содержимое в специально подготовленный dc; k - коэф. пересчета мм в пиксели
	bool DrawImageInField(CaplReportField *field, CDC *dc, RECT &rect);
};
//**************************************************************
//**************************************************************
//**************************************************************
//**************************************************************

/* Принцип генерации отчета:
1. Читаем шаблон
2. Заполняем данные (при необходимости создаем копии последней страницы)
3. Удаялем лишние страницы (если, например,  в шаблоне 2 страницы, а понадобилась только одна)
4. Заполняем поля
5. Сохраняем
*/

class CLASS_DECL_APL_REPORT CaplReport
{

public:
	CaplReport();
	~CaplReport();

	void Clear();
	bool OpenFile(LPCTSTR report_file);// Открыть файл с диска
	bool OpenFileFromMemory(unsigned char *mem, ULONG memsize); // Открыть файл из памяти 
	
	// Генерация отчета
	// bCalcFieldHigh Если true, то высота ячеек будет определяться по содержимому (для ИИ)
	// bDublicateRows - если строка не влазит в поле - дублирвать строку
	bool GenerateReport(CaplStrStrMap *params_map,  T_LIST_CaplReportDataRow *rows, LPCTSTR report_file,
		bool bCalcFieldHigh=true,bool bDublicateRows=false);

	// Если bNotSaveEmptyField, то поля без текста с пустым pen не сохраняются
	// bCompress - Сжимать отчет в zip
	bool SaveReport(LPCTSTR report_file, bool bNotSaveEmptyField=true, bool bCompress=true);

	bool SaveToTiff(LPCTSTR fiff_file, int dpi=400, BOOL bColor = FALSE, DWORD CompressionMode=3);

	bool IsTemplate(){return m_bIsTemplate;};
	bool SetParams(CaplStrStrMap *params_map, bool bReplaceText); //Устанавливает параметры

	CaplReportImage *addImageFromFile(LPCTSTR file_name); //
	CaplReportImage *addImageFromMemory(LPCTSTR file_name, unsigned char *mem, long memsize);

	CaplReportField *FindFieldByName(LPCTSTR name); // Возвращает первое поле с указанным именем

	 CaplTAggr <CaplReportFont*, CaplReportFont*,  /*APLAGGR_UNIQUE|*/APLAGGR_LIST|APLAGGR_AUTOKILLREF> m_fonts;
	 CaplTAggr <CaplReportPen*, CaplReportPen*,  /*APLAGGR_UNIQUE|*/APLAGGR_LIST|APLAGGR_AUTOKILLREF> m_pens;
	 CaplTAggr <CaplReportPage*, CaplReportPage*,  /*APLAGGR_UNIQUE|*/APLAGGR_LIST|APLAGGR_AUTOKILLREF> m_pages;
	 CaplTAggr <CaplReportImage*, CaplReportImage*,  /*APLAGGR_UNIQUE|*/APLAGGR_LIST|APLAGGR_AUTOKILLREF> m_images;

	 CaplTAggr <CaplReportSignType*, CaplReportSignType*,  /*APLAGGR_UNIQUE|*/APLAGGR_LIST|APLAGGR_AUTOKILLREF> m_sign_types;

	 static bool RotateBitmap(CBitmap &bmp, int angle); // Поворачивает картинку

	 int static m_font_reduce_percent; // До скольки процентов можно уменьшать шрифт при отображении в ячейке

protected:
	bool m_bIsTemplate;
	bool OpenXML(LPCTSTR data_buf, UINT data_len, bool bFromFile); // Если bFromFile==true, то в data_buf имя файла, иначе в data_buf данные

	static bool DivideStringIntoParts(CDC *pDC, float cx, CString &text, CStringArray &sa );
};

//**************************************************************
//**************************************************************
//**************************************************************
//**************************************************************

class CLASS_DECL_APL_REPORT CaplReportImage
{
public:
	CaplReportImage(){m_blob=0; m_blob_size=0; m_pdf=0;};
	~CaplReportImage();

	CaplPdfPage *LoadImage(); // Зачитывает данные из m_blob
	void FreeImage();  // Выгружает m_pdf из памяти

	CString m_id;
	CString m_name;
	unsigned int m_blob_size;
	unsigned char *m_blob;
	CaplPdf *m_pdf;
};

//**************************************************************
//**************************************************************
//**************************************************************
//**************************************************************

class CLASS_DECL_APL_REPORT CaplReportTableColumn 
{
public:
	CaplReportTableColumn(CaplReportTable *table){m_cx=0; m_ident_x=0; m_ident_y=0; m_font_index=0; m_table=table; };
	CaplReportTableColumn(CaplReportTable *table, CaplReportTableColumn *src_column);
	
	CaplReportTable *m_table;

	CString m_id;
	float m_cx, m_ident_x, m_ident_y;

	TCHAR m_v_allign;  // вертикальное выравнивание t - top,  m - middle (по умолчанию)  b - bottom
	TCHAR m_h_allign;  // горизонтальное выравнивание l - left (по умолчанию),  с - center  r - right

	int m_font_index;
	CString m_font_id; // При генерации должен быть переделан в m_font_index и очищен
};

//**************************************************************
class CLASS_DECL_APL_REPORT CaplReportTable
{
public:
	CaplReportTable(){m_x=0; m_y=0; m_cx=0; m_cy=0; m_row_cy=0; m_pen_index=-1;};
	CaplReportTable(CaplReportTable *src_table);

	CString m_id;
	float m_x, m_y, m_cx, m_cy, m_row_cy;
	int m_pen_index;
	CString m_pen_id;

	T_LIST_CaplReportTableColumn m_columns;
};