// PrdListView.cpp: implementation of the CPrdListView class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PrdListView.h"
#include "EffectivityView.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CPrdListView, CMultiColumnSortListView)

CPrdListView::CPrdListView()
{
	m_api=0;
	m_pdf=0;
	m_rel=0;

	m_eff_view=0;
}

CPrdListView::~CPrdListView()
{

}

BEGIN_MESSAGE_MAP(CPrdListView, CMultiColumnSortListView)
	//{{AFX_MSG_MAP(CPrdListView)
	ON_WM_MOUSEACTIVATE()
	ON_WM_MOUSEWHEEL()
	ON_WM_VSCROLL()
	ON_WM_LBUTTONDOWN()
	ON_WM_KEYDOWN()
	ON_WM_SIZE()
	ON_WM_RBUTTONDOWN()
	//}}AFX_MSG_MAP
	ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked) 
	ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)
END_MESSAGE_MAP()

void CPrdListView::OnInitialUpdate() 
{
	CMultiColumnSortListView::OnInitialUpdate();

	CListCtrl &ListCtrl = GetListCtrl();

	if(ListCtrl.GetHeaderCtrl()->GetItemCount()==0)
	{
		//задание стиля списка
		//ListCtrl.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT);
		ListCtrl.ModifyStyle(0, LVS_REPORT|LVS_SINGLESEL|LVS_SHOWSELALWAYS);

		ListView_SetExtendedListViewStyle(ListCtrl.m_hWnd,
			ListView_GetExtendedListViewStyle(ListCtrl.m_hWnd)
			|LVS_EX_UNDERLINECOLD|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
	
		if(m_rel==m_api->m_prd_mgr.e_acu)
			ListCtrl.InsertColumn(0,  APL_T("Позиция"));
		else if(m_rel==m_api->m_prd_mgr.e_make_from)
			ListCtrl.InsertColumn(0,  APL_T("Приоритет"));
		SetColumnNumeric(0);

		ListCtrl.InsertColumn(1,  APL_T("Обозначение") );
		ListCtrl.InsertColumn(2,  APL_T("Наименование"));
		ListCtrl.InsertColumn(3,  APL_T("Версия")      );
		ListCtrl.InsertColumn(4,  APL_T("Количество")  );
		SetColumnNumeric(4);
		ListCtrl.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
		ListCtrl.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);
		ListCtrl.SetColumnWidth(2, LVSCW_AUTOSIZE_USEHEADER);
		ListCtrl.SetColumnWidth(3, LVSCW_AUTOSIZE_USEHEADER);
		ListCtrl.SetColumnWidth(4, LVSCW_AUTOSIZE_USEHEADER);
	
	}
	
}

BOOL CPrdListView::PreCreateWindow(CREATESTRUCT& cs) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	return CMultiColumnSortListView::PreCreateWindow(cs);
}

void CPrdListView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
	if(!m_api) return;

}

int CPrdListView::OnMouseActivate( CWnd* pDesktopWnd, 
                                  UINT nHitTest, 
                                  UINT message )
{
  return MA_ACTIVATE;
}

void CPrdListView::RefreshSubPrdList()
{
	CListCtrl &in_prd_ctrl = GetListCtrl();
	
	in_prd_ctrl.SetRedraw(FALSE);

	if(in_prd_ctrl.GetItemCount())	
		in_prd_ctrl.DeleteAllItems();
	

	aplExtent ext0;
	m_api->m_data.GetEntityExtent(m_rel,ext0);	
	
	CaplInstance *inst1,*i_pdf,*i_prd;
	CString buf,buf0;
	for(int i=0; i<ext0.GetSize();i++)
	{
		CString buf;
		m_api->m_data.GetAttr(ext0[i],m_api->m_prd_mgr.a_pdr_r_ting,inst1);
		
		if(inst1!=m_pdf) continue;
		
		m_api->m_data.GetAttr(ext0[i],m_api->m_prd_mgr.a_pdr_r_ted,i_pdf);
		m_api->m_data.GetAttr(i_pdf,m_api->m_prd_mgr.a_pdf_prd,i_prd);
		
		if(i_prd!=0)
		{	
			if(m_api->m_data.IsKindOf(ext0[i], m_api->m_prd_mgr.e_acu))
			{
				m_api->m_data.GetAttr(ext0[i],m_api->m_prd_mgr.a_pdr_id,buf);					
			}
			else if(m_api->m_data.IsKindOf(ext0[i], m_api->m_prd_mgr.e_make_from))
			{
				int iRank;
				m_api->m_data.GetAttr(ext0[i], m_api->m_prd_mgr.a_make_from_ranking, iRank);
				buf.Format(_T("%i"), iRank);
			}
			
			int k=in_prd_ctrl.InsertItem(in_prd_ctrl.GetItemCount(),buf);
			in_prd_ctrl.SetItemData(k,(long)ext0[i]);
			
			m_api->m_data.GetAttr(i_prd,m_api->m_prd_mgr.a_prd_id,buf);
			in_prd_ctrl.SetItemText(k,1,buf);
			
			m_api->m_data.GetAttr(i_prd,m_api->m_prd_mgr.a_prd_name,buf);
			in_prd_ctrl.SetItemText(k,2,buf);
			
			m_api->m_data.GetAttr(i_pdf,m_api->m_prd_mgr.a_pdf_id,buf);
			in_prd_ctrl.SetItemText(k,3,buf);
			
			double count=1;
			buf0=_T("");
			if(m_api->m_data.IsKindOf(ext0[i],m_api->m_prd_mgr.e_qacu_nauo))
			{
				m_api->m_data.GetAttr(ext0[i],m_api->m_prd_mgr.a_apl_qacu_value,count);
				m_api->m_data.GetAttr(ext0[i],m_api->m_prd_mgr.a_apl_qacu_unit,inst1);
				m_api->m_charact_mgr.GetUnitName(inst1,buf0);
			}
			else if(m_api->m_data.IsKindOf(ext0[i],m_api->m_prd_mgr.e_make_from))
			{
				m_api->m_data.GetAttr(ext0[i],m_api->m_prd_mgr.a_make_from_value, count);
				m_api->m_data.GetAttr(ext0[i],m_api->m_prd_mgr.a_make_from_unit, inst1);
				m_api->m_charact_mgr.GetUnitName(inst1, buf0);				
			}
			
			buf.Format(_T("%g %s"),count,buf0);
			in_prd_ctrl.SetItemText(k,4,buf);
		}		
	}
	if(in_prd_ctrl.GetItemCount())
	{
		SetItemSortState(0,ASCENDING);
		SortColumn(0);
		in_prd_ctrl.SetItemState(0,LVIS_SELECTED| LVIS_FOCUSED,LVIS_SELECTED| LVIS_FOCUSED);
	}
	in_prd_ctrl.SetRedraw(TRUE);
	UpdateDiagramSource();
}

BOOL CPrdListView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	
	BOOL res=CMultiColumnSortListView::OnMouseWheel(nFlags, zDelta, pt);
	UpdateDiagramSource(APL_MODE_VISIBLE);
	return res;
}

void CPrdListView::UpdateDiagramSource(long mode)
{
	if(!m_eff_view) return;
	if(mode==APL_MODE_ALL)
	{
		UpdateEffMap();
	}
	m_eff_view->RemoveAllItems(mode);
	CListCtrl &in_prd_ctrl = GetListCtrl();
	int top_vis_index=in_prd_ctrl.GetTopIndex();
	CRect item_rect,cl_rect;
	in_prd_ctrl.GetClientRect(cl_rect);
	int i=top_vis_index;
	while(i<in_prd_ctrl.GetItemCount())
	{
		in_prd_ctrl.GetItemRect(i,item_rect,LVIR_BOUNDS);
		if(item_rect.bottom>cl_rect.bottom) 
			break;
		InsertEffItems(i,APL_MODE_VISIBLE);
		i++;
	}
	if(mode==APL_MODE_ALL)
	{
		for(i=0;i<in_prd_ctrl.GetItemCount();i++)
		{
			InsertEffItems(i,APL_MODE_ALL);
		}
	}
	OnSelChanged();
	bool b_update_calendar=false;
	if(mode==APL_MODE_ALL) b_update_calendar=true;
	m_eff_view->Update(b_update_calendar,b_update_calendar);
}

void CPrdListView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	CMultiColumnSortListView::OnVScroll(nSBCode, nPos, pScrollBar);
	UpdateDiagramSource(APL_MODE_VISIBLE);
}

BOOL CPrdListView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
{
	HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam;	
	
	if(wParam == TVN_SELCHANGED)
	{
		if(m_eff_view) 
		{
			m_eff_view->m_sel_nItem=pHDN->iItem;
			CListCtrl &in_prd_ctrl = GetListCtrl();
			in_prd_ctrl.GetItemRect(pHDN->iItem,m_eff_view->m_sel_item_rect,LVIR_BOUNDS);
			m_eff_view->Update(false);
		}
		return 0;
	}
	else if(wParam!=0)
	{
		int a=0;
	}
	
	return CMultiColumnSortListView::OnNotify(wParam, lParam, pResult);
}
void CPrdListView::InsertEffItems(int nItem, long mode)
{
	CListCtrl &in_prd_ctrl = GetListCtrl();
	CaplInstance *pdr=(CaplInstance*)in_prd_ctrl.GetItemData(nItem);
	if(!pdr) return;

	int eff_index=m_eff_map.QFindByIn((long)pdr);
	if(eff_index<0) 
	{
		InsertEffItemWithNoEff(nItem,mode);
		return;
	}
	int up_index=eff_index;
	int down_index=eff_index-1;

	bool b_eff_inserted=false;
	CaplInstance *eff_up_rel,*eff_down_rel;
	while(up_index<m_eff_map.Size)
	{
		eff_up_rel=(CaplInstance*)m_eff_map[up_index].in;
		if(eff_up_rel!=pdr) break;
		InsertEffItem(&m_eff_map[up_index],nItem,mode);
		up_index++;
	}
	while(down_index>-1)
	{
		eff_down_rel=(CaplInstance*)m_eff_map[down_index].in;
		if(eff_down_rel!=pdr) break;
		InsertEffItem(&m_eff_map[down_index],nItem, mode);
		down_index--;
	}
	return;
	
}

void CPrdListView::InsertEffItem(aplMap_element *map_item, int nItem,long mode)
{
	EffItem new_item;
	SetEffItem(new_item,nItem);

	CaplInstance *eff_inst=(CaplInstance*)map_item->out;
	new_item.m_eff=eff_inst;
	
	m_api->m_data.GetAttr(eff_inst,m_api->m_prd_mgr.a_pde_id,new_item.m_id);
	m_api->m_data.GetAttr(eff_inst,m_api->m_prd_mgr.a_pde_not_active,new_item.m_b_is_not_active);
	
	if(m_api->m_data.IsKindOf(eff_inst,m_api->m_prd_mgr.e_dat_eff))
	{
		new_item.m_eff_type=APL_EFF_DATE;
		m_api->m_data.GetAttr(eff_inst,m_api->m_prd_mgr.a_dat_eff_start_s,new_item.m_start);
		if(new_item.m_start==_T("19010101000000")) new_item.m_start=_T("");
		if(new_item.m_start==_T("19000101000000")) return;
		m_api->m_data.GetAttr(eff_inst,m_api->m_prd_mgr.a_dat_eff_end_s,new_item.m_end);
	}
	else
	if(m_api->m_data.IsKindOf(eff_inst,m_api->m_prd_mgr.e_sn_eff))
	{
		new_item.m_eff_type=APL_EFF_SN;
		m_api->m_data.GetAttr(eff_inst,m_api->m_prd_mgr.a_sn_eff_start,new_item.m_start);
		m_api->m_data.GetAttr(eff_inst,m_api->m_prd_mgr.a_sn_eff_end,new_item.m_end);
		if(new_item.m_start==_T(" ")||new_item.m_end==_T(" ")) return;
	}
	else
		return;
	m_eff_view->InsertItem(new_item,mode);	
}

void CPrdListView::SetEffItem(EffItem &new_item,int nItem)
{
	CListCtrl &in_prd_ctrl = GetListCtrl();
	CaplInstance *eff_rel=(CaplInstance*)in_prd_ctrl.GetItemData(nItem);

	m_api->m_data.GetAttr(eff_rel,m_api->m_prd_mgr.a_pdr_inner_id,new_item.m_ass_item_id);
	CString pdf_id=_T("");
	CaplInstance *pdf;
	m_api->m_data.GetAttr(eff_rel,m_api->m_prd_mgr.a_pdr_r_ted,pdf);
	if(pdf) m_api->GetItemName(pdf,pdf_id);
		
	CRect item_rect;
	in_prd_ctrl.GetItemRect(nItem,item_rect,LVIR_BOUNDS);
	item_rect.top+=2;
	item_rect.bottom-=2;
	
	new_item.m_pdf_id=pdf_id;
	new_item.m_nItem=nItem;
	new_item.m_rel=eff_rel;
	new_item.m_item_rect=item_rect;
}

void CPrdListView::InsertEffItemWithNoEff(int nItem,long mode)
{
	for(long i=0;i<=1;i++)
	{
		EffItem new_item;
		SetEffItem(new_item,nItem);
		new_item.m_eff_type=i;
		new_item.m_b_no_effectivity=true;
		m_eff_view->InsertItem(new_item,mode);	
	}
	
}

void CPrdListView::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CMultiColumnSortListView::OnHeaderClicked(pNMHDR,pResult);
	if(m_eff_view) 
	{
		UpdateDiagramSource(APL_MODE_VISIBLE);
	}
	*pResult = 0;
}

void CPrdListView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CMultiColumnSortListView::OnLButtonDown(nFlags, point);
	OnSelChanged(true);
}

void CPrdListView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	CListCtrl &in_prd_ctrl = GetListCtrl();
	int old_top_index=in_prd_ctrl.GetTopIndex();
	CMultiColumnSortListView::OnKeyDown(nChar, nRepCnt, nFlags);
	int new_top_index=in_prd_ctrl.GetTopIndex();
	if(old_top_index==new_top_index) OnSelChanged(true);
	else UpdateDiagramSource(APL_MODE_VISIBLE);
}

void CPrdListView::OnSelChanged(bool b_update)
{
	if(!m_eff_view) return;
	CListCtrl &in_prd_ctrl = GetListCtrl();
	int nItem=-1;
	POSITION pos=in_prd_ctrl.GetFirstSelectedItemPosition();
	if(pos)
		nItem=in_prd_ctrl.GetNextSelectedItem(pos);
	if(nItem<0)
		return;
	m_eff_view->m_sel_nItem=nItem;
	in_prd_ctrl.GetItemRect(nItem,m_eff_view->m_sel_item_rect,LVIR_BOUNDS);
	CaplInstance *pdr=(CaplInstance*)in_prd_ctrl.GetItemData(nItem);
	if(pdr) m_api->m_data.GetAttr(pdr,m_api->m_prd_mgr.a_pdr_inner_id,m_eff_view->m_cur_ass_item_id);
	m_eff_view->Update(false);

}

void CPrdListView::UpdateEffMap()
{
	m_eff_map.Clear();
	aplExtent ext_eff;
	m_api->m_data.GetEntityExtent(m_api->m_prd_mgr.e_pd_eff,ext_eff);
	for(int i=0;i<ext_eff.GetSize();i++)
	{	
		if(!ext_eff[i]) continue;
		//не отрисовываем неактивные правила применяемости
		bool bNotActive= false;
		m_api->m_data.GetAttr(ext_eff[i],m_api->m_prd_mgr.a_pde_not_active, bNotActive);
		if(bNotActive) continue;
		
		if(m_api->m_data.IsKindOf(ext_eff[i],m_api->m_prd_mgr.e_dat_eff))
		{	
			CString s_date;
			m_api->m_data.GetAttr(ext_eff[i],m_api->m_prd_mgr.a_dat_eff_start_s, s_date);
			//фиктивное правило применяемости
// 			if(s_date==_T("19000101000000")) continue;
		}
		
		CaplInstance *eff_rel;
		m_api->m_data.GetAttr(ext_eff[i],m_api->m_prd_mgr.a_pde_usage,eff_rel);
		if(!eff_rel) continue;
		
		m_eff_map.Add((long)eff_rel,(long)ext_eff[i]);
	}
	m_eff_map.SortIn();
}

void CPrdListView::OnSize(UINT nType, int cx, int cy) 
{
	CMultiColumnSortListView::OnSize(nType, cx, cy);
	
	UpdateDiagramSource(APL_MODE_VISIBLE);
	
}

void CPrdListView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	CMultiColumnSortListView::OnRButtonDown(nFlags, point);
	OnSelChanged(true);
}
