#if !defined(AFX_FINDQUERYDLGEX_H__572F8F65_AE26_4B51_8BDE_74505F8B1EA0__INCLUDED_)
#define AFX_FINDQUERYDLGEX_H__572F8F65_AE26_4B51_8BDE_74505F8B1EA0__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// FindQueryDlgEx.h : header file
//
#include "resource.h"
#include <aplStepQL.h>
#include <apl_gui.h>
#include "apl_api.h"
#include "ResizableDialog.h"
#include "aplStepManager.h"
#include "afxwin.h"

// включаем перечисления столбцов и заголовки буферов
#include "FindQueryDlg.h"

#define TAB_ADJ_TYPE_APPROVAL 0
#define TAB_ADJ_TYPE_CHARACTER 1
#define TAB_ADJ_TYPE_DOCUMENTS 2
#define TAB_ADJ_TYPE_RESOURCES 3
#define TAB_ADJ_TYPE_BLOBS 4
#define TAB_ADJ_TYPE_CLASSIF 5



#define InserString2Control(control,value) 	pos_added=control.AddString(CaplQLQuery::LogOp2String(value));control.SetItemData(pos_added,value);

#define InsertTabAjust(indx,param) {TabCtrlItem.pszText = (LPTSTR)TAB_ADJ_NAME_##param;TabCtrlItem.lParam = TAB_ADJ_TYPE_##param; is_##param=m_TabAdjust.InsertItem(indx,&TabCtrlItem);}

enum TypeSelectCombo
{
	TSC_NonEdit = 0,
	TSC_SelectTypeAttr = 1,
	TSC_SelectLogOp = 2,
	TSC_SelectValue = 3
};

enum TypeSelectInstance
{
	TSI_AllTypes = 0,
	TSI_ClassifierItem = 1,
	TSI_ClassifierLevel = 2,
	TSI_Persorg = 3,
	TSI_Org = 4,
	TSI_Pdf = 5,
	TSI_Item = 6,
	TSI_System = 7
};

// описывает элемент пути в цепочке атрибутов. Если путь заканчивается на этом атрибуте - to_entity ==0
struct CFindAttrPath
{
	CFindAttrPath(CString _attr = _T(""),CString _to_entity = _T(""))
	{
		attr = _attr; to_entity = _to_entity; next_step = 0;
		if(attr[0] != _T('.')) attr.Insert(0, _T('.'));
	}
	~CFindAttrPath(){if(next_step!=0)delete next_step;}
	CString attr;
	CString to_entity;
	CFindAttrPath* next_step;
};

class CNonSortedStrStrArray
{
public:
	class CaplStrStrMapItem
	{
	public:
		CaplStrStrMapItem() {}
		CaplStrStrMapItem(const TCHAR *str_init, const TCHAR *val_init) {str=str_init; val=val_init;};

		CString str;
		CString val;
	};
	
	CNonSortedStrStrArray(){}

	int  Add(LPCTSTR str, LPCTSTR val);	/**< Добавление комбинации. Возвращает индекс добавленного элемента*/
	
	long GetSize() const { return items.GetSize(); }	/**< Размер */
	CaplStrStrMapItem* GetAt(int index) const;			/**< Чтение элемента по индексу*/

	int  FindByIn(LPCTSTR str) const;	/**< Поиск индекса по строке*/
	int  FindByOut(LPCTSTR val) const;	/**< Поиск индекса по значению (долгий поиск перебором!)*/
	
protected:
	CaplTAggr <CaplStrStrMapItem*,CaplStrStrMapItem*,APLAGGR_LIST|APLAGGR_AUTOKILLREF> items;
};

// описывает одно поле, по которому можно проводить поиск
struct SFindAttrDef
{
	SFindAttrDef(CString _name4user,TypeFOAttr _type)
	{
		name4user = _name4user; type = _type; attr_path = 0; path_length = 0; e_top_parent = 0;a_top_parent_ref = 0;
	}
	~SFindAttrDef(){if(attr_path !=0 ) delete attr_path;}
	// тип атрибута - 
	TypeFOAttr type;
	// имя, которое показывается пользователю и заносится в текстовое описание запроса
	CString name4user;
	// если значение выбирается в диалоге - заголовок этого диалога
	CString m_sChooseTitle;
	// если значение выбирается в диалоге выбора инстанса - коневой инстанс
	CaplInstance *m_ciChooseParent;
	// тип диалога выбора
	TypeSelectInstance m_type_select;
	// цепочка атрибутов, к коорым применяется условие
	CFindAttrPath* attr_path;
	int path_length;
	// если надо найти например сборку, ссылающуюсю на ентити из CFindAttrPath - пишем сюда ее тип и атрибут ссылки
	CaplEntity* e_top_parent;
	CaplAttr* a_top_parent_ref;
	CNonSortedStrStrArray m_list_selected_string;

	void SetFuncParam(TypeSelectInstance type_select, CaplInstance *ciRoot, CString sTitle) { m_ciChooseParent=ciRoot; m_sChooseTitle=sTitle; m_type_select = type_select; }
	void AddSelectedString(LPCTSTR selected_string, LPCTSTR saved_string=_T("")){m_list_selected_string.Add(selected_string, saved_string);};
};

// описание типа объекта для поиска
struct SFindObjectDef
{
	SFindObjectDef(CString _name4user,TypeFindObject _type,CString _object_name){ name4user = _name4user; type = _type; m_object_name = _object_name;}
	TypeFindObject type;
	// имя, которое показывается пользователю и заносится в текстовое описание запроса
	CString name4user;
	//
	CString m_object_name;
	// список атрибутов, по которым может производиться поиск
	CaplTAggr<SFindAttrDef*,SFindAttrDef*,APLAGGR_UNIQUE_LIST_AUTOKILLREF> list_attrs;
};

// структура для описания одной строки условия 
struct STypeLogRelVal
{
	STypeLogRelVal(TypeFOAttr _type,CaplQLQuery::aplQLLogRelation _log_rel,CaplValue &_value,CaplValue &_value2)
	{
		type = _type;log_rel=_log_rel;value.Set(_value);value2.Set(_value2);
	}
	TypeFOAttr type; // тип атрибута
	CaplQLQuery::aplQLLogRelation log_rel; // логическое отношение
	CaplValue value; // значение атрибута
	CaplValue value2; // значение атрибута
};

// массив значений, введенных юзером, с приведением к типу атрибута
class CType2ValuesArray
{
protected:
// 	CUIntArray types; // массив отбъектов типа TypeFOAttr
// 	CUIntArray log_rels; // массив отбъектов типа CaplQLQuery::aplQLLogRelation
// 	CaplTAggr<CaplValue*,CaplValue*,APLAGGR_LIST_OR_AUTOKILLREF> values;
 	CaplTAggr<STypeLogRelVal*,STypeLogRelVal*,APLAGGR_LIST_OR_AUTOKILLREF> attr_log_vals;

public:
	CType2ValuesArray(){};
	bool IsExist(TypeFOAttr type);
	bool Add(TypeFOAttr type,CaplQLQuery::aplQLLogRelation val_log_rel,CaplValue &value,CaplValue &value2);
	bool Set(TypeFOAttr type,CaplQLQuery::aplQLLogRelation val_log_rel);
	bool Set(TypeFOAttr type,CaplValue &value,CaplValue &value2);
	bool Get(TypeFOAttr type,CaplQLQuery::aplQLLogRelation &val_log_rel,CaplValue &value,CaplValue &value2);
	bool Del(TypeFOAttr type);
	bool Clear();
	bool CopyFrom(CType2ValuesArray &source);
};


// структура для описания одной строки условия 
struct STypeLogRelations
{
	STypeLogRelations(){def=0;}
	TypeFOAttr type; // тип атрибута
	CUIntArray log_rels; // набор возможных логических отношений для этого типа
	int def; // номер отношения по умолчанию
};
// массив допустимых отношений для типов аттрибутов
class CType2LogRels
{
protected:
// 	CUIntArray types; // массив отбъектов типа TypeFOAttr
// 	CaplTAggr<CUIntArray*,CUIntArray*,APLAGGR_LIST_OR_AUTOKILLREF> log_rels_arrs; // CaplQLQuery::aplQLLogRelation
// 	CUIntArray defs; // значения отношений по умолчаниюю
	CaplTAggr<STypeLogRelations*,STypeLogRelations*,APLAGGR_LIST_OR_AUTOKILLREF> type2log_rels; 

public:
	bool Add(TypeFOAttr type,CaplQLQuery::aplQLLogRelation log_rel,bool def=false);
	bool Get(TypeFOAttr type,CUIntArray &log_rels_arr,int &def);
	bool Is(TypeFOAttr type);
	bool Clear();
};


class CMyComboBox : public CComboBox
{
	DECLARE_DYNAMIC(CMyComboBox)

public:
	CMyComboBox(){};
	CRect m_rect_draw;

	BOOL SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags);
protected:
	//{{AFX_MSG(CMyComboBox)
	afx_msg void OnPaint();
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()

};

enum aplValueTypeEx 
{
	apl_DATE = 100,
	apl_STRING_S1 = 101,
	apl_STRING_S2 = 102,
	apl_STRING_S3 = 103,
	apl_STRING_S4 = 104,
	apl_STRING_S5 = 105,
	apl_STRING_S6 = 106,


	aplINSTANCE_S0 = 150,
	aplINSTANCE_S1 = 151,
	aplINSTANCE_S2 = 152,
	aplINSTANCE_S3 = 153,
	aplINSTANCE_S4 = 154,
	aplINSTANCE_S5 = 155,
	aplINSTANCE_S6 = 156,
	aplINSTANCE_S7 = 157,
	aplINSTANCE_S8 = 158,
	aplINSTANCE_S9 = 159,
	aplINSTANCE_S10 = 160,
	aplINSTANCE_S11 = 161,
	aplINSTANCE_S12 = 162,
	aplINSTANCE_S13 = 163,
	aplINSTANCE_S14 = 164

};


/////////////////////////////////////////////////////////////////////////////
// CFindQueryDlgEx dialog

class CFindQueryDlgEx : public CResizableDialog
{
	// Construction
public:

	CFindQueryDlgEx(CWnd* pParent = NULL);   // standard constructor
	~CFindQueryDlgEx();

	void DrawTabPage();
	void SetTabPagesActive(TypeFindObject old_mode);
	void SetTabPagesEnable(BOOL mode);
	bool GenerateStepQL(bool show_message=true);
	bool SetDataBuf(CaplDataBuf &dbuf);
	bool GetDataBuf(CaplDataBuf &dbuf);
	bool TestNameQuery();

	void FillTabAdjust();
	void FillTabAdjustCharact();

	void BeginEditAttrRel();
	void BeginEditAttrDef();
	void BeginEditAttrVal();
	void CalcMoveEdit(int column);

	CaplAPI *m_api;
	CaplInstance *m_instance;

	// если в комбобоксе "Искать..." должен быть только один-два типа объекта (для SelectInstance)
	long m_vis_mode;
	// если true - можно показывать галочку "Отобразить результаты в таблице"
	bool m_can_make_table;
	// если true - доступна функция "сохранить запрос в БД"
	bool m_can_save;
	// если true - используется как вспомогательный запрос (без инстансы, имени запроса и без иаблицы)
	bool m_mode_slave;
	CString	m_StringNameQuery;
	BOOL	m_IsMakeTableResult;

	int m_indx_of_zero_approval;

	// этот тип объектов искали в последний раз
	TypeFindObject m_mode;

	// если эту переменную установили в выхывающей функции - доступен соответсвующий переключатель в диалоге
	// результат переключателя пишется в переменную
	bool *m_is_new_window;

	CString m_mode_text;
	CString m_descrtiption;

	// массив типов (ентитей) для поиска с атрибутами, по которым возможен поиск
	CaplTAggr<SFindObjectDef*,SFindObjectDef*,APLAGGR_UNIQUE_LIST_AUTOKILLREF> m_all_find_ojects;
	// описатель текущего типа (ентити), выбранного в поле "Найти..."
	SFindObjectDef* m_curr_type_descr;
	// массив значений, введенных юзером для каждого типа атрибутов
	CType2ValuesArray m_attr_values;
	CType2ValuesArray m_attr_values_history[FindObject_MAX];
	// массив допустимых отношений для типов аттрибутов
	CType2LogRels m_attr_types2log_rel;
	// текущее состояние комбобокса выбора-редактирования
	TypeSelectCombo m_curr_combo4edit;
	// номер строки, для которой открыт комбобокс редактирования
	DWORD m_num_curr_combo4edit;


	TypeAdj m_page_num;
	bool m_is_adjustment;
	bool m_read_only;
	bool m_changed;
	bool m_single_mode;
	int m_cur_ext_num;
	// Окончательный запрос
	CString m_QL_query;
	// строки с условиями на атрибуты самого объекта
	CString m_object_name;
	CString m_object_condition;
	// Строки для заполнения экcтентов и полей (fields)
	CString m_extents;
	CString m_blob_query;
	CString m_fields;


	CString	m_StringSource;
	CString	m_StringType;

	CStringArray m_AttrsWithLongPerform;

	//	CaplQLQuery::CaplQLBranchSelect* m_bsel_res;
	// Dialog Data
	//{{AFX_DATA(CFindQueryDlgEx)
	enum { IDD = IDD_FIND_QUERY_EX };
	//CMyComboBox	m_Cmbx4Edit;
	CMyComboBox	m_Cmbx4Edit;
	CMyComboBox	m_CmbxEdit4Edit;
	CEdit	m_Edit4Edit;
	CDateTimeCtrl m_CtrlDate4Edit;
	CDateTimeCtrl m_CtrlDate4Edit2;
	COleDateTime m_Date4Edit;
	COleDateTime m_Date4Edit2;
	CWnd* m_ActiveCtrl;
	HWND m_hwndEditInComboItem;
	bool m_edit2date;

	CButton	m_BtnType;
	CStatic	m_st_header;
	CEdit	m_edt_name_query;
	CComboBox	m_SelectFindType;
	CButton	m_ctrl_find_version;
	CButton	m_BtnAdjEdit;
	CButton	m_BtnAdjDel;
	CButton	m_BtnAdjAdd;
	CSortListCtrl	m_ListAdjust;
	CSortListCtrl	m_ListAttributes;
	CButton	m_BtnAttrAdd;
	CButton	m_BtnAttrDel;
	CButton	m_BtnAttrEdit;
	CTabCtrl	m_TabAdjust;
	CButton	m_ChkSaveQuery;
	CaplButton	m_BtnFind;
	CaplButton	m_BtnCancel;
	CaplButton	m_BtnShowStepQl;
	CButton	m_CtrlMakeTableResult;
	BOOL	m_StateSaveQuery;
	//}}AFX_DATA


	// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CFindQueryDlgEx)
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

	// Implementation
protected:
	CBitmap m_name_bmp;
	CImageList imagelist_tab;
	CImageList imagelist_but;
	CImageList imagelist_list_attr;

	bool m_is_load_bmp;

	HICON m_adj_add_icon;
	HICON m_adj_del_icon;
	HICON m_adj_edit_icon;

	BOOL TestEndEdit(MSG* pMsg);

	void PrepareListFindOjects();

	bool MakeObjectIdentify();
	//BOOL OnToolTipShow( UINT id, NMHDR * pNMHDR, LRESULT * pResult ); ЯАИ:  Перенесено в CaplTranslateDialog

	bool MakeQueryChar();
	bool MakeQueryDoc ();
	bool MakeQueryAppr();
	bool MakeQueryRes ();
	bool MakeQueryBlob();
	bool MakeQueryClassif();

	long GetAttrType(SFindAttrDef *attr_def);

	// управление скобками в логическом выражении
	// пока что отрезано, как избыточная функециональность
	//void CheckSubStringCtrl();

	bool SaveDataToBufBaseString(CString str_par);
	bool SaveDataToBuf();
	bool Save2BufListQChar();
	bool LoadFromBufBaseString(CString &str_par);
	bool LoadDataFromBuf();
	bool LoadFromBufListQChar();
	CaplDataBuf *m_dbuf;

	void AttributesAdd();
	void AttributesDel();

	void SetAdjAndOr(bool is_or);

	void CorrectFieldDescr1(int size, bool is_or);
	void CorrectFieldDescr2(int i, bool is_or);
	void CorrectFieldDescr3(int size, bool is_or);

	void PrintDateValues(bool edit2date,CString &str_val);

	//	CString FillDateCompare(CaplQLQuery::aplQLLogRelation log_relation,int year,int month,int day);
	CString FillDateCompare(CString name_attr, CaplQLQuery::aplQLLogRelation log_relation,COleDateTime* dtt);
	void MakeExtAndField(CaplEntity *base_entity, CaplAttr *attr, CString conditions, bool is_exist);
	CString FillCharValue(ElValChar* el_ch,CaplEntity** base_entity);
	void SetHiglight();

	// Generated message map functions
	//{{AFX_MSG(CFindQueryDlgEx)
	afx_msg void OnSelchangeTabAdjust(NMHDR* pNMHDR, LRESULT* pResult);
	virtual BOOL OnInitDialog();
	afx_msg void OnSelchangeSelectFindType();
	afx_msg void OnAdjustAdd();
	afx_msg void OnAdjustDel();
	afx_msg void OnAdjustEdit();
	afx_msg void OnChkFindVersion();
	afx_msg void OnExecuteFind();
	afx_msg void OnRclickListAdjust(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnDblclkListAdjust(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnRclickListAttributes(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnDblclkListAttributes(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnShowStepql();
	afx_msg void OnChkSaveQuery();
	afx_msg void OnChangeEdit();
	afx_msg void OnChangeEditNameQuery();
	afx_msg void OnBnClickedBtnAttrAdd();
	afx_msg void OnBnClickedBtnAttrDel();
	afx_msg void OnBnClickedBtnAttrEdit();
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()

	aplExtent m_list_project_types;
	CaplTAggr<ElValChar*,ElValChar*,APLAGGR_UNIQUE_LIST_AUTOKILLREF> m_list_char;
	CaplTAggr<ElValDoc*,ElValDoc*,APLAGGR_UNIQUE_LIST_AUTOKILLREF> m_list_doc;
	CaplTAggr<ElValApproval*,ElValApproval*,APLAGGR_UNIQUE_LIST_AUTOKILLREF> m_list_approval;
	CaplTAggr<ElValRes*,ElValRes*,APLAGGR_UNIQUE_LIST_AUTOKILLREF> m_list_res;
	CaplTAggr<ElValBLOB*,ElValBLOB*,APLAGGR_UNIQUE_LIST_AUTOKILLREF> m_list_blob;
	CaplTAggr<ElValClass*,ElValClass*,APLAGGR_UNIQUE_LIST_AUTOKILLREF> m_list_class;

	bool m_is_or_char;
	bool m_is_or_doc;
	bool m_is_or_approval;
	bool m_is_or_res;
	bool m_is_or_blob;
	bool m_is_or_class;
public:
	CButton m_CtrlMakeNewWindow;
	BOOL m_IsNewWindow;
	BOOL m_IsSubstring;
	BOOL m_IsBrackets;
	afx_msg void OnBnClickedChkSubstring();
	afx_msg void OnBnClickedChkBrackets();
	afx_msg void OnBnClickedChkMakeNewWindow();
	afx_msg void OnBnClickedChkMakeTableResult();
	afx_msg void OnSize(UINT nType, int cx, int cy);
	CButton m_CtrlChkSubstring;
	CButton m_CtrlChkBrackets;
	CButton m_CtrlRadioOr;
	CButton m_CtrlRadioAnd;
	CButton m_CtrlMatchCase;
	afx_msg void OnBnClickedRadioAndOr();
	CStatic m_st_tab_cond_ctrl;
	BOOL m_IsMatchCase;
	afx_msg void OnBnClickedChkMatchCase();
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_FINDQUERYDLGEX_H__572F8F65_AE26_4B51_8BDE_74505F8B1EA0__INCLUDED_)
