// GenerationReportDlg.cpp : implementation file
//

#include "stdafx.h"
#include "AsCfgBuilder.h"
#include "GenerationReportDlg.h"
#include "XmlProject.h"
#include "CppGenerationManager.h"
#include "AtlGenerationManager.h"
#include "CSharpGenerationManager.h"
#include "VisualCppRunDlg.h"
#include "GuiDefs.h"
#include "MemDC.h"
#include "DrawUtils.h"
#include "enums.h"
#include "GenerationPrefDlg.h"

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

#define SETTINGS_BK_COLOR_MID1_ENABLED			RGB(0xFF, 0xb5, 0x5C)
#define SETTINGS_BK_COLOR_BOTTOM_ENABLED		RGB(0xFF, 0xFF, 0xFF)	
#define PREF_WIDTH								300

/////////////////////////////////////////////////////////////////////////////
// CGenerationReportDlg dialog


CGenerationReportDlg::CGenerationReportDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CGenerationReportDlg::IDD, pParent),
	initialized_(false),
	project_(NULL),
	cppPref_(NULL),
	atlPref_(NULL)
{
	//{{AFX_DATA_INIT(CGenerationReportDlg)
	//}}AFX_DATA_INIT
}

CGenerationReportDlg::~CGenerationReportDlg()
{
	Clear();
}

void CGenerationReportDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CGenerationReportDlg)
	DDX_Control(pDX, IDOK, cmdClose_);
	DDX_Control(pDX, IDC_MSG, lblMsg_);
	DDX_Control(pDX, IDC_CMD_GENERATE, cmdGenerate_);
	DDX_Control(pDX, IDC_LVW_REPORT, lvwReport_);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CGenerationReportDlg, CDialog)
	//{{AFX_MSG_MAP(CGenerationReportDlg)
	ON_WM_CTLCOLOR()
	ON_BN_CLICKED(IDC_CMD_GENERATE, OnCmdGenerate)
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	ON_WM_CLOSE()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGenerationReportDlg message handlers

BOOL CGenerationReportDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// initialize image list
	//
	imageList_.Create(16, 16, ILC_COLOR32 | ILC_MASK, 4, 4);
	imageList_.Add(AfxGetApp()->LoadIcon(IDI_CLASS));
	imageList_.Add(AfxGetApp()->LoadIcon(IDI_ITEM_SELECTION));
	imageList_.Add(AfxGetApp()->LoadIcon(IDI_TASK_DONE));
	imageList_.Add(AfxGetApp()->LoadIcon(IDI_TASK_FAILED));
	imageList_.Add(AfxGetApp()->LoadIcon(IDI_TASK_DISABLED));

	// initialize report list view
	//
	CRect rc;

	lvwReport_.GetWindowRect(rc);
	lvwReport_.InsertColumn(0,_T(""), LVCFMT_LEFT, rc.Width());
	lvwReport_.SetImageList(&imageList_, LVSIL_SMALL);

	// add preferences
	//
	cppPref_ = AddCppPrefDialog(_T("Cpp Generation"));
	atlPref_ = AddAtlPrefDialog(_T("Atl Generation"));
	//cSharpPref_ = AddCSharpPrefDialog(_T("C# Generation"));
		
	UpdateGenerationButton();

	initialized_ = true;
	
	UpdateWindowSize();

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

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

	CRect rc;
	CRect prefRect;
	CRect btnRect;
	CRect lblRect;
	CRect reportRect;
	int top;

	GetClientRect(rc);

	cmdClose_.GetWindowRect(btnRect);
	
	cmdClose_.SetWindowPos( &CWnd::wndTop, 
							rc.Width() - BORDER - btnRect.Width(), 
							rc.bottom - BORDER - btnRect.Height(),
							0, 
							0, 
							SWP_SHOWWINDOW | SWP_NOSIZE);
	cmdClose_.GetWindowRect(btnRect);
	ScreenToClient(btnRect);


	cmdGenerate_.SetWindowPos(&CWnd::wndTop, 
							  btnRect.left - BORDER - btnRect.Width(),
							  btnRect.top,
							  0,
							  0,
							  SWP_SHOWWINDOW | SWP_NOSIZE);
	
	lblMsg_.SetWindowPos(&CWnd::wndTop, 
						 BORDER, 
						 btnRect.top - BORDER - 20,
						 rc.Width() - 2 * BORDER,
						 20,
						 SWP_SHOWWINDOW);
	lblMsg_.GetWindowRect(lblRect);
	ScreenToClient(lblRect);
	
	top = BORDER;
	for (int i = 0; i < preferences_.size(); i++) {
		preferences_[i]->GetWindowRect(prefRect);
		preferences_[i]->SetWindowPos(&CWnd::wndTop, BORDER, top, PREF_WIDTH, prefRect.Height(), SWP_SHOWWINDOW);
		top += (prefRect.Height() + BORDER);
	}
	
	reportRect.left = rc.left + PREF_WIDTH + 2 * BORDER;
	reportRect.top = BORDER;
	reportRect.bottom = lblRect.top - BORDER;
	reportRect.right = rc.right - BORDER;

	lvwReport_.SetWindowPos(&CWnd::wndTop, 
							reportRect.left, 
							reportRect.top,
							reportRect.Width(),
							reportRect.Height(),
							SWP_SHOWWINDOW);

	//SetWindowPos(&CWnd::wndTop, 0, 0, lvwRect.Width() + 2 * BORDER, top + 100, SWP_SHOWWINDOW | SWP_NOMOVE);

	RedrawWindow();
	RedrawChildren();
}

void CGenerationReportDlg::OnPrefChildChanged()
{
	CRect rc;
	CRect rc1;
	CRect prefRect;
	CRect btnRect;
	CRect lblRect;
	CRect lvwRect;
	int top;
	int width;
	int ncHeight;

	GetWindowRect(rc1);
	width = rc1.Width();

	GetClientRect(rc);

	ncHeight = rc1.Height() - rc.Height();

	lvwReport_.GetWindowRect(lvwRect);
	ScreenToClient(lvwRect);

	// set prefs children position
	//
	top = BORDER;
	for (int i = 0; i < preferences_.size(); i++) {
		preferences_[i]->GetWindowRect(prefRect);
		preferences_[i]->SetWindowPos(&CWnd::wndTop, BORDER, top, PREF_WIDTH, prefRect.Height(), SWP_SHOWWINDOW);
		top += (prefRect.Height() + BORDER);
	}
	
	// set label position
	//
	/*lblMsg_.SetWindowPos(&CWnd::wndTop, 
						 BORDER, 
						 top,
						 rc.Width() - 2 * BORDER,
						 20,
						 SWP_SHOWWINDOW);
	lblMsg_.GetWindowRect(lblRect);
	ScreenToClient(lblRect);

	cmdClose_.GetWindowRect(btnRect);
	cmdClose_.SetWindowPos( &CWnd::wndTop, 
							rc.Width() - BORDER - btnRect.Width(), 
							lblRect.bottom + BORDER,
							0, 
							0, 
							SWP_SHOWWINDOW | SWP_NOSIZE);
	cmdClose_.GetWindowRect(btnRect);
	ScreenToClient(btnRect);

	cmdGenerate_.SetWindowPos(&CWnd::wndTop, 
							  btnRect.left - BORDER - btnRect.Width(),
							  btnRect.top,
							  0,
							  0,
							  SWP_SHOWWINDOW | SWP_NOSIZE);
	
	top = btnRect.bottom + BORDER;
	
	SetWindowPos(&CWnd::wndTop, 0, 0, width, top + ncHeight, SWP_SHOWWINDOW | SWP_NOMOVE);

	//SetWindowPos(&CWnd::wndTop, 0, 0, lvwRect.Width() + 2 * BORDER, top + 100, SWP_SHOWWINDOW | SWP_NOMOVE);*/
	UpdateGenerationButton();
	RedrawWindow();
	RedrawChildren();
}

void CGenerationReportDlg::GenerateAll()
{
	CXmlProjectSettings_Cpp* cppSettings;
	CXmlProjectSettings_Atl* atlSettings;
	CXmlProjectSettings_CSharp* cSharpSettings;
	bool cppSuccess = true;
	bool atlSuccess = true;
	bool cSharpSuccess = true;

	// Cpp generation
	//
	cppSettings = project_->GetProjectSettings()->GetCppSettings();
	if (!cppSettings->GetEnabled()) {
		AppendItem(_T("Visual C++ 6.0 Dll : generation is disabled."), 0, 4);
	} else if (cppSettings->GetPostGenerationStep()->GetActionId() == enGeneratorAction_None) {
		AppendItem(_T("Visual C++ 6.0 Dll : nothing to do."), 0, 4);
	} else {
		CCppGenerationManager generationManager;

		AppendItem(_T("Visual C++ 6.0 Dll generation"), 0, 0);
		lvwReport_.RedrawWindow();

		generationManager.RegisterListener(this);
		cppSuccess = generationManager.Generate(currentDirectory_, project_);
		if (cppSuccess) {
			generationManager.RunCompiler(); 
			generationManager.RunTestProject();	
		} else {
			AppendItem(_T("Visual C++ 6.0 Dll : generation failed"), 0, 3);		
		}
	}

	// Atl project generation
	//
	atlSettings = project_->GetProjectSettings()->GetAtlSettings();
	if (!atlSettings->GetEnabled()) {
		AppendItem(_T("Atl Dll : generation is disabled"), 0, 4);
	} else if (atlSettings->GetPostGenerationStep()->GetActionId() == enGeneratorAction_None) {
		AppendItem(_T("Atl Dll : nothing to do"), 0, 4);
	} else {
		CAtlGenerationManager generationManager;

		AppendItem(_T("Atl Dll generation"), 0, 0);
		lvwReport_.RedrawWindow();

		generationManager.RegisterListener(this);
		atlSuccess = generationManager.Generate(currentDirectory_, project_);
		if (atlSuccess) {
			generationManager.RunCompiler();
			generationManager.RunTestProject();	
		} else {
			AppendItem(_T("Atl Dll : generation failed."), 0, 3);		
		}	
	}
	
	// C# project generation
	//
	cSharpSettings = project_->GetProjectSettings()->GetCSharpSettings();
	if (!cSharpSettings->GetEnabled()) {
		AppendItem(_T("C# Dll : generation is disabled"), 0, 4);
	} else if (cSharpSettings->GetPostGenerationStep()->GetActionId() == enGeneratorAction_None) {
		AppendItem(_T("C# Dll : nothing to do"), 0, 4);
	} else {
		CCSharpGenerationManager generationManager;

		AppendItem(_T("C# Dll generation"), 0, 0);
		lvwReport_.RedrawWindow();

		generationManager.RegisterListener(this);
		cSharpSuccess = generationManager.Generate(currentDirectory_, project_);
		if (cSharpSuccess) {
			generationManager.RunCompiler();
			generationManager.RunTestProject();	
		} else {
			AppendItem(_T("C# Dll : generation failed."), 0, 3);		
		}	
	}

	AppendItem(_T("Code generation complete."), 0, 2);
}


void CGenerationReportDlg::Init(CXmlProject* project, const cmString& currentDirectory)
{
	project_ = project;
	currentDirectory_ = currentDirectory;
}

void CGenerationReportDlg::OnNewTask(const cmString& label)
{
	AppendItem(label, 2, 1);
}

void CGenerationReportDlg::OnTaskUpdate(const cmString& label)
{
	UpdateItem(label, 2, 1);
}

void CGenerationReportDlg::OnTaskComplete(const cmString& label)
{
	UpdateItem(label, 2, 2);
}

void CGenerationReportDlg::OnTaskFailed(const cmString& label)
{
	AppendItem(label, 2, 3);
	lvwReport_.SetColumnWidth(0, 2000);
	//UpdateItem(label, 2, 3);
}

void CGenerationReportDlg::OnTaskDisabled(const cmString& label)
{
	UpdateItem(label, 2, 4);
}

void CGenerationReportDlg::AppendItem(const cmString& label, int indent, int image)
{
	USES_CONVERSION;

	LVITEM item;
	cmString tmp;

	tmp = label;
	// item descriptor
	//			
	item.mask = LVIF_TEXT | LVIF_INDENT | LVIF_IMAGE;
	item.iItem = lvwReport_.GetItemCount();
	item.iSubItem = 0;
	item.pszText = tmp.GetBuffer(0);
	item.iIndent = indent;
	item.iImage = image;

	// insert item
	//
	int index;

	index = lvwReport_.InsertItem(&item);

	// update list view
	//
	lvwReport_.RedrawItems(index, index);
	lvwReport_.UpdateWindow();
}

void CGenerationReportDlg::UpdateItem(const cmString& label, int indent, int image)
{
	LVITEM item;
	int index;
	CString tmp;

	tmp = label;

	// item descriptor
	//			
	index = lvwReport_.GetItemCount() - 1;
	item.mask = LVIF_TEXT | LVIF_INDENT | LVIF_IMAGE;
	item.iItem = index;
	item.iSubItem = 0;
	item.pszText = (TCHAR*)tmp.GetBuffer(0);
	item.iIndent = indent;
	item.iImage = image;

	// update item
	//
	lvwReport_.SetItem(&item);

	// update list view
	//
	lvwReport_.RedrawItems(index, index);
	lvwReport_.UpdateWindow();

}

HBRUSH CGenerationReportDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	
	if (bkBrush_.GetSafeHandle() == NULL)
		bkBrush_.CreateSolidBrush(SETTINGS_BK_COLOR_MID1_ENABLED);//DIALOG_BACK_COLOR);

	pDC->SetBkColor(SETTINGS_BK_COLOR_MID1_ENABLED);//DIALOG_BACK_COLOR);
	
	return bkBrush_;
}

void CGenerationReportDlg::UpdateGenerationButton()
{
	BOOL canGenerate;

	canGenerate = CanGenerate();

	cmdGenerate_.EnableWindow(canGenerate);
	if (canGenerate)
		lblMsg_.SetWindowText(_T("Press \"Generate\" to get your settings !!!"));
	else
		lblMsg_.SetWindowText(_T("To generate your settings you have to select \"Debug\" and/or \"Release\" build!"));
}

BOOL CGenerationReportDlg::CanGenerate()
{
	for (int i = 0; i < preferences_.size(); i++) {
		if (preferences_[i]->GetActionId() != enGeneratorAction_None)
			return true;
	}

	return false;
}

void CGenerationReportDlg::OnCmdGenerate() 
{
	lvwReport_.DeleteAllItems();

	// store cpp settings
	//
	CXmlProjectSettings_Cpp* cppSettings;

	cppSettings = project_->GetProjectSettings()->GetCppSettings();
	cppSettings->GetPostGenerationStep()->SetActionId(cppPref_->GetActionId());
	cppSettings->GetPostGenerationStep()->SetConfigId(cppPref_->GetConfigId());
	cppSettings->GetPostGenerationStep()->SetTestProjectActionId(cppPref_->GetTestProjectActionId());
	
	// store atl settings
	//
	CXmlProjectSettings_Atl* atlSettings;

	atlSettings = project_->GetProjectSettings()->GetAtlSettings();
	atlSettings->GetPostGenerationStep()->SetActionId(atlPref_->GetActionId());
	atlSettings->GetPostGenerationStep()->SetConfigId(atlPref_->GetConfigId());
	atlSettings->GetPostGenerationStep()->SetTestProjectActionId(atlPref_->GetTestProjectActionId());
	
	// store C# settings
	//
	/***
	CXmlProjectSettings_CSharp* cSharpSettings;

	cSharpSettings = project_->GetProjectSettings()->GetCSharpSettings();
	cSharpSettings->GetPostGenerationStep()->SetActionId(cSharpPref_->GetActionId());
	cSharpSettings->GetPostGenerationStep()->SetConfigId(cSharpPref_->GetConfigId());
	cSharpSettings->GetPostGenerationStep()->SetTestProjectActionId(cSharpPref_->GetTestProjectActionId());
	***/

	EnableControls(false);
	GenerateAll();
	EnableControls(true);
}

void CGenerationReportDlg::EnableControls(bool enable)
{


}


void CGenerationReportDlg::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	CMemDC memDC(&dc);
	CBrush b(DIALOG_BACK_COLOR);
	CBrush b2(SETTINGS_BK_COLOR_MID1_ENABLED);
	CRect rc;
	CRect tmp;

	GetClientRect(&rc);
	memDC.FillRect(rc, &b);

	RedrawChildren();	
}


BOOL CGenerationReportDlg::OnEraseBkgnd(CDC* pDC) 
{
	return TRUE;
}

void CGenerationReportDlg::OnClose() 
{
	CDialog::OnCancel();	
	//CDialog::OnClose();
}

void CGenerationReportDlg::Clear()
{
	for (int i = 0; i < preferences_.size(); i++)
		delete preferences_[i];

	preferences_.clear();
}

CGenerationPrefDlg* CGenerationReportDlg::AddCppPrefDialog(const cmString& title)
{
	CGenerationPrefDlg* newDlg;
	CXmlProjectSettings_Cpp* cppSettings;
	
	cppSettings = project_->GetProjectSettings()->GetCppSettings();
	newDlg = new CGenerationPrefDlg;

	// setup actions
	//
	newDlg->AddAction(enGeneratorAction_None);
	newDlg->AddAction(enGeneratorAction_GenerateOnly);
	newDlg->AddAction(enGeneratorAction_GenerateAndOpen);
	newDlg->AddAction(enGeneratorAction_GenerateAndCompile);
	newDlg->SetActionId(cppSettings->GetPostGenerationStep()->GetActionId());

	// setup configurations
	//
	newDlg->AddConfiguration(enGeneratorConfig_All);
	newDlg->AddConfiguration(enGeneratorConfig_Debug);
	newDlg->AddConfiguration(enGeneratorConfig_Release);
	newDlg->AddConfiguration(enGeneratorConfig_UnicodeDebug);
	newDlg->AddConfiguration(enGeneratorConfig_UnicodeRelease);
	
	newDlg->SetConfigId(cppSettings->GetPostGenerationStep()->GetConfigId());

	// setup test project actions
	//
	newDlg->AddTestPrjAction(enTestProjectAction_None);
	newDlg->AddTestPrjAction(enTestProjectAction_GenerateOnly);
	newDlg->AddTestPrjAction(enTestProjectAction_GenerateAndOpen);
	newDlg->SetTestProjectActionId(cppSettings->GetPostGenerationStep()->GetTestProjectActionId());

	newDlg->SetTitle(title);

	newDlg->Create(newDlg->IDD, this);
	preferences_.push_back(newDlg);
	
	return newDlg;
}

CGenerationPrefDlg* CGenerationReportDlg::AddAtlPrefDialog(const cmString& title)
{
	CGenerationPrefDlg* newDlg;
	CXmlProjectSettings_Atl* atlSettings;
	
	atlSettings = project_->GetProjectSettings()->GetAtlSettings();
	newDlg = new CGenerationPrefDlg;

	// setup actions
	//
	newDlg->AddAction(enGeneratorAction_None);
	newDlg->AddAction(enGeneratorAction_GenerateOnly);
	newDlg->AddAction(enGeneratorAction_GenerateAndOpen);
	newDlg->AddAction(enGeneratorAction_GenerateAndCompile);
	newDlg->SetActionId(atlSettings->GetPostGenerationStep()->GetActionId());

	// setup configurations
	//
	newDlg->AddConfiguration(enGeneratorConfig_All);
	newDlg->AddConfiguration(enGeneratorConfig_Debug);
	newDlg->AddConfiguration(enGeneratorConfig_ReleaseMinDependency);
	newDlg->AddConfiguration(enGeneratorConfig_ReleaseMinSize);
	newDlg->AddConfiguration(enGeneratorConfig_UnicodeDebug);
	newDlg->AddConfiguration(enGeneratorConfig_UnicodeReleaseMinDependency);
	newDlg->AddConfiguration(enGeneratorConfig_UnicodeReleaseMinSize);

	newDlg->SetConfigId(atlSettings->GetPostGenerationStep()->GetConfigId());

	// setup test project actions
	//
	newDlg->AddTestPrjAction(enTestProjectAction_None);
	newDlg->AddTestPrjAction(enTestProjectAction_GenerateOnly);
	newDlg->AddTestPrjAction(enTestProjectAction_GenerateAndOpen);
	newDlg->SetTestProjectActionId(atlSettings->GetPostGenerationStep()->GetTestProjectActionId());

	newDlg->SetTitle(title);

	newDlg->Create(newDlg->IDD, this);
	preferences_.push_back(newDlg);
	
	return newDlg;
}

CGenerationPrefDlg* CGenerationReportDlg::AddCSharpPrefDialog(const cmString& title)
{
	CGenerationPrefDlg* newDlg;
	CXmlProjectSettings_CSharp* csharpSettings;

	csharpSettings = project_->GetProjectSettings()->GetCSharpSettings();
	newDlg = new CGenerationPrefDlg;

	// setup actions
	//
	newDlg->AddAction(enGeneratorAction_None);
	newDlg->AddAction(enGeneratorAction_GenerateOnly);
	newDlg->AddAction(enGeneratorAction_GenerateAndOpen);
	newDlg->AddAction(enGeneratorAction_GenerateAndCompile);
	newDlg->SetActionId(csharpSettings->GetPostGenerationStep()->GetActionId());

	// setup configurations
	//
	newDlg->AddConfiguration(enGeneratorConfig_All);
	newDlg->AddConfiguration(enGeneratorConfig_Debug);
	newDlg->AddConfiguration(enGeneratorConfig_Release);
	newDlg->SetConfigId(csharpSettings->GetPostGenerationStep()->GetConfigId());

	// setup test project actions
	//
	newDlg->AddTestPrjAction(enTestProjectAction_None);
	newDlg->AddTestPrjAction(enTestProjectAction_GenerateOnly);
	newDlg->AddTestPrjAction(enTestProjectAction_GenerateAndOpen);
	newDlg->SetTestProjectActionId(csharpSettings->GetPostGenerationStep()->GetTestProjectActionId());

	newDlg->SetTitle(title);

	newDlg->Create(newDlg->IDD, this);
	preferences_.push_back(newDlg);
	
	return newDlg;
}

void CGenerationReportDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	UpdateWindowSize();	
}

void CGenerationReportDlg::RedrawChildren()
{
	cmdClose_.RedrawWindow();
	cmdGenerate_.RedrawWindow();
	lblMsg_.RedrawWindow();
	lvwReport_.RedrawWindow();
	for (int i = 0; i < preferences_.size(); i++)
		preferences_[i]->RedrawWindow();
}