// MemberInfoDlg_ValidationStaticEnum.cpp : implementation file
//

#include "stdafx.h"
#include "AsCfgBuilder.h"
#include "MemberInfoDlg_ValidationStaticEnum.h"
#include "XmlMemberValidation_StaticEnum.h"
#include "XmlMemberValidation_StaticEnumItem.h"
#include "XmlMemberInfo.h"
#include "cmTableRow.h"
#include "cmBaseCell.h"
#include "cmGenericTextCell.h"
#include "cmNumericTextCell.h"
#include "MemDC.h"
#include "AsUtils.h"
#include "GuiDefs.h"

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

#define BORDER				5
#define COLUMNS_NUMBER		5
#define HEADER_FORECOLOR	RGB(80, 80, 150)

#define COL_INDEX_NUMBER		0
#define COL_INDEX_NAME			1
#define COL_INDEX_ENUM_VAL		2
#define COL_INDEX_ASSOC_VAL		3
#define COL_INDEX_DESCRIPTION	4

/////////////////////////////////////////////////////////////////////////////
// CMemberInfoDlg_ValidationStaticEnum dialog


CMemberInfoDlg_ValidationStaticEnum::CMemberInfoDlg_ValidationStaticEnum(CWnd* pParent /*=NULL*/)
	: CPropertyEditorDlg(CMemberInfoDlg_ValidationStaticEnum::IDD, pParent),
	initialized_(false)
{
	//{{AFX_DATA_INIT(CMemberInfoDlg_ValidationStaticEnum)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void CMemberInfoDlg_ValidationStaticEnum::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMemberInfoDlg_ValidationStaticEnum)
	DDX_Control(pDX, IDC_ENUM_PREFIX, lblEnumPrefix_);
	DDX_Control(pDX, IDC_CMD_REMOVE, cmdRemove_);
	DDX_Control(pDX, IDC_CMD_INSERT, cmdInsert_);
	DDX_Control(pDX, IDC_CMD_APPEND, cmdAppend_);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CMemberInfoDlg_ValidationStaticEnum, CPropertyEditorDlg)
	//{{AFX_MSG_MAP(CMemberInfoDlg_ValidationStaticEnum)
	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_CMD_INSERT, OnCmdInsert)
	ON_BN_CLICKED(IDC_CMD_APPEND, OnCmdAppend)
	ON_BN_CLICKED(IDC_CMD_REMOVE, OnCmdRemove)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMemberInfoDlg_ValidationStaticEnum message handlers
void CMemberInfoDlg_ValidationStaticEnum::SetData(CXmlBaseElement* element)
{
	memberInfo_ = dynamic_cast<CXmlMemberInfo*>(element);

	if (memberInfo_)
		lastDataType_ = memberInfo_->GetDataType();

	DisplayData();
}

void CMemberInfoDlg_ValidationStaticEnum::StoreData()
{
	cmTableRow* row;
	cmNumericTextCell* numericCell;
	CXmlMemberValidation_StaticEnum* enumInfo;
	cmString itemName;
	cmString itemDescription;
	cmString itemValue;
	long itemEnumValue;

	enumInfo = memberInfo_->GetValidationInfo()->GetStaticEnum();
	enumInfo->Clear();

	for (int i = table_.GetFixedRowsNumber(); i < table_.GetRowCount(); i++) {
		row = table_.GetRow(i);
		
		if (row == NULL)
			break;

		
		itemName = row->GetCell(COL_INDEX_NAME)->GetText();

		numericCell = dynamic_cast<cmNumericTextCell*>(row->GetCell(COL_INDEX_ENUM_VAL));
		itemEnumValue = numericCell->GetValue();

		switch (memberInfo_->GetDataType()) {
			case enDataType_String:
				itemValue = row->GetCell(COL_INDEX_ASSOC_VAL)->GetText();
				break;

			case enDataType_Long:
				numericCell = dynamic_cast<cmNumericTextCell*>(row->GetCell(COL_INDEX_ASSOC_VAL));
				itemValue = AsUtils::FormatDouble(numericCell->GetValue(), 0);
				break;

			case enDataType_Double:
				numericCell = dynamic_cast<cmNumericTextCell*>(row->GetCell(COL_INDEX_ASSOC_VAL));
				itemValue = AsUtils::FormatDouble(numericCell->GetValue(), memberInfo_->GetDecimalPlaces());
				break;

		}

		itemDescription = row->GetCell(COL_INDEX_DESCRIPTION)->GetText();

		enumInfo->AddEnumItem(itemName, itemEnumValue, itemValue, itemDescription);
	}
}

void CMemberInfoDlg_ValidationStaticEnum::OnDataUpdate()
{
	if (lastDataType_ != memberInfo_->GetDataType()) {
		UpdateValueColumn();
		lastDataType_ = memberInfo_->GetDataType();
	}
}

void CMemberInfoDlg_ValidationStaticEnum::OnSize(UINT nType, int cx, int cy) 
{
	CPropertyEditorDlg::OnSize(nType, cx, cy);
	
	UpdateWindowSize();
	
}

BOOL CMemberInfoDlg_ValidationStaticEnum::OnInitDialog() 
{
	CPropertyEditorDlg::OnInitDialog();
	
	ModifyStyle(0, WS_CLIPCHILDREN);

	table_.Create(CRect(0, 0, 0, 0), this, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, -1);

	initialized_ = true;

	// initialize table
	//
	cmTableRow* row;
	cmBaseCell* cell;
	CString tmp;
	vector<cmString> tmpList;

	table_.SetFixedColumnsNumber(1);
	table_.SetFixedRowsNumber(1);
	table_.SetColumnsNumber(COLUMNS_NUMBER);
	table_.SetBkColor(DIALOG_BACK_COLOR);

	row = table_.AppendRow(5, false);
	
	// build table headers list
	//
	tmpList.push_back(_T(""));
	tmpList.push_back(_T("Name"));
	tmpList.push_back(_T("Enum value"));
	tmpList.push_back(_T("Associated value"));
	tmpList.push_back(_T("Description"));

	// create first row (header)
	//
	for (int i = 0; i < tmpList.size(); i++) {
		if (i == 0)
			table_.SetColumnWidth(i, 30);
		else
			table_.SetColumnWidth(i, 200);
		cell = row->CreateCell(i, enCmTableCellType_Gradient);
		//cell->SetBackColor(::GetSysColor(COLOR_BTNFACE));
		//cell->SetForeColor(::GetSysColor(COLOR_BTNTEXT));
		cell->SetForeColor(RGB(80, 80, 150));
		cell->SetText(tmpList[i]);
		cell->SetFontInfo(_T("tahoma"), 11, true);
	}

	UpdateWindowSize();
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CMemberInfoDlg_ValidationStaticEnum::UpdateWindowSize()
{
	if(!initialized_)
		return;

	CRect lblRect;
	CRect btnRect;
	CRect tableRect;
	CRect rc;
	CRect tmp;

	GetClientRect(rc);
	lblEnumPrefix_.GetWindowRect(lblRect);
	ScreenToClient(lblRect);

	cmdInsert_.GetWindowRect(btnRect);
	ScreenToClient(btnRect);

	tmp.left = rc.right - BORDER - btnRect.Width();
	tmp.right = tmp.left + btnRect.Width();
	tmp.bottom = rc.bottom - BORDER;
	tmp.top = tmp.bottom - btnRect.Height();
	btnRect = tmp;
	cmdInsert_.SetWindowPos(&CWnd::wndTop, btnRect.left, btnRect.top, 0,0, SWP_NOSIZE);

	btnRect.OffsetRect(- tmp.Width() - BORDER, 0);
	cmdAppend_.SetWindowPos(&CWnd::wndTop, btnRect.left, btnRect.top, 0,0, SWP_NOSIZE);

	btnRect.OffsetRect(- tmp.Width() - BORDER, 0);
	cmdRemove_.SetWindowPos(&CWnd::wndTop, btnRect.left, btnRect.top, 0,0, SWP_NOSIZE);

	tableRect.left = BORDER;
	tableRect.top = lblRect.bottom + BORDER;
	tableRect.right = rc.right - BORDER;
	tableRect.bottom = btnRect.top - BORDER;

	table_.SetWindowPos(&CWnd::wndTop, tableRect.left, tableRect.top, tableRect.Width(), tableRect.Height(), SWP_SHOWWINDOW);
	
	RedrawWindow();
}





void CMemberInfoDlg_ValidationStaticEnum::OnCmdInsert() 
{
	cmTableRow* selectedRow;
	cmBaseCell* selectedCell;
	int rowIndex;
	int cellIndex;

	if (table_.GetSelectedItem(&selectedRow, &selectedCell, rowIndex, cellIndex))
		InsertRow(rowIndex, true);
	else
		InsertRow(table_.GetRowCount(), true);
}

void CMemberInfoDlg_ValidationStaticEnum::OnCmdAppend() 
{
	InsertRow(table_.GetRowCount(), true);
}

void CMemberInfoDlg_ValidationStaticEnum::OnCmdRemove() 
{
	cmTableRow* selectedRow;
	cmBaseCell* selectedCell;
	int rowIndex;
	int cellIndex;

	if (table_.GetSelectedItem(&selectedRow, &selectedCell, rowIndex, cellIndex))
		table_.DeleteRow(rowIndex, false);

	RenumberRows(true);
}

cmTableRow* CMemberInfoDlg_ValidationStaticEnum::InsertRow(int rowIndex, bool redraw)
{
	cmTableRow* newRow;
	cmBaseCell* cell;
	cmGenericTextCell* textCell;
	cmNumericTextCell* numCell;
	cmFontInfo fontInfo;

	fontInfo.SetFontName(_T("tahoma"));
	fontInfo.SetFontSize(11);
	fontInfo.SetFontBold(false);

	newRow = table_.InsertRow(rowIndex, COLUMNS_NUMBER);

	// initialize cell with number
	//
	cell = newRow->CreateCell(COL_INDEX_NUMBER, enCmTableCellType_Gradient);
	cell->SetForeColor(HEADER_FORECOLOR);
	cell->SetFontInfo(_T("tahoma"), 11, true);

	// initialize enum name's cell
	//
	textCell = dynamic_cast<cmGenericTextCell*>(newRow->CreateCell(COL_INDEX_NAME, enCmTableCellType_TextBox));
	textCell->SetFontInfo(fontInfo);

	// initialize enum value's cell
	//
	numCell = dynamic_cast<cmNumericTextCell*>(newRow->CreateCell(COL_INDEX_ENUM_VAL, enCmTableCellType_NumTextBox));
	numCell->SetPrecision(0);
	numCell->SetFontInfo(fontInfo);

	// initialize (associated value) cell
	//
	switch (memberInfo_->GetDataType()) {
		case enDataType_Long:
			numCell = dynamic_cast<cmNumericTextCell*>(newRow->CreateCell(COL_INDEX_ASSOC_VAL, enCmTableCellType_NumTextBox));
			numCell->SetPrecision(0);
			numCell->SetFontInfo(fontInfo);
			break;

		case enDataType_Double:
			numCell = dynamic_cast<cmNumericTextCell*>(newRow->CreateCell(COL_INDEX_ASSOC_VAL, enCmTableCellType_NumTextBox));
			numCell->SetPrecision(memberInfo_->GetDecimalPlaces());
			numCell->SetValue(0);
			numCell->SetFontInfo(fontInfo);
			break;

		case enDataType_String:
			textCell = dynamic_cast<cmGenericTextCell*>(newRow->CreateCell(COL_INDEX_ASSOC_VAL, enCmTableCellType_TextBox));
			textCell->SetFontInfo(fontInfo);
			break;
	}
	
	// initialize description's cell
	//
	textCell = dynamic_cast<cmGenericTextCell*>(newRow->CreateCell(COL_INDEX_DESCRIPTION, enCmTableCellType_TextBox));
	textCell->SetFontInfo(fontInfo);

	RenumberRows(false);
	
	if (redraw)
		table_.RedrawWindow();

	return newRow;
}

void CMemberInfoDlg_ValidationStaticEnum::RenumberRows(bool redraw)
{
	TCHAR buf[100];
	cmTableRow* row;
	cmBaseCell* cell;

	for (int i = table_.GetFixedRowsNumber(); i < table_.GetRowCount(); i++) {
		row = table_.GetRow(i);
		cell = row->GetCell(0);
		wsprintf(buf, _T("%d"), i + 1 - table_.GetFixedRowsNumber());
		cell->SetText(buf, false);
	}

	if (redraw)
		table_.RedrawWindow();
}

void CMemberInfoDlg_ValidationStaticEnum::UpdateValueColumn()
{
	cmTableRow* row;
	enDataType dataType;
	cmGenericTextCell* textCell;
	cmNumericTextCell* numCell;
	cmFontInfo fontInfo;

	fontInfo.SetFontName(_T("tahoma"));
	fontInfo.SetFontSize(11);
	fontInfo.SetFontBold(false);

	dataType = memberInfo_->GetDataType();

	for (int i = table_.GetFixedRowsNumber(); i < table_.GetRowCount(); i++) {
		row = table_.GetRow(i);
		
		switch (memberInfo_->GetDataType()) {
			case enDataType_Long:
				numCell = dynamic_cast<cmNumericTextCell*>(row->ReplaceCell(2, enCmTableCellType_NumTextBox));
				if (numCell) {
					numCell->SetPrecision(0);
					numCell->SetFontInfo(fontInfo);
				}
				break;

			case enDataType_Double:
				numCell = dynamic_cast<cmNumericTextCell*>(row->ReplaceCell(2, enCmTableCellType_NumTextBox));
				if (numCell) {
					numCell->SetPrecision(memberInfo_->GetDecimalPlaces());
					numCell->SetValue(0);
					numCell->SetFontInfo(fontInfo);
				}
				break;

			case enDataType_String:
				textCell = dynamic_cast<cmGenericTextCell*>(row->ReplaceCell(2, enCmTableCellType_TextBox));
				if (textCell)
					textCell->SetFontInfo(fontInfo);
				break;
		}	

	}

	table_.RedrawWindow();
}

void CMemberInfoDlg_ValidationStaticEnum::DisplayData()
{
	StaticEnumItems* items;
	CXmlMemberValidation_StaticEnumItem* item;
	cmTableRow* newRow;
	int rowIndex;
	cmGenericTextCell* textCell;
	cmNumericTextCell* numericCell;

	table_.DeleteNonFixedRows();

	items = memberInfo_->GetValidationInfo()->GetStaticEnum()->GetItems();

	rowIndex = 1;
	for (int i = 0; i < items->size(); i++) {
		item = (*items)[i];
		
		newRow = InsertRow(rowIndex, false);
		
		// setup name's cell
		//
		textCell = dynamic_cast<cmGenericTextCell*>(newRow->GetCell(COL_INDEX_NAME));
		textCell->SetText(item->GetItemName(), false);

		// setup enum value's cell
		//
		numericCell = dynamic_cast<cmNumericTextCell*>(newRow->GetCell(COL_INDEX_ENUM_VAL));
		numericCell->SetValue(item->GetItemEnumValue(), false);

		// setup value's cell
		//
		switch (memberInfo_->GetDataType()) {
			case enDataType_String:
				textCell = dynamic_cast<cmGenericTextCell*>(newRow->GetCell(COL_INDEX_ASSOC_VAL));
				textCell->SetText(item->GetItemValue(), false);
				break;

			case enDataType_Long:
				numericCell = dynamic_cast<cmNumericTextCell*>(newRow->GetCell(COL_INDEX_ASSOC_VAL));
				numericCell->SetValue(_wtoi(item->GetItemValue()), false);
				numericCell->SetPrecision(0);
				break;

			case enDataType_Double:
				numericCell = dynamic_cast<cmNumericTextCell*>(newRow->GetCell(COL_INDEX_ASSOC_VAL));
				numericCell->SetValue(wcstod(item->GetItemValue(), NULL), false);
				numericCell->SetPrecision(memberInfo_->GetDecimalPlaces());
				break;

		}

		// setup description's cell
		//
		textCell = dynamic_cast<cmGenericTextCell*>(newRow->GetCell(COL_INDEX_DESCRIPTION));
		textCell->SetText(item->GetItemDescription(), false);

		rowIndex++;
	}

	table_.RedrawWindow();

	// update enum prefix
	//
	cmString prefix;

	prefix = _T("en");
	prefix += memberInfo_->GetName();
	prefix += _T("_");

	lblEnumPrefix_.SetWindowText(prefix);
}