// DlgAccessPatterns.cpp : implementation file
//

#include "stdafx.h"
#include "resource.h"
#include "DlgAccessPatterns.h"
#include "DlgAccessPatternProp.h"
#include "TransportSocketClient.h"

//#define IDC_ADD			1
//#define IDC_DELETE		2
//#define IDC_CHANGE		3

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

extern CImageList imagelist_exclam;

/** Отображает таблицу всех шаблонов доступа; позволяет создавать, изменять, удалять шаблоны доступа
	@param api класс базы данных*/
void AFX_EXT_API EditAccessPatternC(LPVOID lpParameter,bool ( *IsUsed)(CString &, CString &),double add_param)
{
	CaplNetStepData *data = (CaplNetStepData *) lpParameter;

	if(data== 0) return;
	if((int)IsUsed==-1)
	{
		int a = 0;
		memcpy((BYTE*)(data->m_AplTransport->m_tmp_buf.GetBuffer())+4,&add_param,8);
		return;
	}
		

	aplExtent ext_usr;
	data->LoadAllUsers(ext_usr);

	CaplSetResourceHandle res_handle(module_inst);
	CDlgAccessPatterns dlg;
	dlg.m_data=data;
	dlg.m_IsUsed=IsUsed;
	//dlg.m_add_param = add_param;
	dlg.DoModal();

}

/** Отображает таблицу всех шаблонов доступа; позволяет выбрать шаблон доступа
	@param api класс базы данных
	@param curr_pattern текущий выделенный шаблон доступа
	@return выбранный шаблон доступа или 0 если шаблон не был выбран (нажата кнопка Cancel)*/
CaplInstance AFX_EXT_API *SelectAccessPatternC(CaplNetStepData *data, CaplInstance *curr_pattern, bool *bPressOk)
{
	CaplInstance* ret_val = curr_pattern;
	if (bPressOk)
		*bPressOk = false;
	if(data== 0) return 0;

	aplExtent ext_usr;
	data->LoadAllUsers(ext_usr);

	CaplSetResourceHandle res_handle(module_inst);
	CDlgAccessPatterns dlg;
	dlg.m_data = data;
	dlg.m_curr_pattern = curr_pattern;
	dlg.m_mode = _T("select");
	if(dlg.DoModal()==IDOK)
	{
		ret_val=dlg.m_curr_pattern;
		if (bPressOk)
			*bPressOk = true;
	}

	return ret_val;
}



/////////////////////////////////////////////////////////////////////////////
// CDlgAccessPatterns dialog


CDlgAccessPatterns::CDlgAccessPatterns(CWnd* pParent /*=NULL*/)
	: CaplResizableDialog(CDlgAccessPatterns::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDlgAccessPatterns)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_data = 0;
	m_curr_pattern = 0;
	m_mode = _T("create");
	m_list.SetUniqueName(_T("APLUserAdmin::CDlgAccessPatterns"));
	m_RO = false;
	m_show_base_patterns = false;

}


void CDlgAccessPatterns::DoDataExchange(CDataExchange* pDX)
{
	CaplResizableDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDlgAccessPatterns)
	DDX_Control(pDX, IDOK, m_BtnOk);
	DDX_Control(pDX, IDCANCEL, m_BtnCancel);
	DDX_Control(pDX, IDC_BTN_PROP, m_BtnProp);
	DDX_Control(pDX, IDC_BTN_DEL, m_BtnDel);
	DDX_Control(pDX, IDC_BTN_ADD, m_BtnAdd);
	DDX_Control(pDX, IDC_LIST_PATTERN_ST, m_st_list);
	//}}AFX_DATA_MAP
	DDX_Control(pDX, IDC_STATIC_CAPTION, m_Caption);
}


BEGIN_MESSAGE_MAP(CDlgAccessPatterns, CaplResizableDialog)
	//{{AFX_MSG_MAP(CDlgAccessPatterns)
	ON_BN_CLICKED(IDC_BTN_ADD, OnBtnAdd)
	ON_BN_CLICKED(IDC_BTN_DEL, OnBtnDel)
	ON_BN_CLICKED(IDC_BTN_PROP, OnBtnProp)
	ON_NOTIFY(NM_RCLICK, IDC_LIST_PATTERN, OnRclickList)
	ON_NOTIFY(NM_DBLCLK, IDC_LIST_PATTERN, OnDblclkList)
	ON_NOTIFY(NM_CLICK, IDC_LIST_PATTERN, OnClkList)
	//}}AFX_MSG_MAP
	ON_WM_CTLCOLOR()
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CDlgAccessPatterns message handlers

BOOL CDlgAccessPatterns::OnInitDialog() 
{
	CaplResizableDialog::OnInitDialog();

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

	if(m_data== 0)
	{
		EndDialog(IDCANCEL);
		return FALSE;
	}
	// предотвращаем потерю модальности после диалога с бочками из aplSocketTransport
	CORRECT_LOOSE_MODAL_ON_CLASS(m_data);

	short state=GetKeyState(VK_MENU);
	if((state & 0xff00) != 0)
	{
		m_show_base_patterns = true;
	}


	// TODO: Add extra initialization here
//	m_btn_run.SetIcon(GetAplTableIco(APL_TABLE_RUN));
//	m_btn_cancel.SetIcon(GetAplStdIco16(APLSTDICO_CANCEL));

	m_BtnProp.SetIcon(GetAplTableIco(APL_TABLE_PROP));
	m_BtnDel.SetIcon(GetAplTableIco(APL_TABLE_DEL));
	m_BtnAdd.SetIcon(GetAplTableIco(APL_TABLE_NEW));
	m_BtnCancel.SetIcon(GetAplStdIco16(APLSTDICO_CANCEL));
	m_BtnCancel.SetFlat(FALSE);

	m_BtnOk.SetIcon(GetAplStdIco16(APLSTDICO_OK));
	m_BtnOk.SetFlat(FALSE);

	CRect rect;
	//RECT rect={5,5,10,10};
	m_list.Create(WS_VISIBLE|WS_CHILD|WS_BORDER|LVS_SHOWSELALWAYS|LVS_SINGLESEL,rect,this,IDC_LIST_PATTERN);
	m_list.SetImageList(&imagelist_exclam, LVSIL_SMALL); 

	m_st_list.GetWindowRect(&rect);
	ScreenToClient(&rect);
	m_list.MoveWindow(&rect);
	
	ListView_SetExtendedListViewStyle(m_list.m_hWnd,
		ListView_GetExtendedListViewStyle(m_list.m_hWnd)
		|LVS_EX_UNDERLINECOLD |LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);


	AddAnchor(IDC_BTN_ADD,TOP_RIGHT);
	AddAnchor(IDC_BTN_DEL,TOP_RIGHT);
	AddAnchor(IDC_BTN_PROP,TOP_RIGHT);
	
	AddAnchor(IDC_LIST_PATTERN,TOP_LEFT,BOTTOM_RIGHT);
	AddAnchor(IDC_STATIC_CAPTION,TOP_LEFT,TOP_RIGHT);

	AddAnchor(IDOK,BOTTOM_RIGHT);
	AddAnchor(IDCANCEL,BOTTOM_RIGHT);
	
	GetWindowRect(rect);
	
	m_list.DeleteAllColumns();
	m_list.InsertColumn(0, APL_T("Имя шаблона"),LVCFMT_LEFT,rect.Width()*5/20);
	m_list.InsertColumn(1, APL_T("Описание шаблона"),LVCFMT_LEFT,rect.Width()*11/20);
	m_list.InsertColumn(2, APL_T("Подстановочные пользователи/группы"),LVCFMT_LEFT,rect.Width()*2/20);
	if(m_show_base_patterns)
		m_list.InsertColumn(3, APL_T("Шаблон"),LVCFMT_LEFT,rect.Width()*10/20);

	CaplLoadData ld(m_data,DEF_SOURCE);
	ld.AddQuery( _T('e'),  0, m_data->m_ent_apl_access_pattern,0, true,true);
	if (!ld.LoadEx(true,0, APL_T("Чтение шаблонов доступа")))
	{
		if(m_data->GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS)
		{
			AfxMessageBox( APL_T("Ошибка чтения данных!"),MB_OK|MB_ICONSTOP);
		}
	}
	m_data->GetEntityExtent(m_data->m_ent_apl_access_pattern,m_ext);
	
	int i,pos,active_pos=m_ext.GetSize();
	bool is_temp_users;
	CaplInstance* inst;
	CString pattern_src,pattern_rus,name;
	CString all_errors = _T(""),errors;
	aplUsers access_table;
	LVITEM LVItem;
	LVItem.iSubItem = 0;
	LVItem.mask=LVIF_IMAGE;

	if(!m_data->TemporaryCurrUsersCreate()) return FALSE;
	for(i = 0;i<m_ext.GetSize();i++)
	{
		inst=m_ext.GetAt(i);
		if(inst== 0)continue;
		if(inst->GetType()== 0)continue;
		m_data->GetAttr(inst,m_data->m_attr_apl_acc_pat__name,name);
		m_data->GetAttr(inst,m_data->m_attr_apl_acc_pat__pattern,pattern_src);


		if(!m_data->ParseAccessStringPattern(pattern_src,access_table,&errors))
		{
			all_errors+= APL_T("\r\nШаблон: ") + name + APL_T(" Ошибки: ") + errors;
		}
		m_data->PrintAccessStringPattern(access_table, pattern_rus, true, &is_temp_users);
		if(errors != _T(""))
		{
			name += APL_T(" (Ошибки разбора!)");
			LVItem.iImage = 1;
			m_list_missed.Add(inst);
		}else{
			LVItem.iImage = 0;

		}
		pos=m_list.InsertItem(i,name);
		m_list.SetItemData(pos,(DWORD)inst);
		LVItem.iItem=pos;
		m_list.SetItem(&LVItem);

		m_list.SetItemText(pos,1,pattern_rus);
		if(m_mode == _T("select") || m_mode == _T("select_t"))
		{
			if(inst==m_curr_pattern)
			{
				active_pos=pos;
			}
		}

		if(is_temp_users)
		{
			m_list.SetItemText(pos,2,_T("+"));
			if(m_mode == _T("select_t") )
				m_list.SetItemDisabled(pos);
		}
		if(m_show_base_patterns)
		{
			m_list.SetItemText(pos,3,pattern_src);
		}
	}
	if(m_mode == _T("select") || m_mode == _T("select_t"))
	{
		pos=m_list.InsertItem(i, APL_T("<Шаблон доступа не задан>"));
		m_list.SetItemData(pos,(DWORD)0);
		SetWindowText(APL_T("Выбор шаблона доступа"));
	}
	else if(!m_data->IsAdmin())
	{
		m_RO = true;
		AfxMessageBox(APL_T("Текущий пользователь не является администратором. Диалог работает в режиме просмотра шаблонов доступа"));
	}

	m_data->TemporaryCurrUsersDelete();

	if(m_mode ==_T("select") || m_mode == _T("select_t"))
	{
		m_BtnDel.EnableWindow(FALSE);
		m_BtnAdd.EnableWindow(FALSE);
	}	
	else if(m_RO)
	{
		m_BtnDel.EnableWindow(FALSE);
		m_BtnAdd.EnableWindow(FALSE);
		m_BtnOk.ShowWindow(SW_HIDE);
	}
	else if(m_mode == _T("create"))
	{
		CRect rect;
		m_BtnCancel.ShowWindow(SW_HIDE);
		m_BtnCancel.GetWindowRect(&rect);
		ScreenToClient(&rect);
		m_BtnOk.MoveWindow(&rect);
	}

	m_list.SetItemState(active_pos,LVIS_SELECTED| LVIS_FOCUSED,-1);

	
	m_list.SetFocus();
	m_list.SetForegroundWindow();
	
	if(all_errors != _T(""))
	{
		m_Caption.SetWindowText( APL_T("При разборе шаблонов возникли ошибки! Для исправления ошибок откройте и сохраните заново сбойные шаблоны"));
		AfxMessageBox( APL_T("При разборе шаблонов возникли ошибки: ") + all_errors + APL_T("\r\n\r\nДля исправления ошибок откройте и сохраните заново сбойные шаблоны"),MB_ICONERROR);
	}

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

void CDlgAccessPatterns::OnBtnAdd() 
{
	// TODO: Add your control notification handler code here
	CaplInstance* inst;
	int pos;
	CString pattern,name;
	CDlgAccessPatternProp dlg;
	if(m_mode ==_T("select") || m_mode == _T("select_t") || m_RO) return;

	dlg.m_data=m_data;
	if(dlg.DoModal() == IDOK)
	{
		inst = m_data->CreateInstance(m_data->m_ent_apl_access_pattern);
		if(inst != 0)
		{
			m_data->PutAttr(inst,m_data->m_attr_apl_acc_pat__name,dlg.m_Name);
			m_data->PutAttr(inst,m_data->m_attr_apl_acc_pat__pattern,dlg.m_pattern);
			pos=m_ext.Add(inst);
			pos=m_list.InsertItem(pos,dlg.m_Name);
			m_list.SetItemData(pos,(DWORD)inst);
			m_list.SetItemText(pos,1,dlg.m_Definition);
			if(dlg.m_is_temp_users)
				m_list.SetItemText(pos,2,_T("+"));

			m_list.SetItemState(pos, LVNI_SELECTED, LVNI_SELECTED);
		}
	}
}

void CDlgAccessPatterns::OnBtnDel() 
{
	// TODO: Add your control notification handler code here
	CaplInstance* inst;
	CString patt_name;
	CString opt_name;
	if(m_mode ==_T("select") || m_mode == _T("select_t") || m_RO) return;
	int pos= m_list.GetNextItem( -1 , LVNI_ALL | LVNI_SELECTED );
	if( pos== -1)
	{
		AfxMessageBox( APL_T("Запись не выбрана!"));
		return;
	}
	inst=(CaplInstance*)m_list.GetItemData(pos);
	if(inst== 0)
	{
		AfxMessageBox( APL_T("Нельзя удалить пустую запись!"));
		return;
	}
	// проверка - не используется ли этот шаблон в автоматическом назначении доступа
	m_data->GetAttr(inst,m_data->m_attr_apl_acc_pat__name,patt_name);
	if(inst->GetId() != 0)
	{
		if(m_IsUsed== 0)
		{
			AfxMessageBox( APL_T("Не определена функция проверки использования шаблона. Удаление заблокировано. Для удаления используйте модуль \"Настройка БД\""));
		}
		else
		{
			if(m_IsUsed(patt_name,opt_name))
			{
				AfxMessageBox( APL_T("Шаблон \'") + patt_name + APL_T("\' нельзя удалить так как он используется \n при автоматическом назначении доступа"));
				return;	
			}
		}
		// проверка - не используется ли этот шаблон в джоступе инстансов
		if(m_data->NET_IsUsedAccessPattern(inst))
		{
			AfxMessageBox( APL_T("Шаблон \'") + patt_name + APL_T("\' нельзя удалить так как он используется \n при определении доступа объектов БД "));
			return;	
		}
	}
	if(AfxMessageBox( APL_T("Вы действительно хотите удалить шаблон \'") + patt_name + _T("\'?"), MB_YESNO)==IDNO)
	{
		return;	
	}


	m_data->DeleteInstance(inst);
	m_list.DeleteItem(pos);
}

void CDlgAccessPatterns::OnBtnProp() 
{
	// TODO: Add your control notification handler code here
	CDlgAccessPatternProp dlg;
	aplUsers access_table;
	CaplInstance* inst;
	CString error;
	int pos;
	bool is_temp_users;

	dlg.m_data=m_data;
	dlg.m_ro=m_RO;
	dlg.m_show_base_patterns = m_show_base_patterns;
	if(m_mode ==_T("select") || m_mode == _T("select_t"))
	{
		dlg.m_ro = true;
	}

	pos= m_list.GetNextItem( -1 , LVNI_ALL | LVNI_SELECTED );
	if( pos== -1)
	{
		AfxMessageBox( APL_T("Запись не выбрана!"));
		return;
	}
	inst = (CaplInstance*)m_list.GetItemData(pos);
	if(inst == 0)
	{
//		AfxMessageBox("Неверные данные в записи!");
		return;
	}

	if(!m_data->TemporaryCurrUsersCreate()) return;


	m_data->GetAttr(inst,m_data->m_attr_apl_acc_pat__name,dlg.m_Name);
	m_data->GetAttr(inst,m_data->m_attr_apl_acc_pat__pattern,dlg.m_pattern);
	m_data->ParseAccessStringPattern(dlg.m_pattern,access_table,&error);
	m_data->PrintAccessStringPattern(access_table,dlg.m_Definition, true, &is_temp_users);
	
	dlg.m_inst=inst;

	if(dlg.DoModal()==IDOK)
	{
		if(inst != 0)
		{
			m_data->PutAttr(inst,m_data->m_attr_apl_acc_pat__name,dlg.m_Name);
			m_data->PutAttr(inst,m_data->m_attr_apl_acc_pat__pattern,dlg.m_pattern);
			m_list.SetItemText(pos,1,dlg.m_Definition);
			if(dlg.m_is_temp_users)
				m_list.SetItemText(pos,2,_T("+"));
			else
				m_list.SetItemText(pos,2,_T(""));
		}
	}
	if(m_data->ParseAccessStringPattern(dlg.m_pattern,access_table,&error))
	{
		LVITEM LVItem;
		LVItem.iSubItem = 0;
		LVItem.mask=LVIF_IMAGE;
		LVItem.iImage = 0;
		LVItem.iItem=pos;
		m_list.SetItem(&LVItem);
		int i;
		for(i = 0;i<m_list_missed.GetSize();i++)
		{
			if(m_list_missed[i]==inst)
			{
				m_list_missed.Remove(i);
				break;
			}
		}
	}
	else
	{
		dlg.m_Name+= APL_T(" (Ошибки разбора!)");
	}
	m_list.SetItemText(pos,0,dlg.m_Name);
	if(m_list_missed.GetSize() == 0)
	{
		m_Caption.SetWindowText(_T(""));
	}

	m_data->TemporaryCurrUsersDelete();
}

void CDlgAccessPatterns::OnOK() 
{
	// TODO: Add extra validation here
	CaplInstance *inst = 0;

	m_data->NET_SaveChanges();
	if(m_mode ==_T("select") || m_mode == _T("select_t"))
	{
		int pos= m_list.GetNextItem( -1 , LVNI_ALL | LVNI_SELECTED );
		if( pos== -1)
		{
			AfxMessageBox( APL_T("Запись не выбрана!"));
			return;
		}
		if(m_list.GetItemDisabled(pos))
		{
			AfxMessageBox( APL_T(" Шаблон включает текущего пользователя или группу текущего пользователя; такой шаблон нельзя использовать при назначении доступа на объект"));
			return;
		}

		inst=(CaplInstance*)m_list.GetItemData(pos);

	}
	m_curr_pattern = inst;
	
	CaplResizableDialog::OnOK();
}


void CDlgAccessPatterns::OnRclickList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	*pResult = 0;
	CaplMenu menu;
	CaplInstance* inst=0;
	int pos= m_list.GetNextItem( -1 , LVNI_ALL | LVNI_SELECTED );
	if(pos!=-1)inst	=(CaplInstance*)m_list.GetItemData(pos);
	
	BOOL res=menu.CreatePopupMenu();
	UINT flag_add;
	UINT flag_del;
	UINT flag_prop;
	if(m_mode ==_T("select") || m_mode == _T("select_t") || m_RO) { flag_add=MF_BYPOSITION| MF_STRING|MF_GRAYED; } else { flag_add=MF_BYPOSITION| MF_STRING;}
	if(pos== -1 || 	m_mode ==_T("select") || m_mode == _T("select_t") || m_RO){ flag_del=MF_BYPOSITION| MF_STRING|MF_GRAYED; }else{ flag_del=MF_BYPOSITION| MF_STRING;}
	if(pos== -1 || inst== 0){flag_prop=MF_BYPOSITION| MF_STRING|MF_GRAYED;}else{flag_prop=MF_BYPOSITION| MF_STRING;}

	res=menu.InsertMenu(0,flag_add ,IDC_ADD,   APL_T("Добавить"));
	res=menu.InsertMenu(1,flag_del ,IDC_DELETE, APL_T("Удалить"));
	res=menu.InsertMenu(2,flag_prop,IDC_CHANGE, APL_T("Свойства"));

	const MSG* msg;
	CPoint mouseclick;
	msg=GetCurrentMessage();
	//mouseclick - координаты клика мыши
	mouseclick=msg->pt;

	res=menu.TrackPopupMenu(TPM_LEFTALIGN|TPM_NONOTIFY|
		TPM_RIGHTBUTTON|TPM_RETURNCMD,msg->pt.x, msg->pt.y,this);
	//в зависимости от выбора строки контекстного меню :
	switch (res)
	{
	case IDC_ADD	: OnBtnAdd();      break;
	case IDC_DELETE	: OnBtnDel();	break;
	case IDC_CHANGE	: OnBtnProp();	break;
	default:break;
	}

}

void CDlgAccessPatterns::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	*pResult = 0;
	OnBtnProp();
}

void CDlgAccessPatterns::OnClkList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	*pResult = 0;
	int pos= m_list.GetNextItem( -1 , LVNI_ALL | LVNI_SELECTED );
	if(pos != -1)
		m_BtnOk.EnableWindow(m_list.GetItemDisabled(pos)?FALSE:TRUE);
}

HBRUSH CDlgAccessPatterns::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	if(pWnd->GetDlgCtrlID() == IDC_STATIC_CAPTION)
	{
		//pDC->SetBkColor(RGB(0,0,0x7F));
		pDC->SetTextColor(RGB(0xFF,0x00,0x00));
// 		pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
// 		pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
	}

	// TODO:  Change any attributes of the DC here

	// TODO:  Return a different brush if the default is not desired
	return hbr;
}

