// RefusalFilterDlg.cpp : implementation file
//

#include "stdafx.h"
#include "RefusalFilterDlg.h"


// CRefusalFilterDlg dialog

IMPLEMENT_DYNAMIC(CRefusalFilterDlg, CaplTranslateDialog)

CRefusalFilterDlg::CRefusalFilterDlg(CaplFaultMgr *FaultMgr, CWnd* pParent /*=NULL*/)
	: CaplTranslateDialog(CRefusalFilterDlg::IDD, pParent)
{
	m_FaultMgr = FaultMgr;

	m_pSQLparts = 0;
	m_nID = WM_USER+2000;

	m_nTop = 38;
	m_nSpacesHor = 2;
	m_nSpacesVert = 16;
	m_nLeftStart = 7;
	m_nDefHeight = 12;
	m_nComboLeftWidth = 270;	
	m_nComboCenterWidth = 100;	
	m_nValueEditCtrlWidth = 270;
	m_add_to_last_found=false;
	m_bUseOrCondition=false;
}

CRefusalFilterDlg::~CRefusalFilterDlg()
{
}

void CRefusalFilterDlg::DoDataExchange(CDataExchange* pDX)
{
	CaplTranslateDialog::DoDataExchange(pDX);

	DDX_Control(pDX, IDOK, m_ok_btn);
	DDX_Control(pDX, IDCANCEL, m_cancel_btn);
	DDX_Control(pDX, IDC_ADD, m_add);
	DDX_Control(pDX, IDC_DEL, m_minus);
	DDX_Control(pDX, IDC_RESTORE, m_restore);
	DDX_Control(pDX, IDC_ADD_TO_LAST_FOUND, m_add_to_last_found_ctrl);
	DDX_Control(pDX, IDC_CONDITION_TYPE, m_condition_type_combo);
}

BEGIN_MESSAGE_MAP(CRefusalFilterDlg, CaplTranslateDialog)	
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_ADD, OnAdd)
	ON_BN_CLICKED(IDC_DEL, OnMinus)
	ON_CONTROL_RANGE(CBN_SELCHANGE, WM_USER, WM_USER+7000, OnCBN)
	ON_CONTROL_RANGE(BN_CLICKED, WM_USER, WM_USER+7000, OnBtnClick)
	ON_BN_CLICKED(IDC_RESTORE, &CRefusalFilterDlg::OnBnClickedRestore)	
	ON_BN_CLICKED(IDOK, &CRefusalFilterDlg::OnBnClickedOk)
END_MESSAGE_MAP()

BOOL CRefusalFilterDlg::OnInitDialog()
{
	CaplTranslateDialog::OnInitDialog();

	CreateFont();

	// создаем первое условие
	CenterWindow();
	AddNewCondition();

	// кнопки
	m_ok_btn.SetFlat(FALSE);
	m_ok_btn.SetIcon(GetAplStdIco16(APLSTDICO_OK));
	m_cancel_btn.SetFlat(FALSE);
	m_cancel_btn.SetIcon(GetAplStdIco16(APLSTDICO_CANCEL));

	m_add.SetFlat(FALSE);
	m_add.SetIcon(GetAplStdIco16(APLSTDICO_PLUS));
	m_minus.SetFlat(FALSE);
	m_minus.SetIcon(GetAplStdIco16(APLSTDICO_MINUS));	
	m_restore.SetFlat(FALSE);

	m_condition_type_combo.InsertString(0,APL_T("Все условия (объединение \"И\")"));
	m_condition_type_combo.InsertString(1,APL_T("Любое из условий (объединение \"ИЛИ\")"));
	m_condition_type_combo.SetCurSel(0);

	BuildDialogBySQL();

	return TRUE;
}

void CRefusalFilterDlg::OnCancel()
{
	CaplTranslateDialog::OnCancel();
}

CString CRefusalFilterDlg::GetConditionValue(CCondition *pCond, int nIndex)
{
	CString t_str;

	if(pCond->GetType() == COND_STRING)
	{
		if(pCond->GetDefaultValueSize())
		{
			m_caEditCtrl[nIndex]->m_pCombo->GetWindowText(t_str);
		}
		else
		{
			m_caEditCtrl[nIndex]->m_pEdit->GetWindowText(t_str);
		}
		
		t_str = _T("'") + t_str + _T("'");
	}
	else if(pCond->GetType() == COND_INSTANCE)
	{
		if(m_caEditCtrl[nIndex]->m_ciValue) t_str.Format(_T("#%d"), m_caEditCtrl[nIndex]->m_ciValue->GetId());
		else t_str = _T("#0");
	}
	else if(pCond->GetType() == COND_DATE)
	{
		COleDateTime time;
		m_caEditCtrl[nIndex]->m_pDate->GetTime(time);
		aplDate2String(time, t_str);

		t_str = m_FaultMgr->NullTimeInDate(t_str);
		t_str = _T("'") + t_str + _T("'");
	}

	return t_str;
}

CCondition* CRefusalFilterDlg::GetConditionByAttr(CString sAttr)
{
	for(int i=0; i<m_FaultMgr->m_caConditionTmpl.GetSize(); i++)
	{
		if(m_FaultMgr->m_caConditionTmpl[i]->GetAttr() == sAttr)
			return m_FaultMgr->m_caConditionTmpl[i];
	}

	return 0;
}

CConditionOperation* CRefusalFilterDlg::GetOperation(CString sOp)
{
	for(int i=0; i<m_FaultMgr->m_caOperationsTmpl.GetSize(); i++)
	{
		if(m_FaultMgr->m_caOperationsTmpl[i]->GetOperation() == sOp)
			return m_FaultMgr->m_caOperationsTmpl[i];
	}

	return 0;
}

void CRefusalFilterDlg::SetValue(CEditValueCtrl *pEditValueCtrl, EConditionType type, CString sValue)
{
	if(type == COND_DATE)
	{
		COleDateTime time;

		// избавляемся от кавычек
		sValue.Delete(0);
		sValue.Delete( sValue.GetLength()-1 );

		// пишем значение
		aplString2Date(sValue, time);
		if(pEditValueCtrl->m_pDate)
			pEditValueCtrl->m_pDate->SetTime(time);

	}
	else if(type == COND_INSTANCE)
	{
		CString str;

		// избавляемся от #
		sValue.Delete(0);

		// пишем значение
		pEditValueCtrl->m_ciValue = m_FaultMgr->GetAPI()->m_data.GetInstById(_atoi(sValue));
		if(pEditValueCtrl->m_ciValue && pEditValueCtrl->m_pEdit) 
		{
			m_FaultMgr->GetAPI()->GetItemName(pEditValueCtrl->m_ciValue, str);
			pEditValueCtrl->m_pEdit->SetWindowText(str);
		}

	}
	else if(type == COND_STRING)
	{
		// избавляемся от кавычек
		sValue.Delete(0);
		sValue.Delete( sValue.GetLength()-1 );

		// пишем значение
		if(pEditValueCtrl->m_pEdit) pEditValueCtrl->m_pEdit->SetWindowText(sValue);
		else if(pEditValueCtrl->m_pCombo) pEditValueCtrl->m_pCombo->SelectString(-1, sValue);
	}
}

void CRefusalFilterDlg::BuildDialogBySQL()
{
	if(m_pSQLparts == 0) return;
	if(m_pSQLparts->GetSize() == 0) return;

	int nLast;

	// сторим диалог по частям SQL запроса
	for(int i=0; i<m_pSQLparts->GetSize(); i+=3)
	{
		// добалвяем строку
		if(i != 0) AddNewCondition();
	
		nLast = m_caField.GetSize()-1;

		// атрибут
		CCondition *pCond = GetConditionByAttr(m_pSQLparts->GetAt(i));
		m_caField[nLast]->SelectString( -1, pCond->GetName() );
		ComboBoxNotify(m_caField[nLast]->GetDlgCtrlID());
		
		// условие
		CConditionOperation *pCondOp = GetOperation(m_pSQLparts->GetAt(i+1));
		m_caOperation[nLast]->SelectString( -1, pCondOp->GetName() );

		// значение
		SetValue(m_caEditCtrl[nLast], pCond->GetType(), m_pSQLparts->GetAt(i+2));		
	}
}

void CRefusalFilterDlg::ComboBoxNotify(int nID)
{
	int i = 0;
	CComboBox *pTmpl = (CComboBox*)GetDlgItem(nID);
	if(!pTmpl) return;

	// кликнули на комбобоксе условий?
	for(i=0; i<m_caField.GetSize(); i++)
	{
		CComboBox *pBox = m_caField[i];
		if(pBox == pTmpl) 
		{
			CCondition *pCond = (CCondition*)pBox->GetItemData( pBox->GetCurSel() );

			// заполняем возможные операции
			PrepareCondition(pCond, i);

			// показываем окно ввода значения
			ShowValueEditCtrl(pBox, pCond, i);
		}
	}
}

void CRefusalFilterDlg::BuildSQLbyDialog()
{
	if(!m_pSQLparts) return;

	int condition=m_condition_type_combo.GetCurSel();
	if(1==condition) m_bUseOrCondition=true;
	else m_bUseOrCondition=false;

	// проходим по всем компонентам и "собираем
	// по частям" наш запрос

	m_pSQLparts->RemoveAll();
	for(int i=0; i<m_caField.GetSize(); i++)
	{
		CCondition *pCond = (CCondition*)m_caField[i]->GetItemData(m_caField[i]->GetCurSel());
		if(!pCond) continue;

		CConditionOperation *pCondOp = (CConditionOperation*)m_caOperation[i]->GetItemData(m_caOperation[i]->GetCurSel());
		if(!pCondOp) continue;

		m_pSQLparts->Add(pCond->GetAttr());
		m_pSQLparts->Add(pCondOp->GetOperation());
		m_pSQLparts->Add(GetConditionValue(pCond, i));		
	}	
}

void CRefusalFilterDlg::OnOK()
{
	BuildSQLbyDialog();

	m_add_to_last_found=false;
	if(m_add_to_last_found_ctrl.GetCheck()) m_add_to_last_found=true;

	CaplTranslateDialog::OnOK();
}

void CRefusalFilterDlg::AddConditionOperation()
{
	CRect rect(m_nLeftStart+m_nComboLeftWidth+m_nSpacesHor, m_nTop, m_nLeftStart+m_nComboLeftWidth+m_nSpacesHor+m_nComboCenterWidth, m_nTop + m_nDefHeight);
	CComboBox *pBox = 0;

	// создаем условие
	CreateComboBox(&pBox, rect);
	m_caOperation.Add(pBox);

	pBox->GetWindowRect(rect);
	rect.bottom += 100;
	ScreenToClient(rect);
	pBox->MoveWindow(rect);
}

void CRefusalFilterDlg::AddConditionType()
{
	CRect rect(m_nLeftStart, m_nTop, m_nLeftStart+m_nComboLeftWidth, m_nTop + m_nDefHeight);
	CComboBox *pBox = 0;

	// создаем условие
	CreateComboBox(&pBox, rect);
	m_caField.Add(pBox);

	// заполянем возможными условиями
	for(int i=0; i<m_FaultMgr->m_caConditionTmpl.GetSize(); i++)
	{
		CCondition *pp =  m_FaultMgr->m_caConditionTmpl[i];
		pBox->InsertString(i, m_FaultMgr->m_caConditionTmpl[i]->GetName());	
		pBox->SetItemData(i, (DWORD)m_FaultMgr->m_caConditionTmpl[i]);
	}

	IncreaseComboBoxDroppedList(pBox);
}

void CRefusalFilterDlg::IncreaseComboBoxDroppedList(CComboBox *pBox)
{
	CRect rect;

	pBox->GetWindowRect(rect);
	rect.bottom += 500;
	ScreenToClient(rect);
	pBox->MoveWindow(rect);		
}

void CRefusalFilterDlg::MoveWnd(CWnd *Wnd, bool bIncrease, bool bMoveOnly)
{
	CRect rect;
	int nDelta = nDelta = m_nDefHeight + m_nSpacesVert;;
	Wnd->GetWindowRect(rect);
	if(!bIncrease) nDelta *= -1;

	rect.bottom += (nDelta);
	if(bMoveOnly) rect.top += (nDelta);

	ScreenToClient(rect);
	Wnd->MoveWindow(rect);	
}

void CRefusalFilterDlg::ResizeDialog(bool bIncrease)
{
	MoveWnd(this, bIncrease, false);
	CenterWindow();
	
	MoveWnd(GetDlgItem(IDOK), bIncrease);
	MoveWnd(GetDlgItem(IDCANCEL), bIncrease);
	MoveWnd(GetDlgItem(IDC_ADD), bIncrease);
	MoveWnd(GetDlgItem(IDC_DEL), bIncrease);
	MoveWnd(GetDlgItem(IDC_RESTORE), bIncrease);
	MoveWnd(GetDlgItem(IDC_ADD_TO_LAST_FOUND), bIncrease);
}

void CRefusalFilterDlg::DelCondition()
{
	int nLast = m_caField.GetSize() - 1;

	// условие
	//m_caField[nLast]->DestroyWindow();
	delete m_caField[nLast];
	m_caField[nLast] = 0;
	m_caField.RemoveAt(nLast);

	// операция
	delete m_caOperation[nLast];
	m_caOperation[nLast] = 0;
	m_caOperation.RemoveAt(nLast);

	// значение
	delete m_caEditCtrl[nLast];
	m_caEditCtrl[nLast] = 0;
	m_caEditCtrl.RemoveAt(nLast);

	// сокращаем диалог
	ResizeDialog(false);

	// уменьшаем смещение	
	m_nTop = m_nTop - m_nDefHeight - m_nSpacesVert;
}

void CRefusalFilterDlg::AddNewCondition()
{
	// добавляем условие, операцию и элемент выбора
	AddConditionType();
	AddConditionOperation();
	m_caEditCtrl.Add(new CEditValueCtrl());

	// условие по умолчанию
	m_caField[ m_caField.GetSize()-1 ]->SetCurSel(0);
	ComboBoxNotify(m_caField[ m_caField.GetSize()-1 ]->GetDlgCtrlID());

	// двигаем диалог и кнопки ок отмена
	ResizeDialog();

	// увеличиваем смещение	
	m_nTop = m_nTop + m_nDefHeight + m_nSpacesVert;
}

void CRefusalFilterDlg::OnAdd()
{
	AddNewCondition();
	DisableBtns();
}

void CRefusalFilterDlg::DisableBtns()
{
	if(m_caField.GetSize() > 1) m_minus.EnableWindow(TRUE);
	else m_minus.EnableWindow(FALSE);

	if(m_caField.GetSize() >= 24) m_add.EnableWindow(FALSE);
	else m_add.EnableWindow(TRUE);
}

void CRefusalFilterDlg::OnMinus()
{
	DelCondition();
	DisableBtns();
}

void CRefusalFilterDlg::OnBtnClick(UINT id)
{
	CString t_str;
	CaplButton *pTmpl = (CaplButton*)GetDlgItem(id);
	if(!pTmpl) return;

	for(int i=0; i<m_caEditCtrl.GetSize(); i++)
	{
		if(pTmpl == m_caEditCtrl[i]->m_pOk)
		{
			// получаем наше условие
			CCondition *pCond = (CCondition*)m_caField[i]->GetItemData( m_caField[i]->GetCurSel() );
			if(!pCond) return;

			// выбираем новую инстанс
			CaplInstance *ciRes = pCond->lpFuncChoose(m_FaultMgr->GetAPI(), m_FaultMgr->GetExplMgr(), pCond->GetParentInst(), pCond->GetTitle());
			if(!ciRes) return;

			// отображаем то, что выбрали
			m_caEditCtrl[i]->m_ciValue = ciRes;
			m_FaultMgr->GetAPI()->GetItemName(ciRes, t_str);
			m_caEditCtrl[i]->m_pEdit->SetWindowText(t_str);

			return;
		}
		else if(pTmpl == m_caEditCtrl[i]->m_pClear)
		{
			m_caEditCtrl[i]->m_ciValue = 0;
			m_caEditCtrl[i]->m_pEdit->SetWindowText(_T(""));

			return;
		}
	}
}

void CRefusalFilterDlg::OnCBN(UINT id)
{
	ComboBoxNotify(id);
}

void CRefusalFilterDlg::PrepareCondition(CCondition *pCond, int nIndex)
{
	// получаем
	CComboBox *pOperationBox = m_caOperation[nIndex];
	pOperationBox->ResetContent();
	
	// заполняем
	for(int i=0; i<pCond->GetOperationsSize(); i++)
	{
		pOperationBox->InsertString(i, pCond->GetOperation(i)->GetName());
		pOperationBox->SetItemData(i, (DWORD)pCond->GetOperation(i));		
	}

	// выделяем
	if(pCond->GetOperationsSize()) pOperationBox->SetCurSel(0);
}

void CRefusalFilterDlg::CreateComboBox(CComboBox **pBox, CRect rect)
{
	*pBox = new CComboBox();
	(*pBox)->Create(WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST, rect, this, GetNewId());
	(*pBox)->SetFont(&m_font);
}

void CRefusalFilterDlg::CreateEdit(CEdit **pBox, CRect rect, bool bReadOnly)
{
	rect.bottom -= 1;

	*pBox = new CEdit();
	(*pBox)->Create(WS_CHILD|WS_VISIBLE|WS_BORDER|ES_AUTOHSCROLL, rect, this, GetNewId());
	(*pBox)->SetReadOnly(bReadOnly);
	(*pBox)->SetFont(&m_font);
}

void CRefusalFilterDlg::CreateButton(CaplButton **pBtn, CRect rect, int nIco)
{
	*pBtn = new CaplButton();
	(*pBtn)->Create(_T(""), WS_CHILD|WS_VISIBLE, rect, this, GetNewId());
	(*pBtn)->SetFlat(TRUE);
	(*pBtn)->SetIcon(aplGetButtonIco(nIco));
	(*pBtn)->SetFont(&m_font);
}

void CRefusalFilterDlg::CreateDateTimeCtrl(CDateTimeCtrl **pBox, CRect rect)
{
	rect.top -= 1;

	*pBox = new CDateTimeCtrl();
	(*pBox)->Create(WS_CHILD|WS_VISIBLE|WS_BORDER|DTS_LONGDATEFORMAT, rect, this, GetNewId());
	(*pBox)->SetFont(&m_font);
}

void CRefusalFilterDlg::ShowValueEditCtrl(CComboBox *pBox, CCondition *pCond, int nIndex)
{
	int i = 0;

	// скрываем старые старые
	m_caEditCtrl[nIndex]->Clear();
	
	// узнаем место под будующий контролл
	CRect boxRect;
	pBox->GetWindowRect(boxRect);
	ScreenToClient(boxRect);

	CRect rect(m_nLeftStart+m_nComboLeftWidth+m_nSpacesHor+m_nComboCenterWidth+m_nSpacesHor,
		boxRect.top,
		m_nLeftStart+m_nComboLeftWidth+m_nSpacesHor+m_nComboCenterWidth+m_nSpacesHor+m_nValueEditCtrlWidth,
		boxRect.bottom);

	// создаем
	if(pCond->GetType() == COND_STRING)
	{
		// смотрим что отображать: комбобокс или строку редактирования
		if(pCond->GetDefaultValueSize())
		{
			CreateComboBox(&m_caEditCtrl[nIndex]->m_pCombo, rect);
			IncreaseComboBoxDroppedList(m_caEditCtrl[nIndex]->m_pCombo);

			for(i=0; i<pCond->GetDefaultValueSize(); i++)
				m_caEditCtrl[nIndex]->m_pCombo->InsertString(i, pCond->GetDefaultValue(i));								
		}
		else
		{
			CreateEdit(&m_caEditCtrl[nIndex]->m_pEdit, rect);
		}
	}
	else if(pCond->GetType() == COND_DATE)
	{
		// дата
		CreateDateTimeCtrl(&m_caEditCtrl[nIndex]->m_pDate, rect);
	}
	else if(pCond->GetType() == COND_INSTANCE)
	{
		rect.right -= 50;

		// строка редактировния
		CreateEdit(&m_caEditCtrl[nIndex]->m_pEdit, rect, true);
		
		// кнопки
		CRect okRect(rect.right+1, rect.top, rect.right+25, rect.bottom);
		CreateButton(&m_caEditCtrl[nIndex]->m_pOk, okRect, APL_24_SELECT);

		CRect clearRect(okRect.right+1, okRect.top, okRect.right+25, okRect.bottom);
		CreateButton(&m_caEditCtrl[nIndex]->m_pClear, clearRect, APL_24_CANCEL);
	}
	else
	{
		AfxMessageBox(APL_T("Неизвестный тип условия!"));
	}
}

void CRefusalFilterDlg::CreateFont()
{
	ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
	NONCLIENTMETRICS nm;
	nm.cbSize = sizeof (NONCLIENTMETRICS);

	if(::SystemParametersInfo (SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0))
	{
		DWORD err= GetLastError();
		m_lf = nm.lfMenuFont;
		m_font.DeleteObject();
		m_font.CreateFontIndirect (&m_lf);
	}
	else 
	{
		m_font.CreatePointFont(90,_T("Tahoma"));		
	}
}

void CRefusalFilterDlg::ClearMemory()
{

}

void CRefusalFilterDlg::OnDestroy()
{
 	for(int i=0; i<m_caField.GetSize(); i++)
	{
		if(m_caField[i]) delete m_caField[i];
		if(m_caOperation[i]) delete m_caOperation[i];
		if(m_caEditCtrl[i]) delete m_caEditCtrl[i];
	}
}
void CRefusalFilterDlg::OnBnClickedRestore()
{
	for(int i=m_caField.GetSize()-1; i>=1; i--) OnMinus();

	m_caField[0]->SetCurSel(0);
	m_caOperation[0]->SetCurSel(0);
	m_caEditCtrl[0]->SetEmptyValue();

	ComboBoxNotify(m_caField[0]->GetDlgCtrlID());
}

void CRefusalFilterDlg::OnBnClickedOk()
{
	// TODO: Add your control notification handler code here
	OnOK();
}
