// PacketDlg.cpp : implementation file
//

#include "stdafx.h"
#include "PacketDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CPacketDlg dialog
int CALLBACK CPacketDlg::CDataSetTreeItem::CompareHtreeItem(LPARAM lParam1, LPARAM lParam2,LPARAM lParamSort)
{
	if(lParam1==0) return 0;
	if(lParam2==0) return 0;
	CTreeCtrl *tree=((CDataSetTreeItem*)lParam1)->m_tree;
	if(tree==0) return 0;
	HTREEITEM item1=((CDataSetTreeItem*)lParam1)->m_item;
	HTREEITEM item2=((CDataSetTreeItem*)lParam2)->m_item;
	int img1,img2,img0;
	tree->GetItemImage(item1,img1,img0);
	tree->GetItemImage(item2,img2,img0);
	
	if(img1<img2) return -1;
	if(img2<img1) return 1;

	CString str1, str2;
	str1 = tree->GetItemText(item1);
	str2 = tree->GetItemText(item2);

	str1.MakeLower();
	str2.MakeLower();
	
	return str1.Compare(str2);
}
void CPacketDlg::CDataSetTreeItem::Sort(CTreeCtrl* tree)
{
	TVSORTCB sortcb;
	sortcb.hParent=TVI_ROOT;
	sortcb.lpfnCompare=CompareHtreeItem;
	sortcb.lParam=1;
	tree->SortChildrenCB(&sortcb);
}

CPacketDlg::CDataSetTreeItem::CDataSetTreeItem(CaplAPI *api, CTreeCtrl *pTree, CaplTAggr<CDataSetTreeItem*, CDataSetTreeItem*, APLAGGR_LIST_OR_AUTOKILLREF> *pItemsArray, CDataSet* pDataSet):CaplTreeItemData()
{
	ASSERT(api);
	ASSERT(api->m_packet_mgr);
	ASSERT(pItemsArray);
	ASSERT(pDataSet);
	ASSERT(pTree);

	m_tree = pTree;

	m_api = api;
	m_packet_mgr = (CaplPacketMgr*)api->m_packet_mgr;
	m_fictive_item = NULL;
	m_pDataSet = pDataSet;
	m_inst = NULL;

	m_bIsFolder = m_pDataSet->IsFolder();

	m_pItemsArray = pItemsArray;
	m_pItemsArray->Add(this);
}

CPacketDlg::CDataSetTreeItem::CDataSetTreeItem(CaplAPI *api, CTreeCtrl *pTree, CaplTAggr<CDataSetTreeItem*, CDataSetTreeItem*, APLAGGR_LIST_OR_AUTOKILLREF> *pItemsArray, CaplInstance* inst):CaplTreeItemData()
{
	ASSERT(api);
	ASSERT(api->m_packet_mgr);
	ASSERT(pItemsArray);
	ASSERT(inst);
	ASSERT(pTree);
	
	m_tree = pTree;

	m_api = api;
	m_packet_mgr = (CaplPacketMgr*)api->m_packet_mgr;
	m_fictive_item = NULL;
	m_pDataSet = NULL;
	m_inst = inst;

	m_bIsFolder = m_api->m_data.IsKindOf(m_inst, m_packet_mgr->e_folder_data_set);
	
	m_pItemsArray = pItemsArray;
	m_pItemsArray->Add(this);
}

CPacketDlg::CDataSetTreeItem::~CDataSetTreeItem()
{
	CollapseItems();
    if(!::IsWindow(m_tree->m_hWnd)) return;
	m_tree->DeleteItem(m_item);
}

bool CPacketDlg::CDataSetTreeItem::CreateItem(HTREEITEM htParent)
{
	CString name;
	int ico = 0;
	GetName(name, ico);
	
	m_item = m_tree->InsertItem(name, ico, ico, htParent);
	m_tree->SetItemData(m_item, (DWORD)this);
	if(m_inst)
	{
		if(m_api->m_data.IsKindOf(m_inst, m_packet_mgr->e_folder_data_set))
			m_fictive_item=m_tree->InsertItem(_T("fictive"),0,0,m_item);
	}
	else if(m_pDataSet)
	{
		if(m_pDataSet->IsFolder())
			m_fictive_item=m_tree->InsertItem(_T("fictive"),0,0,m_item);
	}
	
	return true;
}

bool CPacketDlg::CDataSetTreeItem::Expand(UINT action)
{
	if(action==TVE_EXPAND)
	{
		if(m_fictive_item)
			m_tree->DeleteItem(m_fictive_item);
		m_fictive_item = NULL;

		m_bExpanded = true;

		if(!m_bIsFolder) return true;

		m_tree->SetItemImage(m_item, ICON_FOLDER+1, ICON_FOLDER+1);

		if(m_inst)
		{
			int i;
			aplExtent ext;
			m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_folder_data_set_content, ext);
			for(i=0; i<ext.GetSize(); i++)
			{
				if(ext[i]==NULL) continue;
				if(ext[i]->GetAccessmode()>aplRO) continue;

				CDataSetTreeItem* pItem = new CDataSetTreeItem(m_api, m_tree, m_pItemsArray, ext[i]);
				pItem->CreateItem(m_item);
			}
		}
		else if(m_pDataSet)
		{
			int i;
			CFolderDataSet *pFDS = (CFolderDataSet*)m_pDataSet;
			for(i=0; i<pFDS->m_Content.GetSize(); i++)
			{
				if(pFDS->m_Content[i]==NULL) continue;
				
				CDataSetTreeItem* pItem = new CDataSetTreeItem(m_api, m_tree, m_pItemsArray, pFDS->m_Content[i]);
				pItem->CreateItem(m_item);
			}
		}
	}
	else
	{
		CollapseItems();
		m_tree->SetItemImage(m_item, ICON_FOLDER, ICON_FOLDER);
	}

	return true;
}

bool CPacketDlg::CDataSetTreeItem::GetName(CString &name, int &ico)
{
	if(m_inst)
	{
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_data_set_name, name);
	}
	else if(m_pDataSet)
	{
		name = m_pDataSet->m_sName;
	}
	else return false;
	
	if(m_bIsFolder)
		ico = ICON_FOLDER;
	else
		ico = ICON_DOCUMENT;

	return true;
}

bool CPacketDlg::CDataSetTreeItem::RefreshItem()
{
	CString buf;
	int ico;
	
	GetName(buf, ico);
	
	m_tree->SetItemText(m_item, buf);
	m_tree->SetItemImage(m_item, ico, ico);

	return true;
}

BOOL CPacketDlg::CDataSetTreeItem::ShowContextMenu(CPoint pt, CWnd *pWnd)
{
	return FALSE;
}

bool CPacketDlg::CDataSetTreeItem::CollapseItems()
{
	HTREEITEM item = 0;
	if(!::IsWindow(m_tree->m_hWnd)) return false;
	while(1)
	{
		item=m_tree->GetChildItem(m_item);
		if(item==0) break;
        CDataSetTreeItem *treeitem=(CDataSetTreeItem*)m_tree->GetItemData(item);
		if(treeitem==this) continue;
        if(treeitem!=0) 
		{
			m_pItemsArray->Remove(m_pItemsArray->Find(treeitem));
		}
        else m_tree->DeleteItem(item);
	}
	if(m_fictive_item==0)
		m_fictive_item = m_tree->InsertItem(_T("fictive"), 0, 0, m_item);
	m_bExpanded = false;
	
	return true;
}

void CPacketDlg::CDataSetTreeItem::Sort()
{
	if(m_tree==0) return;
	if(m_item==0) return;
	
	TVSORTCB sortcb;
	sortcb.hParent=m_item;
	sortcb.lpfnCompare=CompareHtreeItem;
	sortcb.lParam=1;
	m_tree->SortChildrenCB(&sortcb);
}

CPacketDlg::CPacketDlg(CaplAPI *api, CWnd* pParent /*=NULL*/)
	: CaplTranslateDialog(CPacketDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CPacketDlg)
	m_sProvider = _T("");
	m_sId = _T("");
	m_sDescr = _T("");
	m_sState = _T("");
	m_sRegistrator = _T("");
	m_sUnpacker = _T("");
	m_sSender = _T("");
	m_sComment = _T("");
	//}}AFX_DATA_INIT

	ASSERT(api);
	ASSERT(api->m_packet_mgr);
	m_api = api;
	m_packet_mgr = (CaplPacketMgr*)api->m_packet_mgr;

	m_inst = NULL;
	m_Provider = NULL;
	m_Registrator = NULL;
	m_Unpacker = NULL;
	m_Sender = NULL;

	m_pPacket = NULL;
	
	m_bOut = true;
}


void CPacketDlg::DoDataExchange(CDataExchange* pDX)
{
	CaplTranslateDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPacketDlg)
	DDX_Control(pDX, IDC_TREE, m_TreeCtrl);
	DDX_Control(pDX, IDC_DT_SEND, m_dtSendCtrl);
	DDX_Control(pDX, IDC_DT_UNPACK, m_dtUnpackCtrl);
	DDX_Control(pDX, IDC_DT_REGISTR, m_dtRegistrCtrl);
	DDX_Control(pDX, IDC_BROWSE_PROVIDER, m_browseprovider_btn);
	DDX_Control(pDX, IDCANCEL, m_cancel_btn);
	DDX_Control(pDX, IDOK, m_ok_btn);
	DDX_Text(pDX, IDC_PROVIDER, m_sProvider);
	DDX_Text(pDX, IDC_ID, m_sId);
	DDX_Text(pDX, IDC_DESCR, m_sDescr);
	DDX_Text(pDX, IDC_STATE, m_sState);
	DDX_Text(pDX, IDC_REGISTRATOR, m_sRegistrator);
	DDX_Text(pDX, IDC_UNPACKER, m_sUnpacker);
	DDX_Text(pDX, IDC_SENDER, m_sSender);
	DDX_Text(pDX, IDC_COMMENT, m_sComment);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CPacketDlg, CaplTranslateDialog)
	//{{AFX_MSG_MAP(CPacketDlg)
	ON_BN_CLICKED(IDC_BROWSE_PROVIDER, OnBrowseProvider)
	ON_NOTIFY(TVN_ITEMEXPANDING, IDC_TREE, OnItemexpandingTree)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPacketDlg message handlers

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

	m_ok_btn.SetIcon(GetAplStdIco16(APLSTDICO_OK));
	m_ok_btn.SetFlat(FALSE);
	m_cancel_btn.SetIcon(GetAplStdIco16(APLSTDICO_CANCEL));
	m_cancel_btn.SetFlat(FALSE);

	m_dtRegistrCtrl.SetFormat(_T("dd.MM.yyyy hh:mm"));
	m_dtUnpackCtrl.SetFormat(_T("dd.MM.yyyy hh:mm"));
	m_dtSendCtrl.SetFormat(_T("dd.MM.yyyy hh:mm"));

	m_TreeCtrl.SetImageList(aplGetInstImageList(), TVSIL_NORMAL);

	if(m_inst!=NULL)
	{
		CString type;
		CString buf;
		COleDateTime time;
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_id, m_sId);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_descr, m_sDescr);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_state, m_sState);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_registrator, m_Registrator);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_loader, m_Unpacker);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_sender, m_Sender);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_date_registr, buf);
		aplString2Date(buf, time);
		m_dtRegistrCtrl.SetTime(time);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_date_load, buf);
		aplString2Date(buf, time);
		m_dtUnpackCtrl.SetTime(time);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_date_send, buf);
		aplString2Date(buf, time);
		m_dtSendCtrl.SetTime(time);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_provider, m_Provider);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_type, type);
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_comment, m_sComment);

		m_bOut = type.CompareNoCase(_T("out"))==0;
	}
	else if(m_pPacket!=NULL)
	{
		m_Registrator = m_packet_mgr->GetCurrentPerson();
		m_sId = m_pPacket->m_sId;
		m_sDescr = m_pPacket->m_sDescr;
	}
	else
	{
		EndDialog(0);
		return FALSE;
	}

	if(m_Provider)
		m_api->GetItemName(m_Provider, m_sProvider);
	if(m_Registrator)
		m_api->GetItemName(m_Registrator, m_sRegistrator);
	if(m_Sender)
		m_api->GetItemName(m_Sender, m_sSender);
	else
		GetDlgItem(IDC_DT_SEND)->ShowWindow(SW_HIDE);
	if(m_Unpacker==NULL)
		GetDlgItem(IDC_DT_UNPACK)->ShowWindow(SW_HIDE);
	else
		m_api->GetItemName(m_Unpacker, m_sUnpacker);

	if(m_bOut)
	{
		CRect rect, old_rect;
		GetDlgItem(IDC_STATIC_UNPACKER)->ShowWindow(SW_HIDE);
		GetDlgItem(IDC_UNPACKER)->ShowWindow(SW_HIDE);
		GetDlgItem(IDC_STATIC_DATE_UNPACK)->ShowWindow(SW_HIDE);
		GetDlgItem(IDC_DT_UNPACK)->ShowWindow(SW_HIDE);

		GetDlgItem(IDC_STATIC_UNPACKER)->GetWindowRect(&rect);
		GetDlgItem(IDC_STATIC_STATE)->GetWindowRect(&old_rect);
		ScreenToClient(&rect);
		ScreenToClient(&old_rect);
		old_rect.top = rect.top;
		old_rect.bottom = rect.bottom;
		GetDlgItem(IDC_STATIC_STATE)->MoveWindow(&old_rect);

		GetDlgItem(IDC_UNPACKER)->GetWindowRect(&rect);
		GetDlgItem(IDC_STATE)->GetWindowRect(&old_rect);
		ScreenToClient(&rect);
		ScreenToClient(&old_rect);
		old_rect.top = rect.top;
		old_rect.bottom = rect.bottom;
		GetDlgItem(IDC_STATE)->MoveWindow(&old_rect);
	}
	else
	{
		CRect rect, old_rect;
		GetDlgItem(IDC_STATIC_SENDER)->ShowWindow(SW_HIDE);
		GetDlgItem(IDC_SENDER)->ShowWindow(SW_HIDE);
		GetDlgItem(IDC_STATIC_DATE_SEND)->ShowWindow(SW_HIDE);
		GetDlgItem(IDC_DT_SEND)->ShowWindow(SW_HIDE);

		GetDlgItem(IDC_STATIC_UNPACKER)->GetWindowRect(&rect);
		GetDlgItem(IDC_STATIC_STATE)->GetWindowRect(&old_rect);
		ScreenToClient(&rect);
		ScreenToClient(&old_rect);
		old_rect.top = rect.top;
		old_rect.bottom = rect.bottom;
		GetDlgItem(IDC_STATIC_STATE)->MoveWindow(&old_rect);
		
		GetDlgItem(IDC_UNPACKER)->GetWindowRect(&rect);
		GetDlgItem(IDC_STATE)->GetWindowRect(&old_rect);
		ScreenToClient(&rect);
		ScreenToClient(&old_rect);
		old_rect.top = rect.top;
		old_rect.bottom = rect.bottom;
		GetDlgItem(IDC_STATE)->MoveWindow(&old_rect);

		GetDlgItem(IDC_STATIC_SENDER)->GetWindowRect(&rect);
		GetDlgItem(IDC_STATIC_UNPACKER)->GetWindowRect(&old_rect);
		ScreenToClient(&rect);
		ScreenToClient(&old_rect);
		old_rect.top = rect.top;
		old_rect.bottom = rect.bottom;
		GetDlgItem(IDC_STATIC_UNPACKER)->MoveWindow(&old_rect);
		
		GetDlgItem(IDC_SENDER)->GetWindowRect(&rect);
		GetDlgItem(IDC_UNPACKER)->GetWindowRect(&old_rect);
		ScreenToClient(&rect);
		ScreenToClient(&old_rect);
		old_rect.top = rect.top;
		old_rect.bottom = rect.bottom;
		GetDlgItem(IDC_UNPACKER)->MoveWindow(&old_rect);

		GetDlgItem(IDC_STATIC_DATE_SEND)->GetWindowRect(&rect);
		GetDlgItem(IDC_STATIC_DATE_UNPACK)->GetWindowRect(&old_rect);
		ScreenToClient(&rect);
		ScreenToClient(&old_rect);
		old_rect.top = rect.top;
		old_rect.bottom = rect.bottom;
		GetDlgItem(IDC_STATIC_DATE_UNPACK)->MoveWindow(&old_rect);

		GetDlgItem(IDC_DT_SEND)->GetWindowRect(&rect);
		GetDlgItem(IDC_DT_UNPACK)->GetWindowRect(&old_rect);
		ScreenToClient(&rect);
		ScreenToClient(&old_rect);
		old_rect.top = rect.top;
		old_rect.bottom = rect.bottom;
		GetDlgItem(IDC_DT_UNPACK)->MoveWindow(&old_rect);
	}

	FillTree();

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

void CPacketDlg::OnOK() 
{
	if(!UpdateData()) return;

	m_sId.TrimLeft(); m_sId.TrimRight();
	//проверка на уникальность
	CString buf;
	CaplAttrValue tst_value;
	aplExtent res;
	tst_value.attr = m_packet_mgr->a_packet_id;
	tst_value.value.Set(m_sId);
	if(m_api->m_data.NET_FindInstancesWithAttrValues(m_packet_mgr->e_packet, 1, &tst_value, res, false)>0)
	{
		if((res[0]!=m_inst && m_inst!=NULL) || res.GetSize()>1 || (res.GetSize()>0 && m_inst==NULL))
		{
			AfxMessageBox(APL_T("Идентификатор пакета не уникален!"));
			return;
		}
	}

	if(m_inst==NULL)
		m_inst = m_api->m_data.CreateInstance(m_packet_mgr->e_packet);

	m_api->m_data.PutAttr(m_inst, m_packet_mgr->a_packet_id, m_sId);
	m_api->m_data.PutAttr(m_inst, m_packet_mgr->a_packet_descr, m_sDescr);
	m_api->m_data.PutAttr(m_inst, m_packet_mgr->a_packet_state, m_sState);
	m_api->m_data.PutAttr(m_inst, m_packet_mgr->a_packet_provider, m_Provider);

	COleDateTime time;
	m_dtRegistrCtrl.GetTime(time);
	aplDate2String(time, buf);

	m_api->m_data.PutAttr(m_inst, m_packet_mgr->a_packet_date_registr, buf);
	m_api->m_data.PutAttr(m_inst, m_packet_mgr->a_packet_registrator, m_Registrator);

	if(m_Unpacker)
	{
		m_dtUnpackCtrl.GetTime(time);
		aplDate2String(time, buf);
		m_api->m_data.PutAttr(m_inst, m_packet_mgr->a_packet_date_load, buf);
	}
	m_api->m_data.PutAttr(m_inst, m_packet_mgr->a_packet_loader, m_Unpacker);

	m_api->SaveChanges();
	
	CaplTranslateDialog::OnOK();
}

void CPacketDlg::OnBrowseProvider() 
{
	UpdateData();
	aplExtent ext;
	CaplInstance* inst = m_api->m_appr_mgr.SelectPersonOrOrganization(APL_MODE_SELECT_ORG, ext, APL_T("Выбор поставщика"));
	if(inst)
	{
		m_api->GetItemName(inst, m_sProvider);
		m_Provider = inst;
	}
	UpdateData(FALSE);
}

void CPacketDlg::FillTree()
{
	m_TreeCtrl.DeleteAllItems();
	if(m_inst!=NULL)
	{
		CaplInstance *DS;
		m_api->m_data.GetAttr(m_inst, m_packet_mgr->a_packet_data, DS);
		if(DS)
		{
			CDataSetTreeItem *pItem = new CDataSetTreeItem(m_api, &m_TreeCtrl, &m_ItemsArray, DS);
			pItem->CreateItem();
		}
	}
	else if(m_pPacket!=NULL)
	{
		if(m_pPacket->m_pRootDataSet!=NULL)
		{
			CDataSetTreeItem *pItem = new CDataSetTreeItem(m_api, &m_TreeCtrl, &m_ItemsArray, m_pPacket->m_pRootDataSet);
			pItem->CreateItem();
		}
	}
}

void CPacketDlg::OnItemexpandingTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	HTREEITEM ht = pNMTreeView->itemNew.hItem;
	if(ht)
	{
		CDataSetTreeItem* pItem = (CDataSetTreeItem*)m_TreeCtrl.GetItemData(ht);
		if(pItem)
			pItem->Expand(pNMTreeView->action);
	}
	
	*pResult = 0;
}
