// CImportStructPss2IlsDlg.cpp : implementation file
//

#include "stdafx.h"
#include "CImportStructPss2IlsDlg.h"

// CImportStructPss2IlsDlg dialog

bool bLoadStructOnExpand  = true; // структура зачитывается по мере раскрытия
//bool bLoadStructOnExpand  = false;  // вся структура строится при раскрытии диалога


IMPLEMENT_DYNAMIC(CImportStructPss2IlsDlg, CaplResizableDialog)

CImportStructPss2IlsDlg::CImportStructPss2IlsDlg(CWnd* pParent /*=NULL*/)
	: CaplResizableDialog(CImportStructPss2IlsDlg::IDD, pParent)
{
	m_api=0;
	m_top_pdf=0;
	m_top_pdf_hItem=0;
	m_bFilterByDate=false;
}

CImportStructPss2IlsDlg::~CImportStructPss2IlsDlg()
{
}

void CImportStructPss2IlsDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDOK, m_ok_btn);
	DDX_Control(pDX, IDCANCEL, m_cancel_btn);
	DDX_Control(pDX, IDC_TREE_STRUCT, m_tree);
	DDX_Control(pDX, IDC_BUILD_TREE, m_build_tree_btn);
	DDX_Control(pDX, IDC_CHECK_FILTER, m_filter_check);
	DDX_Control(pDX, IDC_DATE_FILTER, m_date_filter);
	DDX_Control(pDX, IDC_FIND1, m_find_btn);
}


BEGIN_MESSAGE_MAP(CImportStructPss2IlsDlg, CaplResizableDialog)
	ON_NOTIFY(NM_CLICK, IDC_TREE_STRUCT, &CImportStructPss2IlsDlg::OnNMClickTreeStruct)
	ON_NOTIFY(NM_RCLICK, IDC_TREE_STRUCT, &CImportStructPss2IlsDlg::OnNMRClickTreeStruct)
	ON_BN_CLICKED(IDC_CHECK_FILTER, &CImportStructPss2IlsDlg::OnBnClickedCheckFilter)
	ON_BN_CLICKED(IDC_BUILD_TREE, &CImportStructPss2IlsDlg::OnBnClickedBuildTree)
	ON_BN_CLICKED(IDC_FIND1, &CImportStructPss2IlsDlg::OnBnClickedFind1)
	ON_NOTIFY(TVN_ITEMEXPANDING, IDC_TREE_STRUCT, &CImportStructPss2IlsDlg::OnTvnItemexpandingTreeStruct)
END_MESSAGE_MAP()


// CImportStructPss2IlsDlg message handlers
//***************************************************************************************
BOOL CImportStructPss2IlsDlg::OnInitDialog()
{
	CaplResizableDialog::OnInitDialog();
	if(m_api==NULL)
	{
		EndDialog(0);
		return FALSE;
	}

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

	m_ok_btn.SetFlat(FALSE);
	m_cancel_btn.SetFlat(FALSE);
	m_ok_btn.SetIcon(GetAplStdIco16(APLSTDICO_PLAY));
	m_cancel_btn.SetIcon(GetAplStdIco16(APLSTDICO_CANCEL));
	m_build_tree_btn.SetFlat(FALSE);
	m_build_tree_btn.SetIcon(GetAplTableIco(APL_TABLE_REFRESH));
	m_find_btn.SetIcon(aplGetButtonIco(APL_24_FIND));
	m_find_btn.SetFlat(FALSE);

	AddAnchor(IDC_TREE_STRUCT,TOP_LEFT,BOTTOM_RIGHT);
	AddAnchor(IDOK,BOTTOM_RIGHT);
	AddAnchor(IDCANCEL,BOTTOM_RIGHT);
	AddAnchor(IDC_FIND1,BOTTOM_LEFT);

	m_tree.SetImageList(aplGetInstImageList(),TVSIL_NORMAL);

	m_filter_check.SetCheck(TRUE);

	BuildStructTree();

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}
//***************************************************************************************
void CImportStructPss2IlsDlg::OnBnClickedBuildTree()
{
	BuildStructTree();

}

bool CImportStructPss2IlsDlg::BuildStructTree()
{
	m_tree.SetRedraw(FALSE);
	m_tree.DeleteAllItems();

	if(m_filter_check.GetCheck())
	{
		m_bFilterByDate=true;
		m_date_filter.GetTime(m_odt_filter);
	}
	else m_bFilterByDate=false;

	long wdlg=aplStartWaitDlg( APL_T("Построение структуры изделия..."));

	m_api->m_prd_mgr.LoadPrdInfo(m_top_pdf);
	m_top_pdf_hItem=InsertItemInTree(TVI_ROOT, m_top_pdf);
	m_tree.SetCheck(m_top_pdf_hItem,TRUE);

	if(bLoadStructOnExpand) m_tree.Expand(m_top_pdf_hItem,TVE_EXPAND);

	aplEndWaitDlg(wdlg);
	m_tree.SetRedraw(TRUE);

	return true;
}
//***************************************************************************************
HTREEITEM CImportStructPss2IlsDlg::InsertItemInTree(HTREEITEM hParent, CaplInstance *item)
{
	if(0==item) return 0;
	if(item->IsDeleted()) return 0;
	if(item->GetAccessmode()>aplRO) return 0;

	CString buf;
	CaplInstance *pdf=0, *nauo=0;
		
	if(m_api->m_data.IsKindOf(item,m_api->m_prd_mgr.e_pdf)) pdf=item;
	else if(m_api->m_data.IsKindOf(item,m_api->m_prd_mgr.e_nauo))
	{
		nauo=item;
		m_api->m_data.GetAttr(nauo,m_api->m_prd_mgr.a_pdr_r_ted,pdf);
		if(0==pdf) return 0;
		if(pdf->IsDeleted()) return 0;
		if(pdf->GetAccessmode()>aplRO) return 0;
	}
	if(0==pdf) return 0;

		
	m_api->m_prd_mgr.GetItemName(pdf,buf);
	int img=m_api->GetInstIco(pdf);

	HTREEITEM hItem=m_tree.InsertItem(buf,img,img,hParent);
	if(0!=nauo)	m_tree.SetItemData(hItem,(long)nauo);
	else m_tree.SetItemData(hItem,(long)pdf);

	if(bLoadStructOnExpand)
	{
		// добавляем фиктивный
		HTREEITEM hFictiveItem=m_tree.InsertItem(_T("fictive"),0,0,hItem);
		m_tree.SetItemData(hFictiveItem,(long)0);
	}
	else
	{
		// раскрываем структуру
		InsertItemStructInTree(hItem,pdf);
	}
	return hItem;
}

bool CImportStructPss2IlsDlg::InsertItemStructInTree(HTREEITEM hItem, CaplInstance *pdf)
{
	if(0==hItem) return false;
	if(0==pdf) return false;


	aplExtent ext_rel,ext_pdf;
	m_api->m_prd_mgr.LoadAllSubProduct(0, 0, pdf, ext_rel, ext_pdf, true);

	if(m_bFilterByDate)
	{
		aplExtent ext_tmp;
		m_api->m_prd_mgr.FilterlByDate(ext_rel,m_odt_filter,ext_tmp);
		ext_rel.Clear();
		ext_rel.Unique=false;
		ext_rel.Append(ext_tmp);
		ext_rel.Unique=true;
	}

	int i;
	for(i=0;i<ext_rel.GetSize();i++)
	{
		InsertItemInTree(hItem,ext_rel[i]);
	}

	if(!bLoadStructOnExpand) m_tree.Expand(hItem,TVE_EXPAND);

	return true;
}

//***************************************************************************************
void CImportStructPss2IlsDlg::OnNMClickTreeStruct(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: Add your control notification handler code here
	*pResult = 0;

	 DWORD dwpos = GetMessagePos();
	 CPoint point;
	 point.x = GET_X_LPARAM(dwpos);
	 point.y = GET_Y_LPARAM(dwpos);

	 m_tree.ScreenToClient(&point);

	// UINT flag=TVHT_ONITEM;
	 UINT flag=TVHT_ONITEMSTATEICON;
	 HTREEITEM cur_item=m_tree.HitTest(point,&flag);

	 if(0==cur_item) return;

	 if(TVHT_ONITEMSTATEICON!=flag) return;

	 *pResult = 1; // Это клик по квадратику, котороый обрабатываем вручну.

	 // Это корневой ?
	 HTREEITEM hParent=m_tree.GetParentItem(cur_item);
	 if(0==hParent || TVI_ROOT==hParent)
	 {
		 AfxMessageBox(APL_T("Изменить отметку корневого элемента нельзя!"),MB_OK|MB_ICONWARNING);
		 return;
	 }

	 if(m_tree.GetCheck(cur_item)) 
	 {
		 // проверяем - все дети не должны быть выделены
		 HTREEITEM child_item=m_tree.GetChildItem(cur_item);
		 while(child_item!=0)
		 {
			 if(m_tree.GetCheck(child_item))
			 {
				 AfxMessageBox(APL_T("Сначала снимите отметки всех дочерних элементов !"),MB_OK|MB_ICONWARNING);
				 return;
			 }
			 child_item=m_tree.GetNextItem(child_item, TVGN_NEXT);
		 }
		 // Снимаем выделение
		m_tree.SetCheck(cur_item,FALSE);

	 }
	 else
	 {
		 // проверяем - родитель должен быть выделен
		 HTREEITEM hParent=m_tree.GetParentItem(cur_item);
		 if(!m_tree.GetCheck(hParent))
		 {
			 AfxMessageBox(APL_T("Сначала отметте родительский элемент !"),MB_OK|MB_ICONWARNING);
			 return;
		 }

		 // Ставим выделение
		 m_tree.SetCheck(cur_item,TRUE);
	 }
}
//***************************************************************************************
void CImportStructPss2IlsDlg::OnNMRClickTreeStruct(NMHDR *pNMHDR, LRESULT *pResult)
{
	*pResult = 0;

	DWORD dwpos = GetMessagePos();
	CPoint point,point1;
	point.x = GET_X_LPARAM(dwpos);
	point.y = GET_Y_LPARAM(dwpos);

	point1=point;

	m_tree.ScreenToClient(&point1);

	// UINT flag=TVHT_ONITEM;
	UINT flag=TVHT_ONITEMICON;
	HTREEITEM cur_item=m_tree.HitTest(point1,&flag);
	if(0==cur_item) return; 

	m_tree.SelectItem(cur_item);
	m_tree.SelectDropTarget(cur_item);


	HTREEITEM child_item=m_tree.GetChildItem(cur_item);
	if(0==child_item) return; 

	CMenu menu;
	menu.CreatePopupMenu();
	menu.AppendMenu(MF_ENABLED|MF_STRING,ID_MENU_ORDER+1, APL_T("Отметить все дочерние"));
	if(!bLoadStructOnExpand)
		menu.AppendMenu(MF_ENABLED|MF_STRING,ID_MENU_ORDER+2, APL_T("Отметить все дочерние рекурсивно"));
	menu.AppendMenu(MF_ENABLED|MF_SEPARATOR,ID_MENU_ORDER+3, _T(""));
	//Нельзя оставлять выделенные на подуровнях, поэтому, если снимать то все
	//menu.AppendMenu(MF_ENABLED|MF_STRING,ID_MENU_ORDER+4, APL_T("Снять отметки со всех дочерних"));
	menu.AppendMenu(MF_ENABLED|MF_STRING,ID_MENU_ORDER+5, APL_T("Снять отметки со всех дочерних рекурсивно"));

	int res=menu.TrackPopupMenu(TPM_LEFTALIGN|TPM_NONOTIFY|
		TPM_RIGHTBUTTON|TPM_RETURNCMD,point.x,point.y,this);

	if(res==ID_MENU_ORDER+1)
	{
		HTREEITEM hPaten=m_tree.GetParentItem(cur_item);
		if(!m_tree.GetCheck(hPaten))
		{
			AfxMessageBox(APL_T("Сначала отметте родительский элемент !"),MB_OK|MB_ICONWARNING);
			return;
		}
		m_tree.SetCheck(cur_item,TRUE);
		SetCheckSubItems(cur_item,TRUE, false);
	}
	else if(res==ID_MENU_ORDER+2) 
	{
		HTREEITEM hPaten=m_tree.GetParentItem(cur_item);
		if(!m_tree.GetCheck(hPaten))
		{
			AfxMessageBox(APL_T("Сначала отметте родительский элемент !"),MB_OK|MB_ICONWARNING);
			return;
		}
		m_tree.SetCheck(cur_item,TRUE);
		SetCheckSubItems(cur_item,TRUE, true);
	}
	//else if(res==ID_MENU_ORDER+4) SetCheckSubItems(cur_item,FALSE, false);
	else if(res==ID_MENU_ORDER+5) SetCheckSubItems(cur_item,FALSE, true);

	return;

}
//***************************************************************************************
void CImportStructPss2IlsDlg::SetCheckSubItems(HTREEITEM hItem, BOOL bCheck, bool bRecursive)
{
	HTREEITEM child_item=m_tree.GetChildItem(hItem);
	DWORD data=m_tree.GetItemData(hItem);
	if(0==data) return; // это фиктивный, его игнорируем
	while(child_item!=0)
	{
		m_tree.SetCheck(child_item,bCheck);
		if(bRecursive) SetCheckSubItems(child_item, bCheck, true);

		child_item=m_tree.GetNextItem(child_item, TVGN_NEXT);
	}
}
//***************************************************************************************
//***************************************************************************************
//***************************************************************************************
void CImportStructPss2IlsDlg::OnOK()
{
	GetInstancesFromTree(m_top_pdf_hItem,m_ext_pdf, m_ext_nauo);
	CaplResizableDialog::OnOK();
}
//***************************************************************************************
bool CImportStructPss2IlsDlg::GetInstancesFromTree(HTREEITEM hitem, aplExtent &ext_pdf, aplExtent &ext_nauo)
{
	if(0==hitem) return false;

	if(!m_tree.GetCheck(hitem)) return false;

	CaplInstance *inst=(CaplInstance *)m_tree.GetItemData(hitem);
	if(0==inst) return false;
	if(m_api->m_data.IsKindOf(inst,m_api->m_prd_mgr.e_pdf)) ext_pdf.Add(inst);
	else if(m_api->m_data.IsKindOf(inst,m_api->m_prd_mgr.e_nauo))
	{
		ext_nauo.Add(inst);
		CaplInstance *pdf;
		m_api->m_data.GetAttr(inst,m_api->m_prd_mgr.a_pdr_r_ted,pdf);
		if(0!=pdf)  ext_pdf.Add(pdf);
	}
	else return false;

	HTREEITEM child_item=m_tree.GetChildItem(hitem);
	while(child_item!=0)
	{
		GetInstancesFromTree(child_item,ext_pdf, ext_nauo);
		child_item=m_tree.GetNextItem(child_item, TVGN_NEXT);
	}

	return true;
}

void CImportStructPss2IlsDlg::OnBnClickedCheckFilter()
{
	if(m_filter_check.GetCheck()) m_date_filter.EnableWindow(TRUE);
	else m_date_filter.EnableWindow(FALSE);
}


void CImportStructPss2IlsDlg::OnBnClickedFind1()
{
	aplShowFindInCtrl(&m_tree);
}

void CImportStructPss2IlsDlg::OnTvnItemexpandingTreeStruct(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	*pResult = 0;

	if(!bLoadStructOnExpand) return;
	
	if( TVE_EXPAND!=pNMTreeView->action) return;
	
	HTREEITEM hItem=pNMTreeView->itemNew.hItem;
	if(0==hItem) return;

	HTREEITEM hChildItem=m_tree.GetChildItem(hItem);
	if(0==hChildItem) return;

	DWORD data=m_tree.GetItemData(hChildItem);
	if(0!=data) return; // Он уже был раскрыт

	// Внутри есть фиктивный и надо раскрывать
	m_tree.DeleteItem(hChildItem);

	data=m_tree.GetItemData(hItem);
	if(0==data) return;

	CaplInstance *pdf=0, *item=(CaplInstance *)data;

	if(m_api->m_data.IsKindOf(item,m_api->m_prd_mgr.e_pdf)) pdf=item;
	else if(m_api->m_data.IsKindOf(item,m_api->m_prd_mgr.e_nauo))
	{
		m_api->m_data.GetAttr(item,m_api->m_prd_mgr.a_pdr_r_ted,pdf);
	}
	if(0==pdf) return ;
	if(pdf->IsDeleted()) return ;
	if(pdf->GetAccessmode()>aplRO) return ;

	m_tree.SetRedraw(FALSE);
	InsertItemStructInTree(hItem,pdf);
	m_tree.SetRedraw(TRUE);

	return;
}
