// SelectAccessAgent.cpp : implementation file
//

#include "stdafx.h"
//#include <apltransportclienttcp.h>
#include <afxcmn.h>
#include "SelectAccessAgent.h"

extern CImageList imagelist;

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

#define TIMER_UNCKECK 12345

/////////////////////////////////////////////////////////////////////////////
// CSelectAccessAgent dialog


CSelectAccessAgent::CSelectAccessAgent(CWnd* pParent /*=NULL*/)
	: CaplResizableDialog(CSelectAccessAgent::IDD, pParent)
{
	//{{AFX_DATA_INIT(CSelectAccessAgent)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_pLastSize.x = 0;
	m_pLastSize.y = 0;
	m_ptMinTrackSize.x = 0;
	m_ptMinTrackSize.y = 0;
	m_non_groupe_item  = 0;
	m_data = 0;
}


void CSelectAccessAgent::DoDataExchange(CDataExchange* pDX)
{
	CaplResizableDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSelectAccessAgent)
	DDX_Control(pDX, IDC_STATIC_1, m_CtrlStatic1);
	DDX_Control(pDX, IDC_ADD_SA, m_CtrlAdd);
	DDX_Control(pDX, IDCANCEL, m_CtrlCancel);
	DDX_Control(pDX, IDC_COMBO_ACCESS, m_CtrlCmbAccess);
	DDX_Control(pDX, IDC_TREE_ACCESS_AGENTS, m_TreeAccessAgents);
	DDX_Control(pDX, IDC_BUTTON4_FBEG, m_btnFBegin);
	DDX_Control(pDX, IDC_BUTTON3_FBACK, m_btnFBack);
	DDX_Control(pDX, IDC_BUTTON2_FFORW, m_btnFForward);
	DDX_Control(pDX, IDC_EDIT1_FVAL, m_edFindStr);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CSelectAccessAgent, CaplResizableDialog)
	//{{AFX_MSG_MAP(CSelectAccessAgent)
	ON_NOTIFY(NM_CLICK, IDC_TREE_ACCESS_AGENTS, OnClickTreeAccessAgents)
	ON_BN_CLICKED(IDC_ADD_SA, OnAddSa)
	//}}AFX_MSG_MAP
	//ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipShow)
	ON_BN_CLICKED(IDC_BUTTON2_FFORW, OnFindForward)
	ON_BN_CLICKED(IDC_BUTTON3_FBACK, OnFindBack)
	ON_BN_CLICKED(IDC_BUTTON4_FBEG, OnButton4Beg)


	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_ACCESS_AGENTS, &CSelectAccessAgent::OnTvnSelchangedTreeAccessAgents)
	ON_WM_TIMER()
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSelectAccessAgent message handlers


BOOL CSelectAccessAgent::OnInitDialog() 
{
	CaplResizableDialog::OnInitDialog();
	if(m_data==NULL)
	{
		EndDialog(0);
		return FALSE;
	}

	// предотвращаем потерю модальности после диалога с бочками из aplSocketTransport
	CORRECT_LOOSE_MODAL_ON_CLASS(m_data);

	ModifyStyleEx(0, WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT);   
	ModifyStyle(0, WS_MAXIMIZEBOX);   

	EnableToolTips(TRUE);
	
	// TODO: Add extra initialization here
	//BOOL res=m_TreeAccessAgents.ModifyStyle(0, LVS_SHOWSELALWAYS);

	m_CtrlCmbAccess.AddString( APL_T("Полный доступ"));
	m_CtrlCmbAccess.AddString( APL_T("Чтение-запись"));
	m_CtrlCmbAccess.AddString( APL_T("Только чтение"));
	m_CtrlCmbAccess.AddString( APL_T("Нет доступа"));


	m_CtrlCmbAccess.SetCurSel(2);
	
	AddAnchor(IDC_TREE_ACCESS_AGENTS,TOP_LEFT,BOTTOM_RIGHT);
	AddAnchor(IDC_STATIC_1,BOTTOM_LEFT);
	AddAnchor(IDC_COMBO_ACCESS,BOTTOM_LEFT,BOTTOM_RIGHT);
	AddAnchor(IDC_ADD_SA,BOTTOM_RIGHT); //-V525
	AddAnchor(IDCANCEL,BOTTOM_RIGHT);
	
	AddAnchor(IDC_STATIC_FCAP,BOTTOM_LEFT);
	AddAnchor(IDC_EDIT1_FVAL,BOTTOM_LEFT,BOTTOM_RIGHT);
	AddAnchor(IDC_BUTTON2_FFORW,BOTTOM_RIGHT);
	AddAnchor(IDC_BUTTON3_FBACK,BOTTOM_RIGHT);
	AddAnchor(IDC_BUTTON4_FBEG,BOTTOM_RIGHT);
	AddAnchor(IDC_STATIC_FIND_TREE,TOP_LEFT,BOTTOM_RIGHT);


	m_CtrlCancel.SetIcon(GetAplStdIco16(APLSTDICO_CANCEL));m_CtrlCancel.SetFlat(FALSE);
	m_CtrlAdd.SetIcon( GetAplStdIco16(APLSTDICO_OK));m_CtrlAdd.SetFlat(FALSE);
	
	m_btnFForward.SetIcon(GetAplTableIco(APL_TABLE_BOTTOM));
	m_btnFBack.SetIcon(GetAplTableIco(APL_TABLE_TOP));
	m_btnFBegin.SetIcon(GetAplTableIco(APL_TABLE_RIGHT));

	m_btnFForward.SetFlat(FALSE);
	m_btnFBack.SetFlat(FALSE);
	m_btnFBegin.SetFlat(FALSE);

	m_btnFForward.SetTooltipText( APL_T("Найти следущий (F3)"));
	m_btnFBack.SetTooltipText( APL_T("Найти предыдущий (Ctrl+F3)"));
	m_btnFBegin.SetTooltipText( APL_T("Сначала"));

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


bool CSelectAccessAgent::Attach(CaplNetStepData* data)
{
	if(data== 0)return false;
	m_data=data;
	m_data->GetEntityExtent(m_data->m_ent_apl_workgroup,m_ext_workgroup);
	m_data->GetEntityExtent(m_data->m_ent_apl_user,m_ext_user);
	return true;
}

///////// Заполняем дерево пользователей и групп
void CSelectAccessAgent::CreateTree()
{
	// Сначала присобачиваем набор картинок
	m_TreeAccessAgents.SetImageList(&imagelist,TVSIL_NORMAL);//   TVSIL_STATE);

	int i = 0,j = 0;
	m_TreeAccessAgents.DeleteAllItems();
	m_list_items_group.RemoveAll();
	m_list_items_users.RemoveAll();
	
	// Массив из значений итемов групп
	CString* pbuf = 0;
	CString buf = _T("");

	CaplAggr aggr;
	CaplInstance *inst_user = 0,*inst_group = 0;
	CaplMap map_user2group;

	// Сортируем по порядку
	CaplStr2InstMap map_group;
	for(i = 0;i<m_ext_workgroup.GetSize();i++)
	{
		m_data->GetAplUserName(m_ext_workgroup[i], buf);
		if(m_ext_workgroup[i]->GetId()==DEFAILT_ID_ADMIN_GROUP)
		{
			continue;
		}
		pbuf=new CString(buf);//*pbuf
		map_group.Add(pbuf,m_ext_workgroup[i]);
	}
	map_group.SortStr();

	HTREEITEM parent_item,cur_item;
	CaplMap group2HTREEITEM;
	int image;
	bool non_group,global_non_group = false;
	//Заносим в дерево группы юзеров
	for(i = 0;i<map_group.Size;i++)
	{
		pbuf=map_group.GetStrByIndx(i);
		inst_group=map_group.GetInstByIndx(i);
		if(inst_group->GetId()==2)
		{
			image=ICON_CUR_GROUPE;
		}
		else
		{
			image=ICON_GROUPE;
		}
		cur_item=m_TreeAccessAgents.InsertItem(*pbuf,image,image,TVI_ROOT);
		m_TreeAccessAgents.SetItemData(cur_item,(DWORD)inst_group);
		group2HTREEITEM.Add((long)inst_group,(long)cur_item);
		m_list_items_group.Add(cur_item);
	}
	group2HTREEITEM.SortIn();
	// Сортируем юзеров по группам
	for(i = 0;i<m_ext_user.GetSize();i++)
	{
		// Определяем параметры юзера
		inst_user=m_ext_user[i];
		non_group = true;
		m_data->CaplStepData::GetAttr(inst_user,m_data->m_attr_apl_user__grop,aggr);
		if(inst_user->GetId()==DEFAILT_ID_ADMIN_USER)
		{
			continue;
		}
		for(j = 0;j<aggr.GetSize();j++)
		{
			aggr.GetByIndex(j,inst_group);
			if(inst_group->GetId()==DEFAILT_ID_ADMIN_GROUP)
			{
				non_group = false;// пользователи из группы адлминов не должны отображаться в списке "без групп"
				continue;
			}
			map_user2group.Add((long)inst_group,(long)inst_user);
			non_group = false;
		}
		if(non_group)
		{
			map_user2group.Add((long)0,(long)inst_user);
			global_non_group = true;
		}

	}
	if(global_non_group)
	{
		// есть пользователи без групп
		image=ICON_NON_GROUPE_USERS;

		m_non_groupe_item=m_TreeAccessAgents.InsertItem( APL_T("Пользователи без групп"),image,image,TVI_ROOT);
		m_TreeAccessAgents.SetItemData(m_non_groupe_item,(DWORD)0);
		group2HTREEITEM.Add((long)0,(long)m_non_groupe_item);
		m_list_items_group.Add(m_non_groupe_item);

	}

	// Упорядочим по группам
	map_user2group.SortIn();

	// Заносим юзеров - каждого в каждую его группу
	for(i = 0;i<map_user2group.Size;i++)
	{
		map_group.Clear();
		inst_group=(CaplInstance*)map_user2group.Data[i].in;
		parent_item=(HTREEITEM)group2HTREEITEM.GetByIn((long)inst_group);
		do{
			inst_user=(CaplInstance*)map_user2group.Data[i].out;
			pbuf=new CString();
			m_data->GetAplUserName(inst_user,*pbuf);
			if(inst_user->GetId()==DEFAILT_ID_ADMIN_USER){
				continue;
			}
			map_group.Add(pbuf,inst_user);
			i++;
		}while(inst_group==(CaplInstance*)map_user2group.Data[i].in);

		i--;// Чтобы не пропустить юзера
		// Сортируем инстансы по имени
		map_group.SortStr();
		
		// Пошли по юзерам группы
		for(j = 0;j<map_group.Size;j++){
			pbuf=map_group.GetStrByIndx(j);
			inst_user=map_group.GetInstByIndx(j);
			if(inst_user->GetId()==1){
				image=ICON_CUR_USER;
			}else{
				image=ICON_USER;
			}
			cur_item=m_TreeAccessAgents.InsertItem(*pbuf,image,image,parent_item);
			m_TreeAccessAgents.SetItemData(cur_item,(DWORD)inst_user);
			m_list_items_users.Add(cur_item);
			
		}
	}

	
}//void CSelectAccessAgent::CreateTree(){



void CSelectAccessAgent::OnAddSa() 
{
	// TODO: Add extra validation here
	//m_ext_out_user.Clear();m_ext_out_workgroup.Clear();
	m_ext_out.Clear();
	CaplInstance* inst;

	m_res_access=(aplAccessModeType)m_CtrlCmbAccess.GetCurSel();
	int i = 0;
	for(i = 0;i<m_list_items_group.GetSize();i++){
		inst=(CaplInstance*)m_TreeAccessAgents.GetItemData(m_list_items_group.GetAt(i));
		if(inst== 0)continue;
		if(inst->GetId()==DEFAILT_ID_ADMIN_GROUP)
			continue;
		if(m_TreeAccessAgents.GetCheck(m_list_items_group.GetAt(i))){
			m_ext_out.Add(inst);
		}
	}
	for(i = 0;i<m_list_items_users.GetSize();i++){
		inst=(CaplInstance*)m_TreeAccessAgents.GetItemData(m_list_items_users.GetAt(i));
		if(inst== 0)continue;
		if(inst->GetId()==DEFAILT_ID_ADMIN_USER)
			continue;
		if(m_TreeAccessAgents.GetCheck(m_list_items_users.GetAt(i))){
			m_ext_out.Add(inst);
		}
	}
	CDialog::OnOK();
}



// ЯАИ:  Перенесено в CaplTranslateDialog
/*BOOL CSelectAccessAgent::OnToolTipShow( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
	TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
	UINT nID = pNMHDR->idFrom;
	
	if (pTTT->uFlags & TTF_IDISHWND){
		nID = ::GetDlgCtrlID((HWND)nID);
// 		CString tooltip_text;
// 		tooltip_text.LoadString(nID);
// 		pTTT->lpszText = _tcsdup(tooltip_text);
		pTTT->lpszText = MAKEINTRESOURCE(nID);
		pTTT->hinst = AfxGetResourceHandle();
		return(true);
	}
	return false;
}*/

bool spdStrIncludeAll(CString s1,const CString &s2)
{
	if(s2.GetLength()>s1.GetLength())
		return false;

	s1.MakeUpper();

	if (s1.Find(s2) >= 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}


//----------- find back -----------------------------------------------------

HTREEITEM find_last_child(CTreeCtrl *tree,HTREEITEM from)
{
	HTREEITEM ii,iin,iich;

	ii=from;

	iich=tree->GetChildItem(from);

	while(iich!=NULL)
	{
		ii=iich;

		iin=tree->GetNextSiblingItem(ii);
		while (iin!=NULL)
		{
			ii=iin;
			iin=tree->GetNextSiblingItem(ii);
		}
		iich=tree->GetChildItem(ii);
	}

	return ii;
}

HTREEITEM find_prev_item(CTreeCtrl *tree,HTREEITEM from)
{
	HTREEITEM ii=tree->GetPrevSiblingItem(from);
	if (ii==NULL)
		return tree->GetParentItem(from);		
	else
		return find_last_child(tree,ii);	
}

HTREEITEM find_item_back(CTreeCtrl *tree,CString &val,HTREEITEM from)
{
	HTREEITEM ii;

	ii=find_prev_item(tree,from);
	CaplInstance *inst;

	while (ii!=NULL)
	{
		inst = (CaplInstance *)tree->GetItemData(ii);

		if(spdStrIncludeAll(tree->GetItemText(ii),val))
			break;

		ii=find_prev_item(tree,ii);
	}
	return ii;
}

//----------- find forward -----------------------------------------------------

HTREEITEM find_next_item(CTreeCtrl *tree,HTREEITEM from)
{
	HTREEITEM re=NULL;

	re=tree->GetChildItem(from);

	if(re==NULL)
		re=tree->GetNextSiblingItem(from);

	if(re==NULL)
	{
		re=NULL;
		while(re==NULL)
		{
			re=tree->GetParentItem(from);
			if(re==NULL)
			{
				break;
			}
			from=re;
			re=tree->GetNextSiblingItem(from);
		}
	}

	return re;
}

HTREEITEM find_item_forw(CTreeCtrl *tree,CString &val,HTREEITEM from)
{
	HTREEITEM ii;

	ii=find_next_item(tree,from);
	CaplInstance *inst;

	while (ii!=NULL)
	{
		inst = (CaplInstance *)tree->GetItemData(ii);

		if(spdStrIncludeAll(tree->GetItemText(ii),val))
			break;

		ii=find_next_item(tree,ii);
	}
	return ii;
}
////////////////---------------------------
HTREEITEM find_last_item(CTreeCtrl *tree)
{
	HTREEITEM it,itn;
	if(tree->GetCount()== 0)
		return NULL;
	it=tree->GetRootItem();
	itn=tree->GetNextSiblingItem(it);
	while(itn)
	{
		it=itn;
		itn=tree->GetNextSiblingItem(it);
	}
	return find_last_child(tree,it);
}
//-----------------------------------------------------------------------------------

void CSelectAccessAgent::OnFindForward()
{
	CString str;
	m_edFindStr.GetWindowText(str);
	str.MakeUpper();

	HTREEITEM re=NULL,item=m_TreeAccessAgents.GetSelectedItem();
	HTREEITEM roo=m_TreeAccessAgents.GetRootItem();
	if(!roo) return;
	HTREEITEM olditem=item;
	CaplInstance *inst;

	if(item==NULL)
	{
		inst = (CaplInstance *)m_TreeAccessAgents.GetItemData(roo);
		if(spdStrIncludeAll(m_TreeAccessAgents.GetItemText(roo),str))
		{
			m_TreeAccessAgents.EnsureVisible(roo);
			m_TreeAccessAgents.SelectItem(roo);
			return;
		}
		else
			olditem=item=roo;
	}

	re=find_item_forw(&m_TreeAccessAgents,str,item);

	if(re!=NULL)
	{	
		m_TreeAccessAgents.SelectItem(re);
		m_TreeAccessAgents.EnsureVisible(re);
	}
	else
	{
		item=roo;
		inst = (CaplInstance *)m_TreeAccessAgents.GetItemData(item);
		if(spdStrIncludeAll(m_TreeAccessAgents.GetItemText(item),str))
		{
			m_TreeAccessAgents.SelectItem(item);
			m_TreeAccessAgents.EnsureVisible(item);
			if(item==olditem)
				AfxMessageBox( APL_T("Не найдено."));
			return;
		}
		re=find_item_forw(&m_TreeAccessAgents,str,item);
		if(re!=NULL)
		{	
			m_TreeAccessAgents.SelectItem(re);
			m_TreeAccessAgents.EnsureVisible(re);
			if(re==olditem)
				AfxMessageBox( APL_T("Не найдено."));
		}
		else
			AfxMessageBox( APL_T("Не найдено."));
	}
}

void CSelectAccessAgent::OnFindBack()
{
	CString str;
	m_edFindStr.GetWindowText(str);
	str.MakeUpper();
	HTREEITEM re=NULL,item=m_TreeAccessAgents.GetSelectedItem();
	HTREEITEM roo=m_TreeAccessAgents.GetRootItem();
	if(!roo) return;
	HTREEITEM olditem=item;
	CaplInstance *inst;

	if(item==NULL)
	{	
		inst = (CaplInstance *)m_TreeAccessAgents.GetItemData(roo);
		if(spdStrIncludeAll(m_TreeAccessAgents.GetItemText(roo),str))
		{
			m_TreeAccessAgents.SelectItem(roo);
			m_TreeAccessAgents.EnsureVisible(roo);
			return;
		}
		else
			olditem=item=roo;
	}

	re=find_item_back(&m_TreeAccessAgents,str,item);

	if(re!=NULL)
	{
		m_TreeAccessAgents.SelectItem(re);
		m_TreeAccessAgents.EnsureVisible(re);
	}
	else
	{

		item=find_last_item(&m_TreeAccessAgents);
		inst = (CaplInstance *)m_TreeAccessAgents.GetItemData(item);
		if(spdStrIncludeAll(m_TreeAccessAgents.GetItemText(item),str))
		{
			m_TreeAccessAgents.SelectItem(item);
			m_TreeAccessAgents.EnsureVisible(item);
			if(item==olditem)
				AfxMessageBox( APL_T("Не найдено."));
			return;
		}
		re=find_item_back(&m_TreeAccessAgents,str,item);
		if(re!=NULL)
		{	
			m_TreeAccessAgents.SelectItem(re);
			m_TreeAccessAgents.EnsureVisible(re);
			if(re==olditem)
				AfxMessageBox( APL_T("Не найдено."));
		}
		else
			AfxMessageBox( APL_T("Не найдено."));
	}
}

void CSelectAccessAgent::OnButton4Beg() 
{
	CString str;
	m_edFindStr.GetWindowText(str);
	str.MakeUpper();
	HTREEITEM re=NULL,item=m_TreeAccessAgents.GetRootItem();
	HTREEITEM roo=m_TreeAccessAgents.GetRootItem();
	if(!roo) return;

	if(item==NULL)
	{
		return;
	}
	CaplInstance *inst = (CaplInstance *)m_TreeAccessAgents.GetItemData(roo);
	if(spdStrIncludeAll(m_TreeAccessAgents.GetItemText(roo),str))
	{
		m_TreeAccessAgents.SelectItem(roo);
		m_TreeAccessAgents.EnsureVisible(roo);
		return;
	}

	re=find_item_forw(&m_TreeAccessAgents,str,item);

	if(re!=NULL)
	{
		m_TreeAccessAgents.SelectItem(re);
		m_TreeAccessAgents.EnsureVisible(re);
	}
	else
	{
		m_TreeAccessAgents.SelectItem(roo);
		m_TreeAccessAgents.EnsureVisible(roo);
		AfxMessageBox( APL_T("Не найдено."));
	}
}
void CSelectAccessAgent::OnTvnSelchangedTreeAccessAgents(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	// TODO: Add your control notification handler code here
// 	if(m_non_groupe_item != 0)
// 	{
// 		m_TreeAccessAgents.SetCheck(m_non_groupe_item,0);
// 	}
	*pResult = 0;
}

void CSelectAccessAgent::OnClickTreeAccessAgents(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

	PostMessage(WM_TIMER,TIMER_UNCKECK,0);

	*pResult = 0;
}


void CSelectAccessAgent::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: Add your message handler code here and/or call default

	CaplResizableDialog::OnTimer(nIDEvent);

	if(nIDEvent == TIMER_UNCKECK)
	{
		if(m_non_groupe_item != 0)
		{
			m_TreeAccessAgents.SetCheck(m_non_groupe_item,0);
		}

	}
}

bool bCntrlPressedU = false;

BOOL CSelectAccessAgent::PreTranslateMessage(MSG* pMsg) 
{
	if (pMsg->message==WM_KEYDOWN)
	{
		if(pMsg->wParam==VK_CONTROL)
			bCntrlPressedU = true;
		else if(pMsg->wParam==VK_F3)
		{
			if(bCntrlPressedU)
				OnFindBack();
			else
				OnFindForward();
		}
	}
	else if (pMsg->message==WM_KEYUP)
	{
		if(pMsg->wParam==VK_CONTROL)
			bCntrlPressedU = false;
	}
	// 	else if (pMsg->message==WM_RBUTTONDOWN)
	// 	{
	// 		if(pMsg->hwnd==m_treeCtrl.m_hWnd)
	// 		{
	// 			CPoint p;
	// 			p.x = GET_X_LPARAM(pMsg->lParam); 
	// 			p.y = GET_Y_LPARAM(pMsg->lParam);
	// 
	// 			UINT flag=TVHT_ONITEM;
	// 			HTREEITEM hItem=m_treeCtrl.HitTest(p,&flag);
	// 			if(0!=hItem){ TreeContextMenu(hItem,pMsg->pt); return TRUE;}
	// 		}
	// 	}

	return CaplResizableDialog::PreTranslateMessage(pMsg);
}