// aplOrganizationTreeItem.cpp: implementation of the CaplOrganizationTreeItem class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "psm.h"
#include "aplOrganizationTreeItem.h"
#include "psmdoc.h"
#include "aplPersonTreeItem.h"
#include "aplDocTreeItem.h"
#include "aplTreeCharacteristicItem.h"
#include "aplCharacteristicGroupTreeItem.h"
#include "apl_prd_inst_item.h"

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

#define INDEX_MENU_ORGANIZATION 25
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CaplOrganizationTreeItem::CaplOrganizationTreeItem(CTreeCtrl *tree, CPSMDoc *pDoc, CaplInstance *inst)
{
	m_doc = pDoc;
	m_tree = tree;
	m_type = APL_TREE_ITEM_ORGANIZATION;
	m_inst=inst;
	m_used_inst_rel=0;
	m_folder=0;
	m_classifier=0;

	if(m_doc)
		m_doc->m_items.Add(this);
}

CaplOrganizationTreeItem::~CaplOrganizationTreeItem()
{
	RemoveFromParenContents(m_inst);
}

bool CaplOrganizationTreeItem::GetName(CString &name)
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL
	name =  APL_T("Организационная структура");
	if(m_inst==0) return true;
	name=_T("???");
	m_doc->m_api.GetItemName(m_inst,name);
	return true;
}

bool CaplOrganizationTreeItem::CreateTreeItem(HTREEITEM parent_item)
{
    if(m_tree==0) return false;
    if(m_doc==0) return false;
	CString name;
	GetName(name);
	int ico = ICON_ORGANIZATION;
	if(m_inst)
		ico = m_doc->m_api.GetInstIco(m_inst);
	InsetItem(name,ico,parent_item);
	SetItemImage(ico, IDX_IL_TREE_ITEM);
	m_fictive_item=m_tree->InsertItem(_T("fictive"),ICON_ORGANIZATION,ICON_ORGANIZATION,m_item);
	m_expanded=false;
	return true;
}

bool CaplOrganizationTreeItem::Expand(UINT action)
{
	int i;
	if(action==2)
	{
		if(m_expanded) return true;
		if(m_fictive_item!=0) 
		{
			m_tree->DeleteItem(m_fictive_item);
			m_fictive_item = 0;
		}

		if(!m_ShowContentsOnExpand)  return true;

		aplExtent out, pers, po;
		m_doc->m_api.m_appr_mgr.GetAllSubOrganization(m_inst,out);
		m_doc->m_api.m_appr_mgr.GetAllSubPerson(m_inst,pers,po);
		m_tree->SetRedraw(FALSE);
		
		for(i =0; i<out.Size;i++)
		{
			if(m_organization.Find(out[i])>-1) continue;
			
			CString sId;
			m_doc->m_api.m_data.GetAttr(out[i], m_doc->m_api.m_appr_mgr.a_org_id, sId);
			if(sId.IsEmpty()) continue;

			CaplOrganizationTreeItem *org = new CaplOrganizationTreeItem(m_tree,m_doc,out[i]);
			org->CreateTreeItem(m_item);
			m_organization.Add(out[i]);
		}
		CaplInstance *person;
		for(i =0; i<po.Size;i++)
		{
// 			if(m_person.Find(pers[i])>-1) continue;
			m_doc->m_api.m_data.GetAttr(po[i], m_doc->m_api.m_appr_mgr.a_po_the_pers, person);
			CaplPersonTreeItem *org = new CaplPersonTreeItem(m_tree,m_doc,person,po[i]);
			org->CreateTreeItem(m_item);
			m_person.Add(pers[i]);
		}
		
		bool old = m_bShowNoFoundMessage;
		m_bShowNoFoundMessage = old;
		m_ExecMyExpand = true;
		if(m_doc->m_auto_expand_items.m_showintree_org&APL_SHOW_DOC)
			ShowAllDocs(false, false);
		if(m_doc->m_auto_expand_items.m_showintree_org&APL_SHOW_CHARACT)
			ShowAllCharacteristic(false);
		m_bShowNoFoundMessage = old;
		m_ExecMyExpand = true;
		Sort();
		m_tree->SetRedraw(TRUE);
	}
	else if(action==1)
	{
		CollapseItem();	
		m_all_prd_instances.Clear();
		m_all_parents.Clear();
		m_organization.Clear();
		m_person.Clear();
	}
	return true;
}


bool CaplOrganizationTreeItem::ShowInListCtrl(CListCtrl *list)
{
	CHECK_SHOW_LIST_CTRL_TOP(m_inst, APL_T("Организационная структура"));


	CString id, name,descr,access,buf;
	m_doc->m_api.m_data.GetAttr(m_inst,m_doc->m_api.m_appr_mgr.a_org_id, id);
	m_doc->m_api.m_data.GetAttr(m_inst,m_doc->m_api.m_appr_mgr.a_org_name, name);
	m_doc->m_api.m_data.GetAttr(m_inst,m_doc->m_api.m_appr_mgr.a_org_descr, descr);
	int ind = list->InsertItem(0, APL_T("Обозначение:"));
	list->SetItemText(ind,1,id);
	ind = list->InsertItem(list->GetItemCount(), APL_T("Наименование:"));
	list->SetItemText(ind,1,name);
	ind = list->InsertItem(list->GetItemCount(), APL_T("Описание:"));
	list->SetItemText(ind,1,descr);

	CaplInstance *inst;

	ind = list->InsertItem(list->GetItemCount(), APL_T("Правопреемник:"));
	m_doc->m_api.m_data.GetAttr(m_inst,m_doc->m_api.m_appr_mgr.a_org_successor, inst);
	if(inst)
	{
		m_doc->m_api.GetItemName(inst,buf);
		list->SetItemText(ind,1,buf);	
	}


	list->InsertItem(list->GetItemCount(),_T(""));
	ind = list->InsertItem(list->GetItemCount(), APL_T("Доступ:"));
	GetAccessName(m_inst,access);
	list->SetItemText(ind,1,access);
	
	aplExtent ext;
	CStringArray  comment;
	
	if(m_inst!=0){
		comment.Add(_T("m_inst"));
		ext.Add(m_inst);
	}
	if(m_classifier!=0){
		CaplInstance* classif_ref;
		m_doc->m_api.m_classifier_mgr.TestClassifierAssociation(m_inst,m_classifier,&classif_ref);
		if(classif_ref!=0){
			comment.Add(_T("classifier association"));
			ext.Add(classif_ref);
		}
		comment.Add(_T("m_classifier"));
		ext.Add(m_classifier);
	}
	if(m_folder!=0){
		comment.Add(_T("m_folder"));
		ext.Add(m_folder);
	}

	ShowInstanceInfoInListCtrl(ext,list,&comment);

	return true;
}

bool CaplOrganizationTreeItem::PasteFile(LPCTSTR file, CPoint *point)
{
	if(file==0) return false;
	if(m_inst!=0) CreateDoc(m_inst,file);
	return true;
}

bool CaplOrganizationTreeItem::PasteItem(CaplTreeItem *item, CPoint *point)
{
	if(!m_inst) return false;
	if(item->m_type!=APL_TREE_ITEM_DOCUMENT &&
		item->m_type!=APL_TREE_ITEM_CHARACTERISTIC &&
		item->m_type!=APL_TREE_ITEM_CHARACTERISTICGROUP &&
		item->m_type!=APL_TREE_ITEM_PRDINST) return false;
	CMenu menu;  gSetPsmResourceHandle();
	CMenu *Popup;
	VERIFY(menu.LoadMenu(IDR_PASTE_ITEM_MENU));
// 	VERIFY(menu.LoadToolBar(IDR_MENU_ICONS));
	CaplMenu::Install(m_tree); // 	VERIFY(CaplMenu::Install(m_tree, ePopupMenu ));
	if(item->m_type==APL_TREE_ITEM_DOCUMENT)
	{
		aplExtent ext;
		item->GetAccessedInstances(ext);
		CString state;
		m_doc_data.GetAttr(ext[0],m_doc->m_api.m_doc_mgr.a_apl_doc_wf_state,state);
		if(state==_T("canceled")) return false;
		Popup = menu.GetSubMenu(2);
	}
	else if(item->m_type==APL_TREE_ITEM_PRDINST)
	{
		CaplInstance *related=((CaplPrdInstTreeItem *)item)->m_inst;

		CaplInstance *related_pdf=0;
		m_doc_data.GetAttr(related, m_doc->m_api.m_prd_inst_mgr.a_prd_inst_pdf,related_pdf);
				
		CaplInstance* comp=m_doc->m_api.m_prd_inst_mgr.InsertInPI(m_inst,related);
		if(comp==0) return true;
					
		CaplPrdInstTreeItem *inst_item= new CaplPrdInstTreeItem(m_tree,m_doc,related);
		inst_item->m_prd_inst_rel=comp;
		inst_item->CreateTreeItem(m_item);
		m_all_prd_instances.Add(comp);
		inst_item->RefreshItem();
		Sort();
		MyExpand(false);
		return true;
	}
	else if(item->m_type==APL_TREE_ITEM_CHARACTERISTIC || item->m_type==APL_TREE_ITEM_CHARACTERISTICGROUP)
		Popup = menu.GetSubMenu(3);

	if(Popup!=0)
	{
		POINT pnt;
		if(point==0)
		{
			RECT rect;
			m_tree->GetItemRect(m_item,&rect,TRUE);
			m_tree->ClientToScreen(&rect);
			pnt.x=rect.right;
			pnt.y=rect.bottom;
		}
		else
		{
			pnt.x=point->x;
			pnt.y=point->y;
		}
		BOOL res = Popup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD,pnt.x,pnt.y,m_tree);
		
		// Вставка документа
		if (res == ID_DOCUMENT_COPY)
		{
			CaplInstance *i_doc=((CaplDocTreeItem *)item)->m_inst;
			
			HTREEITEM ht = m_tree->GetNextItem(item->m_item,TVGN_PARENT);
			CaplTreeItem *Item = (CaplTreeItem*)m_tree->GetItemData(ht);
			aplAccessModeType access =aplOWN;
			if(Item)
			{
				aplExtent instances;
				Item->GetAccessedInstances(instances);
				if(instances.GetSize()>0)
					access = instances.GetAt(0)->GetAccessmode();
			}
			
			if(m_inst->GetAccessmode()>aplRW || access>aplRO)
			{
				AfxMessageBox( APL_T("Нет доступа к объекту"));
				return false;
			}

			if(CaplDocTreeItem::InsertDoc(m_doc,this,&m_all_documents,i_doc,m_inst, false))
				ShowAllDocs();
		}
		//создание по образцу
		else if(res == ID_DOCUMENT_BYDOT)
		{
			CaplInstance *i_doc = ((CaplDocTreeItem *)item)->m_inst;

			aplExtent instances;
			GetAccessedInstances(instances);
			if(m_doc->m_api.m_doc_mgr.CreateDocumentByDot(i_doc,instances[0]))
				ShowAllDocs();
		}
		//премещение документа
		else if(res == ID_DOCUMENT_MOVE)
		{
			CaplDocTreeItem *d_item = (CaplDocTreeItem*)item;
			HTREEITEM parent = m_tree->GetNextItem(d_item->m_item,TVGN_PARENT);
			CaplTreeItem *parent_item = (CaplTreeItem*)m_tree->GetItemData(parent);
			
			CaplDocTreeItem::MoveDocument(m_doc, d_item, parent_item, this);
		}
		else if(res == ID_CHARACTERISTIC_COPY)
		{
			if(item->m_type == APL_TREE_ITEM_CHARACTERISTIC)
			{
				CaplInstance *i_val=((CaplCharacteristicTreeItem *)item)->m_val;
				CreateCharacteristic(m_inst,i_val);
			}
			else if(item->m_type == APL_TREE_ITEM_CHARACTERISTICGROUP)
			{
				CreateCharacteristicGroup(m_inst,((CaplCharacteristicGroupTreeItem*)item)->m_group);
			}
		}
	}
	return true;
}

void CaplOrganizationTreeItem::GetAccessedInstances(aplExtent &ext)
{
	ext.Clear();
	if(m_inst!=0){if(m_inst->GetType()!=0)ext.Add(m_inst);}
}

BOOL CaplOrganizationTreeItem::ShowToolBarButton(CCmdUI *pCmdUI)
{
	if(m_inst==0) return FALSE;
	if(m_inst->GetType()==0) return FALSE;
	switch(pCmdUI->m_nID)
	{
		case ID_SHOW_ALL_DOCS:
		case ID_SHOW_ALL_CHARACTERISTIC:
		case ID_CREATE_DOC:
		case ID_CREATE_CHARACTERISTIC:
		case ID_SHOW_NOTES:
		case ID_CREATE_NOTE:
		case ID_SHOW_ALL_PRD_INST:
			pCmdUI->Enable(TRUE); return TRUE; break;
	}
	return FALSE;
}

void CaplOrganizationTreeItem::ShowCmd(long cmd)
{
	switch(cmd)
	{
		case ID_SHOW_ALL_DOCS: ShowAllDocs();break;
		case ID_SHOW_ALL_CHARACTERISTIC: ShowAllCharacteristic(true);break;
		case ID_CREATE_DOC: CreateDoc();break;
		case ID_CREATE_CHARACTERISTIC: CreateCharacteristic(m_inst);break;
		case ID_SHOW_ALL_PRD_INST: ShowAllPrdInst(); break;
		default: PrepareContextMenu(cmd);break;
	}
}

/*
void CaplOrganizationTreeItem::CreateCharacteristic(CaplInstance *val)
{
	if(m_inst==0) return;
	if(m_inst->GetType()==0) return;
	if(m_inst->GetAccessmode()>aplRO) {aplErrorMessage(S::NoAccessRight,m_inst);return;};
	CaplInstance *new_val=0;
	if(m_doc->m_api.m_charact_mgr.CreateCharacteristic(m_inst,val, &new_val,0,0,true))
	{
		if(CaplTreeItem::m_AutoUzurpireCharacteristic)
		{
			aplExtent ext; 
			ext.Add(new_val);
			m_doc_data.NET_BecomeInstancesOwner(&ext);
		}

		CaplCharacteristicTreeItem *characteristic_item=
			new CaplCharacteristicTreeItem(m_tree,m_doc,new_val);
		characteristic_item->CreateTreeItem(m_item);
		m_all_caracteristic.Add(new_val);
		MyExpand();
		m_doc->ChangeItem(0);m_doc->ChangeItem(this);
	}
}
*/
bool CaplOrganizationTreeItem::TrackPopupMenu(CWnd *wnd, CPoint &point, UINT view_mode)
{
	if(m_inst==0) return false;
	CMenu menu;  gSetPsmResourceHandle();
	CMenu *Popup=0;
	VERIFY(menu.LoadMenu(IDR_TREE_CONTEXT_MENU));
// 	VERIFY(menu.LoadToolBar(IDR_MENU_ICONS));
	CaplMenu::Install(wnd); // 	VERIFY(CaplMenu::Install(m_tree, ePopupMenu ));
	Popup = menu.GetSubMenu(INDEX_MENU_ORGANIZATION);
	if(Popup!=0)
	{
		// Удаляем сообщение
		UINT iNum = 0;
		for (UINT i = 0; i < Popup->GetMenuItemCount(); i++)
		{
			if (Popup->GetMenuItemID(i) == ID_NEW_MESSAGE_CREATE)
			{
				iNum = i;
				break;
			}
		}
		if(iNum>0)
		{
			((CMenu*)Popup)->DeleteMenu(iNum, MF_BYPOSITION);
			((CMenu*)Popup)->DeleteMenu(iNum, MF_BYPOSITION);
		}

		AppendAddIn((CMenu*)Popup);
		UpdateMenu((CMenu**)&Popup, view_mode);

		if(m_folder==0)Popup->EnableMenuItem(ID_REMOVE_FROM_FOLDER, MF_BYCOMMAND | MF_GRAYED);
		if(m_classifier==0){Popup->EnableMenuItem(ID_REMOVE_FROM_CLASSIFIER, MF_BYCOMMAND | MF_GRAYED);}

		BOOL res = Popup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD,point.x,point.y,wnd);
		if(res==ID_CREATE_DOC) CreateDoc();
		else if(res==ID_CREATE_CHARACTERISTIC) CreateCharacteristic(m_inst);
		else if(res==ID_CREATE_CHARACTERISTIC_GROUP) CreateCharacteristicGroup(m_inst);
		else if(res==ID_SHOW_PROPERTIES) m_doc->m_api.m_appr_mgr.ShowOrganizationProperties(m_inst);
		else if(res==ID_OPEN_ITEM_IN_NEW_WINDOW) m_doc->OpenInstanceInNewWindow(m_inst);
		else if(res==ID_SHOW_ALL_INST)
		{
			ShowAllPrdInst();
		}
		else if(res==ID_WHERE_USED_PERORG)
		{
			ShowAllParentOrgs();
		}
		else if(res==ID_REMOVE_FROM_FOLDER)
		{
			if(m_folder!=0)
			{
				if(m_doc->m_api.m_folder_mgr.RemoveFromFolder(m_folder,m_inst))
					m_doc->m_items.Remove(m_doc->m_items.Find(this));
			}				
		}
		else if(res==ID_REMOVE_FROM_CLASSIFIER)
		{
			if(m_classifier!=0)
			{
				if(m_classifier->GetAccessmode()>aplRW)	{AfxMessageBox(ID_NO_ACCESS_RIGHT,MB_OK|MB_ICONSTOP); return true;}
				if(m_doc->m_api.m_classifier_mgr.DeleteClassifierAssociation(m_inst,m_classifier))
					m_doc->m_items.Remove(m_doc->m_items.Find(this));
			}
		}
		else PrepareContextMenu(res);
	}
	return true;
}

void CaplOrganizationTreeItem::ShowProperties()
{
	if(0==m_inst)return;
	if(m_inst->GetType()==0) return;
	m_doc->m_api.m_appr_mgr.ShowOrganizationProperties(m_inst);
}

bool CaplOrganizationTreeItem::RefreshItem()
{
	if(!m_inst) return true;
	CString name;
	GetName(name);
	m_tree->SetItemText(m_item,name);
	if(m_used_inst_rel!=0)
	{
		SetItemImage(ICO_REL_WHERE_USED, IDX_IL_TREE_REL_TYPE);
		CString buf;
		m_doc_data.GetAttr(m_used_inst_rel,m_doc->m_api.m_prd_inst_mgr.a_prd_inst_rel_date_removed,buf);
		if(buf!=_T(""))
			SetItemImage(ICO_EFF_NOT_USED, IDX_IL_TREE_EFF);
	}
	return true;
}

//****************************************************************

void CaplOrganizationTreeItem::ShowAllParentOrgs()
{
	if(m_doc==0) return;
	StartBusy();
	m_tree->SetRedraw(FALSE);
	
	aplExtent ext;
	aplExtent orgs;
	CaplInstance* inst;
	int i;

	CaplAPI* api= &m_doc->m_api;
	
	if(api->m_data.IsKindOf(m_inst, api->m_appr_mgr.e_org))
	{
		api->m_data.GetEntityExtent(api->m_appr_mgr.e_org_rel, ext);

		for(i= 0; i<ext.GetSize(); i++)
		{
			api->m_data.GetAttr(ext[i], api->m_appr_mgr.a_org_rel_related, inst);
			if(inst==m_inst)
			{
				api->m_data.GetAttr(ext[i], api->m_appr_mgr.a_org_rel_relating, inst);
				CaplOrganizationTreeItem* org_Item= NULL;
				if(InsertInstInTree(inst, m_item, m_doc, m_tree, m_all_parents, 0, ((CaplTreeItem**)&org_Item)))
				{
					org_Item->m_used_inst_rel= ext[i];
					org_Item->RefreshItem();
				}
			}
		}
	}

	MyExpand(false);
	StopBusy();
	m_tree->SetRedraw(TRUE);
}

void CaplOrganizationTreeItem::ShowAllPrdInst()
{
	if(m_doc==0) return;
	StartBusy();
	CaplInstance *inst;
	aplExtent ext,ext_rel;
	m_doc->m_api.m_prd_inst_mgr.LoadInsertedInstances(m_inst,ext_rel,ext);
	int show_history;
	m_doc->m_api.m_options_mgr.GetOptionValueBN( APL_NO_T("Показывать историю экземпляров изделий"),show_history,1);
	CString date_removed;
	for(int i=0;i<ext_rel.Size;i++)
	{
		if(m_all_prd_instances.Find(ext_rel[i])>=0) continue ;
		if(!show_history)
		{
			m_doc_data.GetAttr(ext_rel[i],m_doc->m_api.m_prd_inst_mgr.a_prd_inst_rel_date_removed,date_removed);
			if(date_removed!=_T("")) continue;
		}
		m_doc_data.GetAttr(ext_rel[i],m_doc->m_api.m_prd_inst_mgr.a_prd_inst_rel_related,inst);
		if(m_doc_data.IsKindOf(inst,m_doc->m_api.m_prd_inst_mgr.e_prd_inst))
		{
			CaplPrdInstTreeItem *inst_item= new CaplPrdInstTreeItem(m_tree,m_doc,inst);
			inst_item->m_prd_inst_rel=ext_rel[i];
			inst_item->CreateTreeItem(m_item);
			m_all_prd_instances.Add(ext_rel[i]);
			inst_item->RefreshItem();
		}
	}
	MyExpand(false);
	StopBusy();
	m_tree->SetRedraw(TRUE);
}