#include "stdafx.h"
#include "dictionary.h"

#include "PSMDoc.h"

/*#include "aplTopLevelItem.h"
#include "aplFolderTreeItem.h"
#include "aplMessageTreeItem.h"*/
#include "aplMessageFolderTreeItem.h"
#include "aplTreeProcessItem.h"
#include "aplTreeTaskItem.h"
#include "TreeProductItem.h"
#include "aplDocTreeItem.h"
#include "TabView.h"

#include "resource.h"

//CaplProcessTreeItem
CaplProcessTreeItem::CaplProcessTreeItem(CTreeCtrl *tree, CPSMDoc *doc, CaplInstance* inst)
{
	m_type= APL_TREE_ITEM_PROCESS;
	m_doc= doc;
	m_tree= tree;
	m_process= inst;
	m_folder= NULL;
	m_project= NULL;
	m_task= NULL;
	m_bIsParent=false;
	if(doc!=0) 
		doc->m_items.Add(this);	
}

bool CaplProcessTreeItem::GetName(CString &name)
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL
	CHECK_GET_NAME(m_process);
	
	CString buf;
	name= _T("");
	if(m_doc->m_api.m_show.m_show_process_id)
	{
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_action_id, name);
	}
	if(m_doc->m_api.m_show.m_show_process_name)
	{
		if(name!=_T(""))
			name+=_T(" : ");
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_action_name, buf);
	}
	name+=buf;
	return true;
}

bool CaplProcessTreeItem::RefreshItem()
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL
	if(!m_process || m_process->GetType()==0) return false;
	m_doc->m_wf_mgr.LoadProcessInfo(m_process);

	font_style=0;
	color=RGB(0,0,0);
	
	UINT ico= ICON_PROCESS;
	
	if(m_tree!=0)
	{
		CString name, buf, buf1;
		GetName(name);
		
		CString str;
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_state, str);
		UINT ico_state= 1, ico_prior= ICO_EFF_NO, ico_type= 0;
		if(str==_T("running")) ico_state++;
		else if(str==_T("suspended"))  ico_state+=2;
		else if(str==_T("terminated"))   ico_state+=3;
		else if(str==_T("completed")) ico_state+=4;
		else if(str==_T("jammed"))  ico_state=8;

		CString prior;
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_act_inst_prior, prior);
		if(prior==_T("low")) ico_prior= ICO_EFF_LOW;
		else if(prior==_T("hight")) ico_prior= ICO_EFF_HIGH;
		else ico_prior= ICO_EFF_NORMAL;;
		
		CaplInstance* owner;
		CaplInstance* manager;
		CaplInstance* person;
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_owner, owner);
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_manager, manager);
		person= m_doc->m_api.m_appr_mgr.GetCurrentPerson();
		if(owner!=person && aplIsPersonOrgElement(&m_doc->m_api, manager, person))
			ico_type= 9;

		SetItemImage(ico_type, IDX_IL_TREE_REL_TYPE);		
		SetItemImage(ico_prior, IDX_IL_TREE_EFF);		
		SetItemImage(ico_state,IDX_IL_TREE_OBJ_STATE);
		SetItemImage(ico, IDX_IL_TREE_ITEM);

		if(m_bIsParent) SetItemImage(ICO_REL_WHERE_USED, IDX_IL_TREE_REL_TYPE);

		m_tree->SetItemText(m_item, name);	

		// Выделяем цветом просроченные
		// Выделяем цветом просроченные
		bool bWarning=false;
		if(m_doc->m_wf_mgr.GetItemColor(m_process,color,&bWarning)) {	if(bWarning) font_style|=APL_FONT_BOLD;	}
	}
	if(m_doc->m_tab_view->m_item_old==this) m_doc->ChangeItem(this);
	return true;
}

bool CaplProcessTreeItem::CreateTreeItem(HTREEITEM parent_item)
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL
	CString name, buf, buf1;
	//GetName(buf);
	UINT ico= ICON_PROCESS;
	
	InsetItem(buf,ico,parent_item);
	SetItemImage(ico, IDX_IL_TREE_ITEM);
	m_fictive_item=m_tree->InsertItem(_T("fictive"), 0, 0, m_item);
	m_expanded=false;

	RefreshItem();

	return true;
}

bool CaplProcessTreeItem::Expand(UINT action)
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL
	
	if(action==2)
	{
		if(m_expanded) return true;
		if(m_hasSubItem) Expand(1);
		if(m_fictive_item!=0)
		{
			m_tree->DeleteItem(m_fictive_item);
			m_fictive_item=0;
		}
		GetProcessTasks();
		m_hasSubItem= true;
		m_expanded= true;
		m_tree->SetRedraw(TRUE);
		SortTask();
	}
	else if(action==1)
	{
		CollapseItem();
		m_task_items.Clear();
		m_work_obj_items.Clear();
	}
	return true;
}

void CaplProcessTreeItem::ShowProperties()
{
	_APL_TREE_ITEM_CHEK_PARAM_VOID
	if(m_doc->m_wf_mgr.LoadProcessInfo(m_process))
	{
		m_doc->m_wf_mgr.ShowProcessProperties(m_process);
		RefreshItem();
	}
}

bool CaplProcessTreeItem::ShowInListCtrl(CListCtrl *list)
{
	if(list==0) return false;
	else list->DeleteAllItems();
	if(m_doc==0)return false;
	if(m_doc->m_BShowInListCtrl==false) return true;
	
	CHECK_SHOW_LIST_CTRL(m_process);

	m_doc->m_wf_mgr.LoadProcessInfo(m_process);

	CString buf, buf1;
	int i= list->InsertItem(0,  APL_T("Обозначение:"));
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_action_id, buf);
	list->SetItemText(i, 1, buf);
	i= list->InsertItem(1,  APL_T("Наименование:"));
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_action_name, buf);
	list->SetItemText(i, 1, buf);
	i= list->InsertItem(2,  APL_T("Описание:"));
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_action_dscr, buf);
	list->SetItemText(i, 1, buf);
	
	i= list->InsertItem(3, _T(""));

	CaplInstance* inst= NULL;
	CaplAggr aggr;
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_owner, inst);
	if(inst)
	{
		i= list->InsertItem(4,  APL_T("Владелец:"));
		//m_doc->m_api.m_appr_mgr.GetPersonName(inst, buf);
		m_doc->m_api.GetItemName(inst, buf);
		if(m_doc->m_api.m_data.IsKindOf(inst,m_doc->m_api.m_appr_mgr.e_person))
		{
			CString sPhone;
			m_doc_data.GetAttr(inst, m_doc->m_api.m_appr_mgr.a_pers_phone, sPhone);
			if(sPhone!=_T("")){buf+=_T(" (тел.");buf+=sPhone; buf+=_T(")");}
		}
		list->SetItemText(i, 1, buf);
		list->SetItemData(i,(long)inst);
	}

	i= list->InsertItem(5, _T(""));
	
	COleDateTime odt;
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_act_inst_start_date, buf);
	if(!buf.IsEmpty())
	{
		i=list->InsertItem(6,  APL_T("Дата создания:"));
		aplString2Date(buf, odt);	
		buf= odt.Format(_T("%d.%m.%Y  %H:%M"));
		list->SetItemText(i, 1, buf);
	}
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_act_inst_end_date, buf);
	if(buf.IsEmpty())
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_act_inst_finish_date, buf);
	if(!buf.IsEmpty())
	{
		i=list->InsertItem(7,  APL_T("Дата завершения:"));
		aplString2Date(buf, odt);	
		buf= odt.Format(_T("%d.%m.%Y  %H:%M"));
		list->SetItemText(i, 1, buf);
	}
	double n;
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_act_inst_percent, n);
	buf.Format(_T("%i"), (int)n);buf+=_T('%');
	i=list->InsertItem(8,  APL_T("Выполнено:"));
	list->SetItemText(i, 1, buf);		
	
	list->InsertItem(9, _T(""));
	
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_act_inst_prior, buf);
	if(buf==_T("low")) buf=  APL_T("Низкий");
	else if(buf==_T("medium")) buf=  APL_T("Обычный");
	else if(buf==_T("hight")) buf=  APL_T("Высокий");
	i=list->InsertItem(10,  APL_T("Приоритет:"));
	list->SetItemText(i, 1, buf);

	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_state, buf);
	if(buf==_T("initiated")) buf=  APL_T("Создан");
	else if(buf==_T("running")) buf=  APL_T("Выполняется");
	else if(buf==_T("suspended")) buf=  APL_T("Остановлен");
	else if(buf==_T("terminated")) buf=  APL_T("Прерван");
	else if(buf==_T("completed")) buf=  APL_T("Завершен");
	else if(buf==_T("jammed")) buf=  APL_T("Завис");
	i=list->InsertItem(11,  APL_T("Состояние:"));
	list->SetItemText(i, 1, buf);

/*
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_, );
*/

	aplExtent ext;
	CStringArray  comment;

	if(m_process!=0){
		comment.Add(_T("m_process"));
		ext.Add(m_process);
	}
	
	ShowInstanceInfoInListCtrl(ext,list,&comment);
	
	return true;
}

void CaplProcessTreeItem::ShowCmd(long cmd)
{
	switch(cmd)
	{
		case ID_CREATE_DOC: CreateDocument(); break;
		case ID_CREATE_PRODUCT: CreateProduct(); break;
		case ID_SHOW_NOTES: ShowNotes(); break;
	}
}

BOOL CaplProcessTreeItem::ShowToolBarButton(CCmdUI* pCmdUI)
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL
	
	if(m_process==0) return false;
	if(m_process->GetId()==0) return false;
	if(m_process->GetType()==0) return false;

	CString buf;
	BOOL bShow= FALSE;
	CaplInstance *user= m_doc->m_api.m_appr_mgr.GetCurrentPerson();
	CaplInstance* per= NULL;
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_owner, per);
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_state, buf);

	if(user==per && (buf==_T("running") || buf==_T("initiated")))
	{
		bShow= TRUE;
	}

	switch(pCmdUI->m_nID)
	{
		case ID_CREATE_DOC: 
		case ID_CREATE_PRODUCT: 
			pCmdUI->Enable(bShow); return TRUE; break;
		case ID_SHOW_NOTES:
		case ID_CREATE_NOTE:
			pCmdUI->Enable(TRUE); return TRUE; break;

	}
	return FALSE;
}

bool CaplProcessTreeItem::TrackPopupMenu(CWnd* wnd, CPoint &point, UINT view_mode)
{
	if(!m_process || m_process->GetType()==0)
		return false;

	CMenu menu;  gSetPsmResourceHandle();
	VERIFY(menu.LoadMenu(IDR_TREE_CONTEXT_MENU));
// 	VERIFY(menu.LoadToolBar(IDR_MENU_ICONS));
	CaplMenu::Install(wnd); //	VERIFY(CaplMenu::Install(wnd, ePopupMenu ));
    CMenu* pPopup = menu.GetSubMenu(INDEX_PROCESS_MENU);
    ASSERT(pPopup != NULL);
	if(pPopup==0) return false;

	if(m_process)
	{
		AppendAddIn((CMenu*)pPopup);
		UpdateMenu((CMenu**)&pPopup, view_mode);
	}
	
	//для запуска процесса с несколькими входными точками
	CArray<CStPointsMenuInfo, CStPointsMenuInfo> stPoints;
	CMenu* pSubPopup= NULL;

	CaplInstance *user= m_doc->m_api.m_appr_mgr.GetCurrentPerson();

	CaplInstance* owner= NULL, *manager= NULL;
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_owner, owner);
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_manager, manager);
	CString buf;
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_state, buf);
	if(buf!=_T("initiated") && buf!=_T("suspended"))
		pPopup->EnableMenuItem(ID_PROCESS_RUN, MF_BYCOMMAND | MF_GRAYED);
	if(buf==_T("initiated"))
	{
		pPopup->EnableMenuItem(ID_PROCESS_SUSPEND, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_PROCESS_RESTART, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_PROCESS_COMPLETE, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_PROCESS_ARCHIVE, MF_BYCOMMAND | MF_GRAYED);
		if(user!=owner)
			pPopup->EnableMenuItem(ID_PROCESS_RUN, MF_BYCOMMAND | MF_GRAYED);

		aplExtent acts, st_points;
		m_doc->m_wf_mgr.GetProcessComponents(m_process, acts);
		
		//!!!
		int m= 100; //могут рухнуть ресурсы PDM... Хотя, скорее всего, ID не завязаны на ресурсы.
		for(int i= 0; i<acts.GetSize(); i++)
		{
			if(m_doc_data.IsKindOf(acts[i], m_doc->m_wf_mgr.e_start_point))
			{	
				CString str, name;
				m_doc_data.GetAttr(acts[i], m_doc->m_wf_mgr.a_action_id, name);
				m_doc_data.GetAttr(acts[i], m_doc->m_wf_mgr.a_action_name, str);
				if(!str.IsEmpty())
				{
					name+=_T(":")+str;
				}
				CStPointsMenuInfo info(m, name, acts[i]);
				stPoints.Add(info);
				m+=10;
			}
		}
		
		if(stPoints.GetSize()>1)
		{
			pSubPopup= new CMenu;
			
			if(pSubPopup->CreatePopupMenu())
			{
				for(int n= 0; n<stPoints.GetSize(); n++)
				{
					pSubPopup->InsertMenu(n, MF_BYPOSITION|MF_STRING, 
						stPoints[n].m_iID, stPoints[n].m_sName);
				}
			}

			pPopup->ModifyMenu(ID_PROCESS_RUN, MF_BYCOMMAND|MF_POPUP, 
				(UINT)pSubPopup->GetSafeHmenu(),  APL_T("Запустить с..."));
		}
	}
	if(buf==_T("completed") || buf==_T("terminated"))
	{
		pPopup->EnableMenuItem(ID_PROCESS_SUSPEND, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_PROCESS_RESTART, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_PROCESS_COMPLETE, MF_BYCOMMAND | MF_GRAYED);				
		pPopup->EnableMenuItem(ID_PROCESS_TERMINATE, MF_BYCOMMAND | MF_GRAYED);				
		pPopup->EnableMenuItem(ID_PROCESS_BECOME_OWNER, MF_BYCOMMAND | MF_GRAYED);
		
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_archive_date, buf);
		if(user!=owner || !buf.IsEmpty())//не владелец, или уже сдали в архив
		{
			pPopup->EnableMenuItem(ID_PROCESS_ARCHIVE, MF_BYCOMMAND | MF_GRAYED);
		}
		pPopup->EnableMenuItem(ID_CREATE_DOC, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_CREATE_PRODUCT, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_CREATE_REFUSAL, MF_BYCOMMAND | MF_GRAYED);
	}
	
	if(!aplIsPersonOrgElement(&m_doc->m_api, owner, user)/*user!=owner*/ && 
		!aplIsPersonOrgElement(&m_doc->m_api, manager, user)/*user!=manager*/)
	{
		pPopup->EnableMenuItem(ID_PROCESS_SUSPEND, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_PROCESS_RESTART, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_PROCESS_COMPLETE, MF_BYCOMMAND | MF_GRAYED);				
		pPopup->EnableMenuItem(ID_PROCESS_TERMINATE, MF_BYCOMMAND | MF_GRAYED);				
		
		if(!m_doc->m_api.m_data.IsAdmin())
		{
			pPopup->EnableMenuItem(ID_PROCESS_BECOME_OWNER, MF_BYCOMMAND | MF_GRAYED);
			pPopup->EnableMenuItem(ID_DELETE, MF_BYCOMMAND | MF_GRAYED);
		}

		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_archive_date, buf);
		if(user!=owner || !buf.IsEmpty())//не владелец, или уже сдали в архив
		{
			pPopup->EnableMenuItem(ID_PROCESS_ARCHIVE, MF_BYCOMMAND | MF_GRAYED);
		}
		pPopup->EnableMenuItem(ID_CREATE_DOC, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_CREATE_PRODUCT, MF_BYCOMMAND | MF_GRAYED);		
		pPopup->EnableMenuItem(ID_CREATE_REFUSAL, MF_BYCOMMAND | MF_GRAYED);		
	}
	else
	{
		pPopup->EnableMenuItem(ID_PROCESS_BECOME_OWNER, MF_BYCOMMAND | MF_GRAYED);
	}

	if(buf==_T("suspended"))
	{
		pPopup->ModifyMenu(ID_PROCESS_RUN, MF_BYCOMMAND|MF_STRING, ID_PROCESS_RUN,  APL_T("&Продолжить выполнение"));
		pPopup->EnableMenuItem(ID_PROCESS_SUSPEND, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_PROCESS_ARCHIVE, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_DELETE, MF_BYCOMMAND | MF_GRAYED);
	}
	if(buf==_T("running"))
	{
		pPopup->EnableMenuItem(ID_PROCESS_ARCHIVE, MF_BYCOMMAND | MF_GRAYED);
		pPopup->EnableMenuItem(ID_DELETE, MF_BYCOMMAND | MF_GRAYED);
	}

	if(!m_folder)
		pPopup->EnableMenuItem(ID_REMOVE_FROM_FOLDER, MF_BYCOMMAND | MF_GRAYED);
	if(!m_project)
		pPopup->EnableMenuItem(ID_DELETE_FROM_PROJECT, MF_BYCOMMAND | MF_GRAYED);
	if(!m_task)
		pPopup->EnableMenuItem(ID_DELETE_FROM_TASK, MF_BYCOMMAND | MF_GRAYED);

	BOOL res = pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
						point.x, point.y, wnd);

	CaplInstance* proc= NULL;
	COleDateTime odt;
	m_doc_data.NET_GetServerDateTime(odt);
	CStringArray procLog;
	int i;

	switch (res)
	{
		case ID_PROCESS_RUN:
			RunWfProcess();
			break;
		case ID_PROCESS_SUSPEND:
			SuspendWfProcess();
			break;
		case ID_PROCESS_RESTART:
			proc= m_doc->m_wf_mgr.RestartWfProcess(m_process);
			if(proc)
			{
				if(m_folder)m_doc->m_api.m_folder_mgr.AddToFolder(m_folder, proc);
				if(m_project)m_doc->m_api.m_project_mgr->CreateAssociation(m_project, proc);
				HTREEITEM item= m_tree->GetParentItem(m_item);
				CaplTreeItem* parentItem= (CaplTreeItem*)m_tree->GetItemData(item);
				aplExtent ext;
				CaplTreeItem* newItem= NULL;
				
				if(parentItem)parentItem->InsertInstInTree(proc, item, m_doc, m_tree, ext, NULL, &newItem);
				parentItem->Sort();
				
				((CaplProcessTreeItem*)newItem)->m_folder= m_folder;
				((CaplProcessTreeItem*)newItem)->m_project= m_project;
				
				if(m_process->GetType()==NULL) m_doc->m_items.Remove(m_doc->m_items.Find(this));
				else RefreshItem();
			}
			break;
		case ID_PROCESS_TERMINATE:
			m_doc->m_wf_mgr.TerminateWfProcess(m_process);
			RefreshItem();
			break;
		case ID_PROCESS_COMPLETE:
			m_doc->m_wf_mgr.EndWfProcess(m_process);
			RefreshItem();
			break;
		case ID_WORK_ITEMS:
			ShowWorkObjects();
			if(!m_expanded)
			{
				m_expanded= true;
				m_hasSubItem= true;
			}
			MyExpand();
			break;
		case ID_PROCESS_TASKS:
			GetProcessTasks();
			if(!m_expanded)
			{
				m_expanded= true;
				m_hasSubItem= true;
			}
			MyExpand();
			SortTask();
			break;
		case ID_CREATE_DOC:
			if(m_doc->m_wf_mgr.CanChangeWorkObjectsList(m_process))
			{
				if(CreateDocument())
				{
					ShowWorkObjects();
					if(!m_expanded)
					{
						m_expanded= true;
						m_hasSubItem= true;
					}
					MyExpand();
				}
			}
			break;
		case ID_CREATE_PRODUCT:
			if(m_doc->m_wf_mgr.CanChangeWorkObjectsList(m_process))
			{
				if(CreateProduct())
				{
					ShowWorkObjects();
					if(!m_expanded)
					{
						m_expanded= true;
						m_hasSubItem= true;
					}
					MyExpand();
				}
			}
			break;
		case ID_CREATE_REFUSAL:
			if(m_doc->m_wf_mgr.CanChangeWorkObjectsList(m_process))
			{
				if(CreateRefusal())
				{
					ShowWorkObjects();
					if(!m_expanded)
					{
						m_expanded= true;
						m_hasSubItem= true;
					}
					MyExpand();
				}
			}
			break;
		case ID_CREATE_NOTE: CreateNote(); break;
		case ID_SHOW_NOTES: ShowNotes(); break;
		case ID_PROCESS_ARCHIVE:
			{
				aplDate2String(odt, buf);
				m_doc_data.PutAttr(m_process, m_doc->m_wf_mgr.a_proc_archive_date, buf);
				m_doc_data.NET_SaveChanges();

			}
			break;
		case ID_DELETE:
			if(IDYES==AfxMessageBox( APL_T("Вы действительно хотите удалить процесс?"), MB_YESNO|MB_ICONWARNING) && 
				m_doc->m_wf_mgr.DeleteWfProcess(m_process, procLog))
			{
				m_doc->m_items.Remove(m_doc->m_items.Find(this));
			}
			break;
		
		case ID_SHOW_WF_TEMPL_SCHEMA:
			{
				CaplInstance *ptempl=0;
				m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_of_tmpl, ptempl);

				m_doc->m_wf_mgr.ShowTemplateSchema(ptempl,0);
			}
			break;
		case ID_SHOW_PARENT_TASK:
			{
				ShowParentTasks();
			}
			break;
		case ID_SHOW_PARENT_PROCESS:
			{
				ShowParentProcess();
			}
			break;
		case ID_SHOW_CONTAINED_FOLDER:
			{
				ShowContainedFolder(m_process);
			}
			break;
		case ID_REMOVE_FROM_FOLDER:
			{
				if(m_doc->m_api.m_folder_mgr.RemoveFromFolder(m_folder, m_process))
					m_doc->m_items.Remove(m_doc->m_items.Find(this));
			}
			break;
		case ID_DELETE_FROM_PROJECT:
			{
				if(m_doc->m_project_mgr->DeleteAssociation(m_project, m_process))
					m_doc->m_items.Remove(m_doc->m_items.Find(this));
			}
			break;
		case ID_DELETE_FROM_TASK:
			if(IDYES==AfxMessageBox( APL_T("Вы действительно хотите удалить процесс\nиз перечня подпроцессов задания?"), MB_YESNO|MB_ICONWARNING))
			{
				aplExtent ext;
				m_doc->m_api.m_data.GetAttr(m_task, m_doc->m_wf_mgr.a_task_sub_proc, ext);
				ext.Remove(ext.Find(m_process));
				m_doc->m_api.m_data.PutAttr(m_task, m_doc->m_wf_mgr.a_task_sub_proc, ext);
				m_doc->m_api.SaveChanges();
				
				CaplTaskTreeItem* task_item;

				for(int j= 0; j<m_doc->m_items.GetSize(); j++)
				{
					if(m_doc->m_items[j]->m_type!=APL_TREE_ITEM_TASK) continue;

					task_item= (CaplTaskTreeItem*)m_doc->m_items[j];
					if(task_item->m_task!=m_task) continue;

					task_item->m_sub_proc_items.Remove(task_item->m_sub_proc_items.Find(m_process));
				}

				m_doc->m_items.Remove(m_doc->m_items.Find(this));
			}
			break;
		case ID_PROCESS_BECOME_OWNER:
			{
				CaplInstance* person= m_doc->m_api.m_appr_mgr.GetCurrentPerson();
				if(!person)
				{
					AfxMessageBox( APL_T("Анонимный пользователь не может стать ответственным за контроль процесса!"));
					break;
				}

				CaplInstance* curManager;
				m_doc->m_api.m_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_manager, curManager);
				if(curManager==person)
					break;

				if(curManager)
				{
					if(IDNO==AfxMessageBox( APL_T("У процесса уже есть ответственный за контроль. Продолжить?"), MB_YESNO|MB_ICONQUESTION))
						break;
				}
				else
				{
					if(IDNO==AfxMessageBox( APL_T("Вы хотите стать ответственным за контроль  процесса?"), MB_YESNO|MB_ICONQUESTION))
						break;					
				}

				m_doc->m_api.m_data.PutAttr(m_process, m_doc->m_wf_mgr.a_proc_manager, person);
				m_doc->m_api.SaveChanges();
				
				if(IDYES==AfxMessageBox( APL_T("Вы стали ответственным за контроль  процесса. Открыть свойства процесса?"), MB_YESNO|MB_ICONQUESTION))
					ShowProperties();
			}
			break;
		default: 		
			for(i=0; i<stPoints.GetSize(); i++)
			{
				if(res==stPoints[i].m_iID)//это запускается процесс
				{
					CaplInstance* first_activity= NULL;
					aplExtent ext1, ext2;
					m_doc->m_wf_mgr.GetConnectors(stPoints[i].m_point, ext1, ext2);
					
					if(ext2[0])
					{
						m_doc_data.GetAttr(ext2[0], m_doc->m_wf_mgr.a_act_rel_to, first_activity);
/*						if(first_activity && !m_doc_data.IsKindOf(first_activity, m_doc->m_wf_mgr.e_activity))
						{
							//скорее всего со входа идет на выход
							first_activity= NULL;
						}*/
						RunWfProcess(first_activity);
					}
					
					break;
				}
			}
			
			PrepareContextMenu(res);
			break;
	}

	if(pSubPopup)
	{
		pSubPopup->DestroyMenu();
		delete pSubPopup;
		pSubPopup= NULL;
	}
	return true;

}

void CaplProcessTreeItem::ShowUserProcesses()
{
	_APL_TREE_ITEM_CHEK_PARAM_VOID	
}
 
void CaplProcessTreeItem::RunWfProcess(CaplInstance* first_activity)
{
	_APL_TREE_ITEM_CHEK_PARAM_VOID	
	
	m_doc->m_wf_mgr.LoadProcessInfo(m_process);

	CString sSt;
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_state, sSt);

	if(sSt==_T("initiated"))
	{
		///////////////////////////////////////////////////////////////////////////
		//Если имеется несколько точек входа, при запуске процесса надо указать,
		//с какой точки начинать процесс. 
/*		aplExtent act, ep;
		m_doc->m_wf_mgr.GetProcessComponents(m_process, act);
		for(int i= 0; i<act.GetSize(); i++)
		{
			if(m_doc_data.IsKindOf(act[i], m_doc->m_wf_mgr.e_start_point))
			{
				aplExtent ext1, ext2;
				m_doc->m_wf_mgr.GetConnectors(act[i], ext1, ext2);
				
				if(ext2[0])
					m_doc_data.GetAttr(ext2[0], m_doc->m_wf_mgr.a_act_rel_to, first_activity);
				break; //пока только одна точка входа
			}
		}
		///////////////////////////////////////////////////////////////////////////////
		if(!first_activity)
		{
			MessageBox(NULL, APL_T("Неовзможно запустить процесс"), APL_T("Ошибка запуска процесса"),
				MB_OK|MB_ICONERROR);
			return;
		}
		
		m_doc_data.PutAttr(m_process, m_doc->m_wf_mgr.a_proc_first_activity, first_activity);
		m_doc_data.NET_SaveChanges();*/
	}

	if(m_doc->m_wf_mgr.RunWfProcess(m_process, true, first_activity))
		RefreshItem();
}

void CaplProcessTreeItem::GetProcessTasks()
{
	_APL_TREE_ITEM_CHEK_PARAM_VOID
	if(!m_process || m_process->GetType()==0)
		return;
	
	aplExtent ext_tasks;
	m_doc->m_wf_mgr.GetProcessTasks(m_process, ext_tasks);
	CString buf;
	bool bInsert;
	for(int i= 0; i<ext_tasks.GetSize(); i++)
	{
		if(-1==m_task_items.Find(ext_tasks[i]))
		{
			buf= _T("");
			bInsert= true;
/*			m_doc_data.GetAttr(ext_tasks[i], m_doc->m_wf_mgr.a_task_state, buf);
			if(buf==_T("suspend") && !CaplTaskTreeItem::m_ShowSuspended) bInsert= false;
			if(buf==_T("complete") && !CaplTaskTreeItem::m_ShowCompleted) bInsert= false;
			if(buf==_T("cancel") && !CaplTaskTreeItem::m_ShowCanceled) bInsert= false;*/
			if(bInsert)
			{
				CaplTaskTreeItem* item= new CaplTaskTreeItem(m_tree, m_doc, ext_tasks[i], APL_WF_SWOW_SP);
				item->CreateTreeItem(m_item);
				m_task_items.Add(ext_tasks[i]);
			}
		}
	}
}

void CaplProcessTreeItem::SuspendWfProcess()
{
	_APL_TREE_ITEM_CHEK_PARAM_VOID
	m_doc->m_wf_mgr.LoadProcessInfo(m_process);
	if(m_doc->m_wf_mgr.SuspendWfProcess(m_process))
	{
		RefreshItem();
	}
}

void CaplProcessTreeItem::ShowWorkObjects()
{
	_APL_TREE_ITEM_CHEK_PARAM_VOID
	m_tree->SetRedraw(FALSE);
	if(m_process && m_doc->m_wf_mgr.LoadProcessInfo(m_process))
	{
		int i;
		CaplAggr aggr;
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_wo, aggr);
		aplExtent ext;
		for(i= 0; i<aggr.GetSize(); i++)
		{
			CaplInstance* inst= NULL, *inst1= NULL;
			aggr.GetByIndex(i, inst1);
			
			if(!inst1) continue;
			if(inst1->GetAccessmode()==aplNO) continue;
			
			m_doc_data.GetAttr(inst1, m_doc->m_wf_mgr.a_wo_object, inst);

			if(!inst) continue;
			if(inst->GetAccessmode()==aplNO) continue;
	
			ext.Add(inst);
		}
	
		m_doc->m_api.m_message_mgr.LoadExtentInfo(ext);

		for(i= 0; i<ext.GetSize(); i++)
		{
			if(-1==m_work_obj_items.Find(ext[i]))
			{
				CaplTreeItem* aplItem= NULL;
				InsertInstInTree(ext[i], m_item, m_doc, m_tree, m_work_obj_items, 
					NULL, &aplItem);
			}
		}
	}//if(proc)
	m_tree->SetRedraw(TRUE);
}

void CaplProcessTreeItem::Sort(bool bRefreshParent)
{
	SortTask();
}

void CaplProcessTreeItem::SortTask()
{
	if(m_tree==0) return;
	if(m_item==0) return;
	TVSORTCB sortcb;
	sortcb.hParent=m_item;
	sortcb.lpfnCompare=CompareTaskTreeItem;
	sortcb.lParam=1;
	m_tree->SortChildrenCB(&sortcb);	
}

int CALLBACK CaplProcessTreeItem::CompareTaskTreeItem(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{

	if(lParam1==0) return 0;
	if(lParam2==0) return 0;
	
	if(((CaplTreeItem*)lParam1)->m_type!=APL_TREE_ITEM_TASK || ((CaplTreeItem*)lParam2)->m_type!=APL_TREE_ITEM_TASK)
		return 0;
	
	CaplInstance* inst1= ((CaplTaskTreeItem*)lParam1)->m_task;
	CaplInstance* inst2= ((CaplTaskTreeItem*)lParam2)->m_task;
	
	/*  ЯАИ. При параллельных процессах время запуска логического блока и того, что но запускает,
		совпадает с точностью до секунды.  Порядок сортировки получается странный.
		Добавление дополнительно соритровки по ID не решает проблемы, т.к. сравниваются не все со всеми.
	
	CString buf1, buf2;
	((CaplTaskTreeItem*)lParam1)->m_doc_data.GetAttr(inst1, 
		((CaplTaskTreeItem*)lParam1)->m_doc->m_wf_mgr.a_act_inst_start_date, buf1);
	((CaplTaskTreeItem*)lParam2)->m_doc_data.GetAttr(inst2, 
		((CaplTaskTreeItem*)lParam2)->m_doc->m_wf_mgr.a_act_inst_start_date, buf2);

	if(buf1==_T("") || buf2==_T("") || buf1==buf2 )
	{
		if(inst1->GetId() < inst2->GetId()) return -1;
		return 1;
	}
	return buf1.Compare(buf2);*/

	if(inst1->GetId() < inst2->GetId()) return -1;
	return 1;

}

bool CaplProcessTreeItem::PasteItem(CaplTreeItem *item, CPoint *point)
{
	if(item==0) return false;
	if(m_tree==0) return false;
	if(m_doc==0) return false;
	if(!m_process || m_process->GetType()==0)
		return false;
	
	CaplInstance *user= m_doc->m_api.m_appr_mgr.GetCurrentPerson();
	CaplInstance* owner= NULL;
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_owner, owner);
	
	if(user!=owner) return false;

	CaplAggr aggr;
	CaplInstance* proc= NULL;
	if(m_process)
	{
		CString buf;
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_state, buf);
		if(buf!=_T("running") && buf!=_T("initiated") ) return true;
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_wo, aggr);
	}
	else return false;
	
	CaplInstance* inst= NULL;
	if(item->m_type==APL_TREE_ITEM_PRODUCT)
	{
		inst=((CaplProductTreeItem*)item)->m_pdf;
		if(inst==0) inst=((CaplProductTreeItem*)item)->m_prd;
		if(inst==0) return false;
	}
	else if(item->m_type==APL_TREE_ITEM_DOCUMENT)
	{
		if(0!=((CaplDocTreeItem*)item)->m_rev) inst=((CaplDocTreeItem*)item)->m_rev;
		else inst=((CaplDocTreeItem*)item)->m_inst;
		if(inst==0) return false;
	}
	else 
	{
		aplExtent ext;
		item->GetAccessedInstances(ext);
		if(!ext.GetSize()) return false;

		inst= ext[0];
	}

	bool bIsNew= true;
	for(int i= 0; i<aggr.GetSize(); i++)
	{
		CaplInstance* wo= NULL;
		CaplInstance* w_item= NULL;
		aggr.GetByIndex(i, wo);
		if(wo)
			m_doc_data.GetAttr(wo, m_doc->m_wf_mgr.a_wo_object, w_item);
		if(inst==w_item) bIsNew= false;
	}
	if(bIsNew)
	{
		if(!m_doc->m_wf_mgr.CanChangeWorkObjectsList(proc))return false;
		CaplInstance* wo= m_doc_data.CreateInstance(m_doc->m_wf_mgr.e_wo);
		if(wo)
		{
			m_doc_data.PutAttr(wo, m_doc->m_wf_mgr.a_wo_object, inst);
			m_doc_data.PutAttr(wo, m_doc->m_wf_mgr.a_wo_action, m_process);

			aggr.Add(wo);
			
			m_doc_data.PutAttr(m_process, m_doc->m_wf_mgr.a_proc_wo, aggr);
			m_doc_data.NET_SaveChanges();
		}
	}
	return true;
}

bool CaplProcessTreeItem::CreateDocument()
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL
	if(m_process==0) return false;
	if(m_process->GetType()==0) return false;
	
	CaplInstance* doc=m_doc->m_api.m_doc_mgr.CreateDocument(_T(""), 0, 0, 0, _T(""));
	if(doc==0) return false;
	/*
	if(CaplTreeItem::m_AutoUzurpireDoc)
	{
		aplExtent ext; 
		ext.Add(doc);
		m_doc_data.NET_BecomeInstancesOwner(&ext);
	}*/

	m_doc->m_wf_mgr.LoadProcessInfo(m_process);
	CaplAggr aggr;			
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_wo, aggr);
	CaplInstance* wo= m_doc_data.CreateInstance(m_doc->m_wf_mgr.e_wo);
	if(wo)
	{
		m_doc_data.PutAttr(wo, m_doc->m_wf_mgr.a_wo_object, doc);
		m_doc_data.PutAttr(wo, m_doc->m_wf_mgr.a_wo_action, m_process);

		aggr.Add(wo);
		
		m_doc_data.PutAttr(m_process, m_doc->m_wf_mgr.a_proc_wo, aggr);
		m_doc_data.NET_SaveChanges();
	}
	return true;
}

bool CaplProcessTreeItem::CreateRefusal()
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL
	if(m_process==0) return false;
	if(m_process->GetType()==0) return false;

	//CaplInstance *refusalt=m_doc->m_api.m_expl_mgr->CreateRefusal();
	aplExtent ext;
	CaplInstance *refusalt=m_doc->m_fault_mgr.CreateRefusal(0,ext);
	if(0==refusalt) return false;

	m_doc->m_wf_mgr.LoadProcessInfo(m_process);
	CaplAggr aggr;			
	m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_wo, aggr);
	CaplInstance* wo= m_doc_data.CreateInstance(m_doc->m_wf_mgr.e_wo);
	if(wo)
	{
		m_doc_data.PutAttr(wo, m_doc->m_wf_mgr.a_wo_object, refusalt);
		m_doc_data.PutAttr(wo, m_doc->m_wf_mgr.a_wo_action, m_process);

		aggr.Add(wo);

		m_doc_data.PutAttr(m_process, m_doc->m_wf_mgr.a_proc_wo, aggr);
		m_doc_data.NET_SaveChanges();
	}
	return true;
}

bool CaplProcessTreeItem::CreateProduct()
{
	_APL_TREE_ITEM_CHEK_PARAM_BOOL
	
	if(m_process==0) return false;
	if(m_process->GetType()==0) return false;
	
	CaplInstance *tmp_prd, *tmp_inst = m_doc->m_api.m_prd_mgr.CreateProduct(NULL, aplModeCreateProduct);
	if(tmp_inst!=NULL)
	{
		m_doc_data.GetAttr(tmp_inst, m_doc->m_api.m_prd_mgr.a_pdf_prd, tmp_prd);
		
		m_doc->m_wf_mgr.LoadProcessInfo(m_process);
		CaplAggr aggr;			
		m_doc_data.GetAttr(m_process, m_doc->m_wf_mgr.a_proc_wo, aggr);
		CaplInstance* wo= m_doc_data.CreateInstance(m_doc->m_wf_mgr.e_wo);
		if(wo)
		{
			m_doc_data.PutAttr(wo, m_doc->m_wf_mgr.a_wo_object, tmp_prd);
			m_doc_data.PutAttr(wo, m_doc->m_wf_mgr.a_wo_action, m_process);
			
			aggr.Add(wo);
			
			m_doc_data.PutAttr(m_process, m_doc->m_wf_mgr.a_proc_wo, aggr);
			m_doc_data.NET_SaveChanges();
		}
	}
	return true;
}

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

bool CaplProcessTreeItem::ShowParentProcess()
{
	aplExtent ext;
	m_doc->m_wf_mgr.GetParentTasks(m_process,ext);
	if(0==ext.GetSize()) {AfxMessageBox(APL_T("Процесс не является подпроцессом")); return true;}
	m_doc->m_wf_mgr.LoadTaskInfo(ext);
	int i;
	for(i=0;i<ext.GetSize();i++)
	{
		CaplInstance *task=ext[i];
		if(0==task) continue;
		CaplInstance *proc;
		m_doc_data.GetAttr(task, m_doc->m_wf_mgr.a_task_proc, proc);
		if(0==proc) continue;

		CaplProcessTreeItem* item= new CaplProcessTreeItem(m_tree, m_doc, proc);
		item->m_bIsParent=true;
		item->CreateTreeItem(m_item);
	}
	MyExpand(false);
	return true;
}
bool CaplProcessTreeItem::ShowParentTasks()
{
	//Expand(2);
	aplExtent ext;
	m_doc->m_wf_mgr.GetParentTasks(m_process,ext);
	if(0==ext.GetSize()) {AfxMessageBox(APL_T("Процесс не является подпроцессом")); return true;}

	m_doc->m_wf_mgr.LoadTaskInfo(ext);
	int i;
	for(i=0;i<ext.GetSize();i++)
	{
		CaplInstance *task=ext[i];

		CaplTaskTreeItem* item= new CaplTaskTreeItem(m_tree, m_doc, task);
		item->m_bIsParent=true;
		item->CreateTreeItem(m_item);

	}
	MyExpand(false);
	return true;
}
