#include "stdafx.h"
#include "SortClass.h"
/////////////////////////////////////////////////////////////////////////////
// CSortClass
CSortClass::CSortClass(CListCtrl * _pWnd, const int _iCol, const int _bIsNumeric )
{	
	iCol = _iCol;	
	pWnd = _pWnd;	
	bIsNumeric = _bIsNumeric;	
	ASSERT(pWnd);
	if(pWnd==NULL) return;
	if(pWnd->IsKindOf(RUNTIME_CLASS(CSortListCtrl)))
		((CSortListCtrl*)pWnd)->m_iFillSortData = 1;
	int max = pWnd->GetItemCount();	
	DWORD dw;	
	CString txt;	
	if (bIsNumeric==1)	
	{
		for (int t = 0; t < max; t++)		
		{			
			dw = pWnd->GetItemData(t);
			txt = pWnd->GetItemText(t, iCol);
			pWnd->SetItemData(t, (DWORD) new CSortItemReal(dw, txt));		 //-V572
		}	
	}	
	else if (bIsNumeric==2)	
	{
		for (int t = 0; t < max; t++)		
		{			
			dw = pWnd->GetItemData(t);
			txt = pWnd->GetItemText(t, iCol);
			pWnd->SetItemData(t, (DWORD) new CSortItemDate(dw, txt));		 //-V572
		}	
	}
	else if (bIsNumeric==3)	
	{
		for (int t = 0; t < max; t++)		
		{			
			dw = pWnd->GetItemData(t);
			txt = pWnd->GetItemText(t, iCol);
			pWnd->SetItemData(t, (DWORD) new CSortItemDateTime(dw, txt));		 //-V572
		}	
	}
	else if (bIsNumeric==4)	
	{
		for (int t = 0; t < max; t++)		
		{			
			dw = pWnd->GetItemData(t);
			txt = pWnd->GetItemText(t, iCol);
			pWnd->SetItemData(t, (DWORD) new CSortItemTime(dw, txt)); //-V572
		}	
	}
	else if (bIsNumeric==5)
	{
		for(int t=0; t<max; ++t)
		{
			dw = pWnd->GetItemData(t);
			txt = pWnd->GetItemText(t, iCol);
			pWnd->SetItemData(t, (DWORD) new CSortItemDateTimeSpan(dw, txt)); //-V572
		}
	}
	else
	{
		for (int t = 0; t < max; t++)	
		{			
			dw = pWnd->GetItemData(t);
			txt = pWnd->GetItemText(t, iCol);
			pWnd->SetItemData(t, (DWORD) new CSortItem(dw, txt)); //-V572
		}
	}
	if(pWnd->IsKindOf(RUNTIME_CLASS(CSortListCtrl)))
		((CSortListCtrl*)pWnd)->m_iFillSortData = 2;
}
CSortClass::~CSortClass()
{	
	ASSERT(pWnd);
	if(pWnd==NULL) return;
	if(pWnd->IsKindOf(RUNTIME_CLASS(CSortListCtrl)))
		((CSortListCtrl*)pWnd)->m_iFillSortData = 1;
	int max = pWnd->GetItemCount();
	if (bIsNumeric==1)	
	{		
		CSortItemReal * pItem;		
		for (int t = 0; t < max; t++)	
		{
			pItem = (CSortItemReal *) pWnd->GetItemData(t);			ASSERT(pItem);
			pWnd->SetItemData(t, pItem->dw);	
			delete pItem;	
		}
	}	
	else if (bIsNumeric==2)	
	{		
		CSortItemDate * pItem;		
		for (int t = 0; t < max; t++)	
		{
			pItem = (CSortItemDate *) pWnd->GetItemData(t);	
			ASSERT(pItem);
			pWnd->SetItemData(t, pItem->dw);	
			delete pItem;	
		}
	}	
	else if (bIsNumeric==3)	
	{		
		CSortItemDateTime * pItem;		
		for (int t = 0; t < max; t++)	
		{
			pItem = (CSortItemDateTime *) pWnd->GetItemData(t);	
			ASSERT(pItem);
			pWnd->SetItemData(t, pItem->dw);	
			delete pItem;	
		}
	}	
	else if (bIsNumeric==4)	
	{		
		CSortItemTime * pItem;		
		for (int t = 0; t < max; t++)	
		{
			pItem = (CSortItemTime *) pWnd->GetItemData(t);	
			ASSERT(pItem);
			pWnd->SetItemData(t, pItem->dw);	
			delete pItem;	
		}
	}	
	else if (bIsNumeric==5)
	{
		CSortItemDateTimeSpan *pItem;
		for(int t=0; t<max; ++t)
		{
			pItem = (CSortItemDateTimeSpan*)pWnd->GetItemData(t);	
			ASSERT(pItem);
			pWnd->SetItemData(t, pItem->dw);	
			delete pItem;	
		}
	}
	else
	{
		CSortItem * pItem;
		for (int t = 0; t < max; t++)
		{
			pItem = (CSortItem *) pWnd->GetItemData(t);
			ASSERT(pItem);
			pWnd->SetItemData(t, pItem->dw);
			delete pItem;
		}
	}
	if(pWnd->IsKindOf(RUNTIME_CLASS(CSortListCtrl)))
		((CSortListCtrl*)pWnd)->m_iFillSortData = 0;
}

void CSortClass::Sort(const bool bAsc)
{	
	if (bIsNumeric==1)	
	{		
		if (bAsc)
			pWnd->SortItems(CompareAscR, 0L);
		else	
			pWnd->SortItems(CompareDesR, 0L);
	}
	else if (bIsNumeric==2)	
	{		
		if (bAsc)
			pWnd->SortItems(CompareAscD, 0L);
		else	
			pWnd->SortItems(CompareDesD, 0L);
	}
	else if (bIsNumeric==3)	
	{		
		if (bAsc)
			pWnd->SortItems(CompareAscDT, 0L);
		else	
			pWnd->SortItems(CompareDesDT, 0L);
	}
	else if (bIsNumeric==4)	
	{		
		if (bAsc)
			pWnd->SortItems(CompareAscT, 0L);
		else	
			pWnd->SortItems(CompareDesT, 0L);
	}
	else if (bIsNumeric==5)
	{
		if (bAsc)
			pWnd->SortItems(CompareAscDTS, 0L);
		else
			pWnd->SortItems(CompareDesDTS, 0L);
	}
	else
	{	
		if (bAsc)	
			pWnd->SortItems(CompareAsc, 0L);	
		else
			pWnd->SortItems(CompareDes, 0L);
	}
}

int CALLBACK CSortClass::CompareAsc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{	
	CSortItem * i1 = (CSortItem *) lParam1;
	CSortItem * i2 = (CSortItem *) lParam2;	
	ASSERT(i1 && i2);
	return i1->txt.CompareNoCase(i2->txt);
}

int CALLBACK CSortClass::CompareDes(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{	
	CSortItem * i1 = (CSortItem *) lParam1;
	CSortItem * i2 = (CSortItem *) lParam2;	
	ASSERT(i1 && i2);
	return i2->txt.CompareNoCase(i1->txt);
}

int CALLBACK CSortClass::CompareAscR(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	CSortItemReal * i1 = (CSortItemReal *) lParam1;
	CSortItemReal * i2 = (CSortItemReal *) lParam2;
	ASSERT(i1 && i2);
	if (i1->dVal == i2->dVal) 
		return 0;	
	return i1->dVal > i2->dVal ? 1 : -1;
}

int CALLBACK CSortClass::CompareDesR(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{	
	CSortItemReal * i1 = (CSortItemReal *) lParam1;
	CSortItemReal * i2 = (CSortItemReal *) lParam2;
	ASSERT(i1 && i2);
	if (i1->dVal == i2->dVal)
		return 0;	
	return i1->dVal < i2->dVal ? 1 : -1;
}

int CALLBACK CSortClass::CompareAscD(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	CSortItemDate * i1 = (CSortItemDate *) lParam1;
	CSortItemDate * i2 = (CSortItemDate *) lParam2;
	ASSERT(i1 && i2);
	if (i1->dt == i2->dt) 
		return 0;	
	return i1->dt > i2->dt ? 1 : -1;
}

int CALLBACK CSortClass::CompareDesD(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{	
	CSortItemDate * i1 = (CSortItemDate *) lParam1;
	CSortItemDate * i2 = (CSortItemDate *) lParam2;
	ASSERT(i1 && i2);
	if (i1->dt == i2->dt)
		return 0;	
	return i1->dt < i2->dt ? 1 : -1;
}

int CALLBACK CSortClass::CompareAscDT(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{	
	CSortItemDateTime * i1 = (CSortItemDateTime *) lParam1;
	CSortItemDateTime * i2 = (CSortItemDateTime *) lParam2;
	ASSERT(i1 && i2);
	if (i1->dt == i2->dt) 
	return 0;	
	return i1->dt > i2->dt ? 1 : -1;
}

int CALLBACK CSortClass::CompareDesDT(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{	
	CSortItemDateTime * i1 = (CSortItemDateTime *) lParam1;
	CSortItemDateTime * i2 = (CSortItemDateTime *) lParam2;
	ASSERT(i1 && i2);
	if (i1->dt == i2->dt)
		return 0;	
	return i1->dt < i2->dt ? 1 : -1;
}

int CALLBACK CSortClass::CompareAscT(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	CSortItemTime * i1 = (CSortItemTime *) lParam1;
	CSortItemTime * i2 = (CSortItemTime *) lParam2;
	ASSERT(i1 && i2);
	if (i1->iH == i2->iH) 
	{
		return i1->iM - i2->iM;
	}
	return i1->iH - i2->iH;
}

int CALLBACK CSortClass::CompareDesT(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	CSortItemTime * i1 = (CSortItemTime *) lParam1;
	CSortItemTime * i2 = (CSortItemTime *) lParam2;
	ASSERT(i1 && i2);
	if (i1->iH == i2->iH) 
	{
		return i2->iM - i1->iM;
	}
	return i2->iH - i1->iH;
}

int CALLBACK CSortClass::CompareAscDTS(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{	
	CSortItemDateTimeSpan *i1 = (CSortItemDateTimeSpan*)lParam1;
	CSortItemDateTimeSpan *i2 = (CSortItemDateTimeSpan*)lParam2;
	ASSERT(i1 && i2);
	if (i1->dt == i2->dt) 
		return 0;	
	return i1->dt > i2->dt ? 1 : -1;
}

int CALLBACK CSortClass::CompareDesDTS(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{	
	CSortItemDateTimeSpan *i1 = (CSortItemDateTimeSpan*)lParam1;
	CSortItemDateTimeSpan *i2 = (CSortItemDateTimeSpan*)lParam2;
	ASSERT(i1 && i2);
	if (i1->dt == i2->dt)
		return 0;	
	return i1->dt < i2->dt ? 1 : -1;
}

CSortClass::CSortItem::CSortItem(const DWORD _dw, const CString & _txt)
{
	dw = _dw;
	txt = _txt;
}

CSortClass::CSortItem::~CSortItem()
{
}

CSortClass::CSortItemReal::CSortItemReal(const DWORD _dw, const CString & _txt)
{
	CString buf;
	for(int i=0;i<_txt.GetLength();i++)	{ if(_txt[i]!=_T(' ')) buf+=_txt[i]; }
	dVal = __atof(buf);	
	dw = _dw;
}
CSortClass::CSortItemDate::CSortItemDate(const DWORD _dw, const CString & _txt)
{
	dt.ParseDateTime(_txt);
	if(dt.GetStatus( )==COleDateTime::invalid) 
		dt.SetDateTime(9000,1,1,0,0,0);
	//CString buf=dt.Format("%d.%m.%Y  %H:%M:%S");
	dw = _dw;
}
CSortClass::CSortItemDateTime::CSortItemDateTime(const DWORD _dw, const CString & _txt)
{
	int year(0), month(0), day(0), hour(0), min = 0, sec(0);
	if(_txt.GetLength()==19){
		year	=_atoi(_txt.Mid(6,4));
		month	=_atoi(_txt.Mid(3,2));
		day		=_atoi(_txt.Mid(0,2));
		hour	=_atoi(_txt.Mid(11,2));
		min		=_atoi(_txt.Mid(14,2));
		sec		=_atoi(_txt.Mid(17,2));
	}
	else if(_txt.GetLength()==16)
	{
		year	=_atoi(_txt.Mid(6,4));
		month	=_atoi(_txt.Mid(3,2));
		day		=_atoi(_txt.Mid(0,2));
		hour	=_atoi(_txt.Mid(11,2));
		min		=_atoi(_txt.Mid(14,2));
	}
	else if(_txt.GetLength()==10)//Вариант - только дата
	{
		year	=_atoi(_txt.Mid(6,4));
		month	=_atoi(_txt.Mid(3,2));
		day		=_atoi(_txt.Mid(0,2));
	}
	if(month!=0)dt=COleDateTime(year, month, day, hour, min, sec);
	else  dt.ParseDateTime(_txt);

	if(dt.GetStatus( )!=COleDateTime::valid) 
		dt.SetDateTime(9000,1,1,0,0,0);
	//CString buf=dt.Format("%d.%m.%Y  %H:%M:%S");
	dw = _dw;
}

CSortClass::CSortItemTime::CSortItemTime(const DWORD _dw, const CString & _txt)
{
	CString m, h, str;
	int i;
	iM = 0, iH = 0;
	str = _txt;
	dw = _dw;

	int ind = str.Find(_T(":"));
	ind = ind>-1?ind:str.Find(_T("/"));
	ind = ind>-1?ind:str.Find(_T("\\"));
	ind = ind>-1?ind:str.Find(_T("="));
	ind = ind>-1?ind:str.Find(_T("*"));
	ind = ind>-1?ind:str.Find(_T("`"));
	CString t;

	bool bOk = true;

	if(ind>0)
	{
		t = str.Left(ind);
		for(i=0; i<t.GetLength(); i++)
		{
			if(!iswdigit(t[i]))
			{
				bOk = false;
				break;
			}
		}
		if(bOk)
		{
			iH = _atoi(t);
			str.TrimLeft(t);
			str.TrimLeft(_T(":"));
			str.TrimLeft(_T("/"));
			str.TrimLeft(_T("\\"));
			str.TrimLeft(_T("="));
			str.TrimLeft(_T("*"));
			str.TrimLeft(_T("`"));
			if(str.GetLength()!=2)
			{
				bOk = false;
			}
			else
			{
				for(i=0; i<2; i++)
				{
					if(!iswdigit(str[i]))
					{
						bOk = false;
						break;
					}
				}
				if(bOk)
					iM = _atoi(str);
			}
		}
	}
	else 
	{
		for(i=0; i<str.GetLength(); i++)
		{
			if(!iswdigit(str[i]))
			{
				bOk = false;
				break;
			}
		}
		if(bOk)
			iH = _atoi(str);
	}

	if(!bOk)
	{
		iH = 0;
		iM = 0;
	}
}

CSortClass::CSortItemDateTimeSpan::CSortItemDateTimeSpan(const DWORD _dw, const CString &_txt)
{
	int iDays, iHours, iMinutes;

	CString sDaySplitter(aplDaySpanSplitter);
	int indDay = _txt.Find(sDaySplitter);
	iDays = indDay>=0? _atoi(_txt.Mid(0, indDay)) : 0;
	int indHour = indDay>=0? indDay+sDaySplitter.GetLength() : 0;
	int indMin = _txt.Find(_T(":"), indHour);
	if (indMin>=0)
	{
		iHours = _atoi(_txt.Mid(indHour, indMin-indHour));
		iMinutes = indMin<_txt.GetLength()? _atoi(_txt.Mid(indMin+1)) : 0;
	}
	else
	{
		iHours = _atoi(_txt.Mid(indHour));
		iMinutes = 0;
	}

	dt = COleDateTimeSpan(iDays, iHours, iMinutes, 0);
	dw = _dw;
}