// CategoryDiffDlg.cpp : implementation file
//

#include "stdafx.h"
#include "CategoryDiffDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CCategoryDiffDlg dialog


CCategoryDiffDlg::CCategoryDiffDlg(CWnd* pParent /*=NULL*/)
	: CResizableDialog(CCategoryDiffDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CCategoryDiffDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_api=NULL;
	m_inst=NULL;
	m_ListCategoryDiff.SetUniqueName(_T("apl_psm_addin_list_category_diff"));


	cColNames[ColProductId]		= (TCHAR*)APL_T("Обозначение");
	cColNames[ColProductName]	= (TCHAR*)APL_T("Наименование");
	cColNames[ColInsAuthor]		= (TCHAR*)APL_T("Добавил");
	cColNames[ColInsDate]		= (TCHAR*)APL_T("Дата добавления");
	cColNames[ColInsVersionNo]	= (TCHAR*)APL_T("Версия");
	cColNames[ColDelAuthor]		= (TCHAR*)APL_T("Удалил");
	cColNames[ColDelDate]		= (TCHAR*)APL_T("Дата удаления");
	cColNames[ColDelVersionNo]	= (TCHAR*)APL_T("Версия");

	iColSizes[0]=100;
	iColSizes[1]=100;
	iColSizes[2]=80;
	iColSizes[3]=120;
	iColSizes[4]=50;
	iColSizes[5]=50;
	iColSizes[6]=100;
	iColSizes[7]=50;
}


void CCategoryDiffDlg::DoDataExchange(CDataExchange* pDX)
{
	CResizableDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CCategoryDiffDlg)
	DDX_Control(pDX, IDC_LIST_FRAME, m_ListFrame);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CCategoryDiffDlg, CResizableDialog)
	//{{AFX_MSG_MAP(CCategoryDiffDlg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCategoryDiffDlg message handlers

BOOL CCategoryDiffDlg::OnInitDialog()
{
	CResizableDialog::OnInitDialog();
	ModifyStyleEx(0, WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT);   
	ModifyStyle(0, WS_MAXIMIZEBOX);   
	
	// TODO: Add extra initialization here
	SetControlsPositions();
	SetControlsAnchors();

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

BOOL CCategoryDiffDlg::SetControlsPositions()
{
	RECT rect={5,5,10,10};
	
	m_ListCategoryDiff.Create
							(
								WS_VISIBLE|WS_CHILD|WS_BORDER|LVS_SORTASCENDING,
								rect,
								this,
								IDC_LIST_CAT_CTRL
							);

	m_ListFrame.GetWindowRect(&rect);
	ScreenToClient(&rect);
	m_ListCategoryDiff.MoveWindow(&rect);

	return TRUE;

}

BOOL CCategoryDiffDlg::SetControlsAnchors()
{
	AddAnchor(IDOK, BOTTOM_RIGHT);
	AddAnchor(IDC_LIST_CAT_CTRL, TOP_LEFT,BOTTOM_RIGHT);

	return TRUE;
}

BOOL CCategoryDiffDlg::AddListColumns()
{
	int iColNo=0;

	for(iColNo=ColFirstColumn;iColNo<=ColLastColumn;iColNo++)
	{
		m_ListCategoryDiff.InsertColumn
										(
											iColNo,
											cColNames[iColNo],
											LVCFMT_LEFT,
											iColSizes[iColNo]
										);
	}

	return TRUE;
}

BOOL CCategoryDiffDlg::FillTable()
{

	if(!m_api->m_data.IsKindOf(m_inst,m_api->m_categ_mgr.e_categ))
		return FALSE;

	//	несортированный список версий продуктов
	aplExtent		aeUnsortedVersions;
	//	отсортированный по порядку создания список версий продуктов
	aplExtent		aeSortedVersions;

	//	список продуктов в текущей версии
	aplExtent		aeCurrVersionProducts;
	//	список продуктов в предыдущей версии
	aplExtent		aePrevVersionProducts;

	int i=0,j=0,k=0,iRowNo=0;

	
	//	получаем несортированный список версий продуктов одной категории
	m_api->m_categ_mgr.GetAllCategoryVersion(m_inst,aeUnsortedVersions);
	//	сортируем версии по порядку создания. первый параметр - вход, второй - выход
	SortVersions(aeUnsortedVersions,aeSortedVersions);
	//	загружаем информацию по категории
	m_api->m_categ_mgr.LoadCategoryInfo(aeSortedVersions,TRUE);

	//	цикл по отсортированным версиям продуктов
	for(i=0;i<aeSortedVersions.GetSize();i++)
	{
		//	получаем список продуктов для данной версии
		m_api->m_data.GetAttr
							(
								aeSortedVersions[i],
								m_api->m_categ_mgr.a_categ_ver_products,
								aeCurrVersionProducts
							);
		//	цикл по продуктам в текущей версии
		for(j=0;j<aeCurrVersionProducts.GetSize();j++)
		{
			//	если первый раз проходим по списку продуктов (первая версия)
			if(0==i)
			{
				AddProductId(	aeCurrVersionProducts[j],	iRowNo);
				AddProductName(	aeCurrVersionProducts[j],	iRowNo);
				AddInsVersionNo(aeSortedVersions[i],		iRowNo);
				AddInsAuthor(	aeSortedVersions[i],		iRowNo);
				AddInsDate(		aeSortedVersions[i],		iRowNo);
				//	зачем-то надо
				m_ListCategoryDiff.SetItemData(iRowNo,(DWORD)aeCurrVersionProducts[j]);
				//	добавляем текущий продукт в список продуктов предыдущей версии
				aePrevVersionProducts.Add(aeCurrVersionProducts[j]);
			}
			//	если не первый раз проходим по списку продуктов (не первая версия)
			else
			{
				//	проверяем, был ли текущий продукт в предыдущей версии
				//	если не был - его добавили
				if(-1==aePrevVersionProducts.Find(aeCurrVersionProducts[j]))
				{
					AddProductId(	aeCurrVersionProducts[j],	iRowNo);
					AddProductName(	aeCurrVersionProducts[j],	iRowNo);
					AddInsVersionNo(aeSortedVersions[i],		iRowNo);
					AddInsAuthor(	aeSortedVersions[i],		iRowNo);
					AddInsDate(		aeSortedVersions[i],		iRowNo);
					//	зачем-то надо
					m_ListCategoryDiff.SetItemData(iRowNo,(DWORD)aeCurrVersionProducts[j]);
				}
			}
		}
		//	цикл по всем продуктам в предыдущей версии
		for(k=0;k<aePrevVersionProducts.GetSize();k++)
		{
			//	проверяем есть ли продукт из предыдущей версии в текущей версии
			//	если нет - продукт удалили в текущей версии
			if(-1==aeCurrVersionProducts.Find(aePrevVersionProducts[k]))
			{
				int itItemIndex=0,ii=0;

				for(ii=0;ii<m_ListCategoryDiff.GetItemCount();ii++)
				{
					if(aePrevVersionProducts[k]==(CaplInstance*)m_ListCategoryDiff.GetItemData(ii))
						itItemIndex=ii;
				}
				AddDelAuthor(	aeSortedVersions[i],	itItemIndex);
				AddDelVersionNo(aeSortedVersions[i],	itItemIndex);
				AddDelDate(		aeSortedVersions[i],	itItemIndex);
			}
		}

		if(0!=i)
		{
			int t=0;
			aePrevVersionProducts.Clear();
			for(t=0;t<aeCurrVersionProducts.GetSize();t++)
				aePrevVersionProducts.Add(aeCurrVersionProducts[t]);
		}
	}
/*
    цикл i по версиям
		для каждой версии получаем список продуктов
		цикл j по продуктам в списке
			для первого прохода по списку продуктов (для первой версии):
				получаем обозначение и наименование
				получаем автора добавления и дату добавления
				добавляем в список продуктов предыдущей версии
			для последующих проходов по списку продуктов:
				проверяем, был ли продукт в предыдущей версии
					если не был - его добавили.
						получаем обозначение и наименование
						получаем автора добавления и дату добавления
					если был - ничего не выводим (продукт без изменений)
				для всех продуктов в предыдущей версии проверяем есть ли он в текущей
					если есть - ничего не выводим
					если нет - его удалили из текущей.
						получаем автора удаления и дату удаления
				перезаписываем список продуктов предыдущей версии списком продуктов текущей версии
*/
	return TRUE;
}

BOOL CCategoryDiffDlg::SortVersions(aplExtent &aplUnsorted, aplExtent &aplSorted)
{
	//	указатель на текущую версию продукта (для сортировки)
	CaplInstance*	ciCurrVersion=NULL;
	//	указатель на предыдущю версию продукта (для сортировки)
	CaplInstance*	ciPrevVersion=NULL;

	int i=0;
	//	сортируем версии по дате создания и добавляем их в aeSortedVersions
	while(TRUE)
	{
		//	сработало ли условие в цикле
		BOOL	bIsConditionWorked=FALSE;
		//	цикл по всем версиям продуктов
		for(i=0;i<aplUnsorted.GetSize();i++)
		{
			//	для каждой версии получаем указатель на предыдущую версию 
			m_api->m_data.GetAttr
								(
									aplUnsorted[i],
									m_api->m_categ_mgr.a_categ_ver_prev,
									ciPrevVersion
								);
			//	если указатель на текущую версию равен указателю на предыдущую версию - 
			//	присваиваем указателю на текущую версию текущую версию,
			//	добавляем текущую в список отсортированных версий,
			//	поднимаем флаг срабатывания условия в цикле
			//	и выходим из цикла "for".
			//	для самой первой версии указатель на предыдущую версию равен NULL!
			if(ciCurrVersion==ciPrevVersion)
			{
				ciCurrVersion=aplUnsorted[i];
				aplSorted.Add(ciCurrVersion);
				bIsConditionWorked=TRUE;
				break;
			}
		}
		//	если условие сработало - продолжаем сортировку
		if(TRUE==bIsConditionWorked)
		{
			i=0;
			continue;
		}
		//	если нет - значит в неотсортированном массиве закончились элементы.
		//	завершаем сортировку.
		else
			break;
	}
/*
	TRACE("***********************************************\n");
	TRACE("unsorted elements %d\n",aplUnsorted.GetSize());
	TRACE("sorted elements %d\n",aplSorted.GetSize());
	TRACE("***********************************************\n");
*/
	return TRUE;
}


BOOL CCategoryDiffDlg::AddProductId(CaplInstance* caplIns, int& iRow)
{
	CString			csOutTextField;
	//	получаем обозначение продукта
	m_api->m_data.GetAttr
						(
							caplIns,
							m_api->m_prd_mgr.a_prd_id,
							csOutTextField
						);
	//	добавляем в список
	iRow=m_ListCategoryDiff.InsertItem(iRow,csOutTextField);

	return TRUE;
}

BOOL CCategoryDiffDlg::AddProductName(CaplInstance* caplIns, int& iRow)
{
	CString			csOutTextField;
	//	получаем наименование продукта
	m_api->m_data.GetAttr
						(
							caplIns,
							m_api->m_prd_mgr.a_prd_name,
							csOutTextField
						);
	//	добавляем в список
	m_ListCategoryDiff.SetItemText(iRow,ColProductName,csOutTextField);


	return TRUE;
}

BOOL CCategoryDiffDlg::AddInsVersionNo(CaplInstance* caplIns, int& iRow)
{
	CString			csOutTextField;
	//	получаем номер версии
	m_api->m_data.GetAttr
						(
							caplIns,
							m_api->m_categ_mgr.a_categ_ver_num,
							csOutTextField
						);
	//	добавляем в список (версия создания продукта)
	m_ListCategoryDiff.SetItemText(iRow,ColInsVersionNo,csOutTextField);

	return TRUE;
}

BOOL CCategoryDiffDlg::AddInsAuthor(CaplInstance* caplIns, int& iRow)
{
	CaplInstance*	ciChangeAuthor=NULL;
	CString			csOutTextField;
	//	получаем автора изменения (добавления)
	m_api->m_data.GetAttr
						(
							caplIns,
							m_api->m_categ_mgr.a_categ_ver_author,
							ciChangeAuthor
						);
	m_api->m_appr_mgr.GetPersonName(ciChangeAuthor,csOutTextField);
	//	добавляем в список
	m_ListCategoryDiff.SetItemText(iRow,ColInsAuthor,csOutTextField);

	return TRUE;
}

BOOL CCategoryDiffDlg::AddInsDate(CaplInstance* caplIns, int& iRow)
{
	CString			csOutTextField;
	COleDateTime	codtDate;
	//	получаем время изменения (добавления)
	m_api->m_data.GetAttr
						(
							caplIns,
							m_api->m_categ_mgr.a_categ_ver_end,
							csOutTextField
						);
	//	переводим текст в дату
	aplString2Date(csOutTextField,codtDate);
	//	форматируем дату в читаемый текст
	csOutTextField=codtDate.Format(_T("%d:%m:%Y %H:%M:%S"));
	//	добавляем в список
	m_ListCategoryDiff.SetItemText(iRow,ColInsDate,csOutTextField);


	return TRUE;
}

BOOL CCategoryDiffDlg::AddDelAuthor(CaplInstance* caplIns, int& iRow)
{
	CaplInstance*	ciChangeAuthor=NULL;
	CString			csOutTextField;
	//	получаем автора изменения (удаления)
	m_api->m_data.GetAttr
						(
							caplIns,
							m_api->m_categ_mgr.a_categ_ver_author,
							ciChangeAuthor
						);
	m_api->m_appr_mgr.GetPersonName(ciChangeAuthor,csOutTextField);
	//	добавляем в список
	m_ListCategoryDiff.SetItemText(iRow,ColDelAuthor,csOutTextField);

	return TRUE;
}

BOOL CCategoryDiffDlg::AddDelDate(CaplInstance* caplIns, int& iRow)
{
	CString			csOutTextField;
	COleDateTime	codtDate;
	//	получаем время изменения (удаления)
	m_api->m_data.GetAttr
						(
							caplIns,
							m_api->m_categ_mgr.a_categ_ver_end,
							csOutTextField
						);
	//	переводим текст в дату
	aplString2Date(csOutTextField,codtDate);
	//	форматируем дату в читаемый текст
	csOutTextField=codtDate.Format(_T("%d:%m:%Y %H:%M:%S"));
	//	добавляем в список
	m_ListCategoryDiff.SetItemText(iRow,ColDelDate,csOutTextField);

	return TRUE;
}

BOOL CCategoryDiffDlg::AddDelVersionNo(CaplInstance* caplIns, int& iRow)
{
	CString			csOutTextField;
	//	получаем номер версии
	m_api->m_data.GetAttr
						(
							caplIns,
							m_api->m_categ_mgr.a_categ_ver_num,
							csOutTextField
						);

	//	добавляем в список (версия удаления продукта)
	m_ListCategoryDiff.SetItemText(iRow,ColDelVersionNo,csOutTextField);

	return TRUE;
}
