// aplOrgStructHelper.cpp: implementation of the CaplOrgStructHelper class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "apl_api.h"
#include "aplOrgStructHelper.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

void CaplOrgStructHelper::SetApi(CaplAPI *api)
{
	m_api = api;
}

int CALLBACK CaplOrgStructHelper::CompareTreeItems(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	if((lParam1==0) || (lParam2==0)) return 0;
	CaplAPI *m_api=(CaplAPI *)lParamSort;
	if(0==m_api) return 0;
	CaplAutorizationManager *m_autMgr = &(m_api->m_appr_mgr);
	CaplNetStepData *data= m_autMgr->m_data;
	CaplInstance *inst1= (CaplInstance *)lParam1;
	CaplInstance *inst2= (CaplInstance *)lParam2;
	if(data->IsKindOf(inst1, m_autMgr->e_pers_org)) data->GetAttr(inst1, m_autMgr->a_po_the_pers, inst1);
	if(data->IsKindOf(inst2, m_autMgr->e_pers_org)) data->GetAttr(inst2, m_autMgr->a_po_the_pers, inst2);
	int type1 = (int)inst1->GetType();
	int type2 = (int)inst2->GetType();
	if(type1<type2) return 1;
	else if(type1>type2) return  -1;
	CString name1, name2;
	m_autMgr->m_api->GetItemName(inst1,name1);
	m_autMgr->m_api->GetItemName(inst2,name2);
	return name1.Compare(name2);
}

void CaplOrgStructHelper::Sort(CTreeCtrl &tc, HTREEITEM item)
{
	TVSORTCB sortcb;
	sortcb.lpfnCompare = CompareTreeItems;
	sortcb.lParam = (LPARAM)m_api;
	sortcb.hParent = item;
	tc.SortChildrenCB(&sortcb);
}

void  CaplOrgStructHelper::InsertItem(CTreeCtrl &tc, CaplInstance *item, HTREEITEM parent)
{
	if(0==item) return;
	if(0==item->GetType()) return;
	if(item->GetAccessmode()>aplRO) return;

	CString name;

	if(m_api->m_data.IsKindOf(item, m_api->m_appr_mgr.e_pers_org)) 
		m_api->m_data.GetAttr(item, m_api->m_appr_mgr.a_po_the_pers, item);

	if(m_bWithPers && m_api->m_data.IsKindOf(item, m_api->m_appr_mgr.e_person))
	{
		m_api->GetItemName(item,name);
		HTREEITEM pers_item=tc.InsertItem(name,ICON_PERSON,ICON_PERSON,parent,TVI_LAST);
		tc.SetItemData(pers_item,(long)item);
	}
	else if(m_bWithOffc && m_api->m_data.IsKindOf(item, m_api->m_appr_mgr.e_official))
	{
		m_api->GetItemName(item,name);
		HTREEITEM pers_item=tc.InsertItem(name,ICON_OFFICIAL,ICON_OFFICIAL,parent,TVI_LAST);
		tc.SetItemData(pers_item,(long)item);
	}
	else if(m_api->m_data.IsKindOf(item, m_api->m_appr_mgr.e_org))
	{
		m_api->GetItemName(item,name);
		HTREEITEM org_item=tc.InsertItem(name,ICON_ORGANIZATION,ICON_ORGANIZATION,parent,TVI_LAST);
		tc.SetItemData(org_item,(long)item);

		int i;
		CaplAggr* aggr_org=m_org_struct_map.QGetByIn((long)item);
		if(0!=aggr_org)
		{
			for(i=0;i<aggr_org->GetSize();i++)
			{
				int k;
				aggr_org->GetByIndex(i,k);
				InsertItem(tc,(CaplInstance *)k,org_item);
			}
		}

		CaplAggr* aggr_pers=m_org_pers_map.QGetByIn((long)item);
		if(0!=aggr_pers)
		{
			for(i=0;i<aggr_pers->GetSize();i++)
			{
				int k;
				aggr_pers->GetByIndex(i,k);
				InsertItem(tc,(CaplInstance *)k,org_item);
			}
		}
	}
}


HTREEITEM CaplOrgStructHelper::InsertFolder(CTreeCtrl &tc, CaplInstance *folder, HTREEITEM parent)
{
	if(0==folder) return 0;
	if(0==folder->GetType()) return 0;
	if(folder->GetAccessmode()>aplRO) return 0;

	int i,ico=ICON_FOLDER; 
	CString name,name1;
	m_api->m_folder_mgr.GetItemName(folder,name);
	name1=name; name1.MakeLower();
	if(name1==APL_NO_T("адресная книга"))
	{
		CaplInstance *parent;
		m_api->m_data.GetAttr(folder,m_api->m_folder_mgr.a_folder_parent,parent);
		if(parent==m_api->m_data.GetCurrUser())  ico=ICON_PERS_FOLDER;
	}
	
	HTREEITEM hitem=tc.InsertItem(name,ico,ico,parent,TVI_LAST);
	tc.SetItemData(hitem,(long)folder);

	aplExtent ext;
	m_api->m_folder_mgr.GetAllSubFolder(folder,ext);
	if(ext.Size>0)
	{
		for(i=0;i<ext.GetSize();i++)
			InsertFolder(tc,ext[i],hitem);
	}

	m_api->m_folder_mgr.GetFolderContents(folder,ext);
	if(ext.Size>0)
	{
		for(i=0;i<ext.GetSize();i++)
			InsertItem(tc,ext[i],hitem);
	}
	return hitem;
}

void CaplOrgStructHelper::FillTree(CTreeCtrl &tc, aplExtent &extRoot, bool bWithPers, bool bWithOffc, bool bWithMy, bool bWithAWG, bool bPO)
{
	tc.SetRedraw(FALSE);
	tc.DeleteAllItems();
	m_org_struct_map.Clear();
	m_org_pers_map.Clear();

	m_bWithPers=bWithPers;
	m_bWithOffc=bWithOffc;
	m_bWithMy=bWithMy;
	m_bWithAWG=bWithAWG;

	int i;
	CString buf;
	CaplInstance *inst,*inst1;

	aplExtent extOrg ;
	aplExtent extPers;
	aplExtent extOffc;
	aplExtent extPO  ;
	aplExtent extREL ;

	aplExtent extBottomOrg; extBottomOrg.Unique=false;
	aplExtent extBottomPers; extBottomPers.Unique=false;

	//Определякм Верхушки организаций

	m_api->m_data.GetEntityExtent(m_api->m_appr_mgr.e_org,		extOrg);
	m_api->m_data.GetEntityExtent(m_api->m_appr_mgr.e_person,   extPers);
	m_api->m_data.GetEntityExtent(m_api->m_appr_mgr.e_official, extOffc);

	m_api->m_data.GetEntityExtent(m_api->m_appr_mgr.e_org_rel, extREL);
	for (i=0; i<extREL.Size; ++i) 
	{
		if(extREL[i]->GetAccessmode() > aplRO) continue;
		m_api->m_data.GetAttr(extREL[i], m_api->m_appr_mgr.a_org_rel_relating, inst);
		m_api->m_data.GetAttr(extREL[i], m_api->m_appr_mgr.a_org_rel_related, inst1);
		if(0==inst) continue;
		if(0==inst1) continue;
		if(0==inst->GetType()) continue;
		if(0==inst1->GetType()) continue;
		m_org_struct_map.Add((long)inst,(long)inst1);

		extBottomOrg.Add(inst1);
	}
	extBottomOrg.Sort();

	if(bWithPers||bWithOffc)
	{
		m_api->m_data.GetEntityExtent(m_api->m_appr_mgr.e_pers_org, extPO);
		for (i=0; i<extPO.Size; ++i) 
		{
			CaplInstance *po=extPO[i];
			if(0==po->GetType()) continue;
			if(po->GetAccessmode() > aplRO) continue;
			m_api->m_data.GetAttr(po, m_api->m_appr_mgr.a_po_end_date, buf);
			if(buf!=_T("")) continue;
			m_api->m_data.GetAttr(po, m_api->m_appr_mgr.a_po_the_pers, inst);
			m_api->m_data.GetAttr(po, m_api->m_appr_mgr.a_po_the_org, inst1);
			if(0==inst) continue;
			if(0==inst1) continue;
			if(0==inst->GetType()) continue;
			if(0==inst1->GetType()) continue;
			m_org_pers_map.Add((long)inst1,(long)inst);

			extBottomPers.Add(inst);
		}
		extBottomPers.Sort();
	}

	/*CaplInstance *curs_pers=m_api->m_data.GetCurrUser();
	 Перенесено в мои рабочие группы
	int iVal=0;
	m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Настройка Workflow\\Выводить личные папки в диалог выбора организаций"), iVal, 1);

	if(0!=curs_pers && iVal>0  && extRoot.GetSize()==0)
	{
		aplExtent adressbooks;
		CaplAttrValue find_values[2];
		find_values[0].attr = m_api->m_folder_mgr.a_folder_parent;
		find_values[0].value.Set(curs_pers);
		find_values[1].attr = m_api->m_folder_mgr.a_folder_name;
		find_values[1].value.Set(APL_NO_T("адресная книга"));
		m_api->m_data.NET_FindInstancesWithAttrValues(m_api->m_folder_mgr.e_folder, 2, &find_values[0], adressbooks, false);

		if(adressbooks.GetSize()>0)
		{
			HTREEITEM item=InsertFolder(tc,adressbooks[0],TVI_ROOT);
			if(bWithMy && 0==extRoot.GetSize()) tc.Expand(item, TVE_EXPAND);
		}
		HTREEITEM parent = tc.InsertItem( APL_T("Личные папки"), ICON_PERS_FOLDER, ICON_PERS_FOLDER, TVI_ROOT, TVI_FIRST);
		tc.SetItemData(parent, 0);

		aplExtent ext;
		m_api->m_folder_mgr.GetAllSubFolder(curs_pers,ext);
		if(ext.Size>0)
		{
			int i; 
			for(i=0;i<ext.GetSize();i++)
			{
				InsertFolder(tc,ext[i],parent);				
			}
		}
		if(bWithMy && 0==extRoot.GetSize()) tc.Expand(parent, TVE_EXPAND);
	}*/

	CaplInstance *curs_user=m_api->m_data.GetCurrUser();
	CaplInstance *curs_pers = m_api->m_appr_mgr.GetCurrentPerson();
	if(bWithMy && 0!=curs_pers) // Мои рабочие группы
	{
		CString sEndDate;
		HTREEITEM parent = tc.InsertItem( APL_T("Мои рабочие группы"), ICON_ORGANIZATION, ICON_ORGANIZATION, TVI_ROOT, TVI_LAST);
		tc.SetItemData(parent, 0);

		// адресная книга
		CaplInstance* address_book = m_api->m_message_mgr.GetAddressBook();

		if(address_book != 0)
		{
			m_api->m_folder_mgr.LoadFolderInfo(address_book);
			HTREEITEM item=InsertFolder(tc,address_book,parent);
			//if(bWithMy && 0==extRoot.GetSize()) tc.Expand(item, TVE_EXPAND);
		}
	

		// рабочие группы
		CaplAttrValue av(m_api->m_appr_mgr.a_po_the_pers);
		av.value.Set(curs_pers);
		aplExtent ext;
		m_api->m_data.NET_FindInstancesWithAttrValues(m_api->m_appr_mgr.e_pers_org,	1, &av, ext, false);

		for (i=0; i<ext.GetSize(); i++)
		{
			m_api->m_data.GetAttr(ext[i], m_api->m_appr_mgr.a_po_the_org, inst);
			if(!inst) continue;
			m_api->m_data.GetAttr(ext[i], m_api->m_appr_mgr.a_po_end_date, sEndDate);
			if(sEndDate!=_T("")) continue;
			InsertItem(tc,inst,parent);
				}
		if(0==extRoot.GetSize()) tc.Expand(parent, TVE_EXPAND);
	}


	if(bWithAWG || (extRoot.GetSize()==0)) // Все рабочие группы
	{
		// Добавляем корневые организации
		HTREEITEM parent = tc.InsertItem( APL_T("Все рабочие группы"), ICON_ORGANIZATION, ICON_ORGANIZATION, TVI_ROOT, TVI_LAST);
		tc.SetItemData(parent, 0);
		for (i=0; i<extOrg.Size; ++i) 
		{
			CaplInstance *org=extOrg[i];
			if(0==org->GetType()) continue;
			if(org->GetAccessmode() > aplRO) continue;

			int k=aplQFindInstInExtent(extBottomOrg,org,false);
			if(k>=0) 
				continue; // это не верхушка
			m_api->m_data.GetAttr(org, m_api->m_appr_mgr.a_org_name, buf);
			if(buf ==  APL_NO_T("Удаленные")) 
				continue;

			InsertItem(tc,org,parent);
		}
		// Добавляем корневых  сотрудников
		extPers.Append(extOffc);
		for (i=0; i<extPers.Size; ++i) 
		{
			CaplInstance *pers=extPers[i];
			if(0==pers->GetType()) continue;
			if(pers->GetAccessmode() > aplRO) continue;

			int k=aplQFindInstInExtent(extBottomPers,pers,false);
			if(k>=0) continue; // это не верхушка

			InsertItem(tc,pers,parent);
		}
		if(0==extRoot.GetSize()) tc.Expand(parent, TVE_EXPAND);
	}

	if(extRoot.GetSize()>0)
	{
		for (i=0; i<extRoot.GetSize(); i++)
		{
			InsertItem(tc,extRoot[i],TVI_ROOT);
		}
	}
	Sort(tc, TVI_ROOT);
	tc.SetRedraw(TRUE);
}
