// WhereUsedListView.cpp : implementation file
//

#include "stdafx.h"
#include "psm.h"
#include "PSMDoc.h"
#include "WhereUsedListView.h"
#include "TreeProductItem.h"
#include "aplTreeCharacteristicItem.h"

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

/////////////////////////////////////////////////////////////////////////////
// CWhereUsedListView

IMPLEMENT_DYNCREATE(CWhereUsedListView, CaplListView)

CWhereUsedListView::CWhereUsedListView()
{
	SetUniqueName(_T("CWhereUsedListView"));

	m_bLimitShowItems=true;;
	m_iMaxCountShowItems=30;
#ifdef _DEBUG
	m_iMaxCountShowItems=3;
#endif
}

CWhereUsedListView::~CWhereUsedListView()
{
}


BEGIN_MESSAGE_MAP(CWhereUsedListView, CaplListView)
	//{{AFX_MSG_MAP(CWhereUsedListView)
	ON_WM_CREATE()
	ON_WM_LBUTTONDBLCLK()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWhereUsedListView drawing

void CWhereUsedListView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CWhereUsedListView diagnostics

#ifdef _DEBUG
void CWhereUsedListView::AssertValid() const
{
	CListView::AssertValid();
}

void CWhereUsedListView::Dump(CDumpContext& dc) const
{
	CListView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CWhereUsedListView message handlers

int CWhereUsedListView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CaplListView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
    ListView_SetExtendedListViewStyle(m_hWnd,
		ListView_GetExtendedListViewStyle(m_hWnd)
                | LVS_EX_FULLROWSELECT|/*LVS_EX_GRIDLINES|*/LVS_EX_INFOTIP);

	//LIST.SetImageList(aplGetRelImageList(),LVSIL_SMALL);
	LIST.SetImageList(aplGetInstImageList(),LVSIL_SMALL);

	ResetList(FALSE);
	return 0;
}

void CWhereUsedListView::ResetList(BOOL bShowOneComumn)
{
	int nColumnCount = LIST.GetHeaderCtrl()->GetItemCount();

	if(bShowOneComumn)
	{
		if(1==nColumnCount) return;

		SaveColumnWidths();
		for (int i=0; i < nColumnCount; i++) LIST.DeleteColumn(0);

		LIST.InsertColumn(0, APL_T("Информация"),LVCFMT_LEFT,1600);
		SetUniqueName(_T("fictive")); // Для того чтобы  эта ширина не сохранялась при выходе
		return;
	}

	if(nColumnCount>2) return;

	for (int i=0; i < nColumnCount; i++) LIST.DeleteColumn(0);

	SetUniqueName(_T("CWhereUsedListView"));
	LIST.InsertColumn(0, APL_T("Обозначение"),LVCFMT_LEFT,120);
	LIST.InsertColumn(1, APL_T("Наименование"),LVCFMT_LEFT,160);
	LIST.InsertColumn(2, APL_T("Версия"),LVCFMT_LEFT,50);
	LIST.InsertColumn(3, APL_T("Количество"),LVCFMT_LEFT,50);
	LIST.InsertColumn(4, APL_T("Ед. изм."),LVCFMT_LEFT,50);
	LIST.InsertColumn(5, APL_T("Позиция"),LVCFMT_LEFT,50);// pdr.id
	LIST.InsertColumn(6, APL_T("Позиционное обозначение"),LVCFMT_LEFT,50);// asu.reference_designator
	LIST.InsertColumn(7, APL_T("Применяемость"),LVCFMT_LEFT,100);
	LIST.InsertColumn(8, APL_T("Примечание"),LVCFMT_LEFT,150);
	LoadColumnWidths();
	SetColumnNumeric(3);
	
}

void CWhereUsedListView::UpdateTreeItem(CaplTreeItem *item)
{
	//if(item==m_cur_item) return;
	m_cur_item=item;
	GetListCtrl().DeleteAllItems();
	if(item==0) return;
	
	if(item->m_type!=APL_TREE_ITEM_PRODUCT) return;
	CaplInstance *m_prd=0, *m_pdf=0,*m_val=0; 
	m_prd=((CaplProductTreeItem*)item)->m_prd;
	m_pdf=((CaplProductTreeItem*)item)->m_pdf;
	
	if(m_prd==0) return;
	if(m_pdf==0) return;
	int i,k;

	// Чтение из базы
	if(!item->m_doc_data.IsConnected()) return;

	CaplInstance *i_nauo, *i_pdf, *i_prd,*inst1;
	CString id,name,ver,buf,buf1;

	CaplAPI &m_api=m_cur_item->m_doc->m_api;
	CaplNetStepData &data=item->m_doc_data;
	CaplProductManager &prd_mgr=m_api.m_prd_mgr;


	// Предварительное определение числа элементов
	CaplAttrValue tst_values[1];
	tst_values[0].value.Set(((CaplProductTreeItem*)item)->m_pdf);
	tst_values[0].attr=prd_mgr.a_pdr_r_ted;
	
	aplExtent ext_rel0;
	StartBusy();
	data.NET_FindInstancesWithAttrValues(prd_mgr.e_pdr,1,&tst_values[0],ext_rel0,true);
	StopBusy();

	if(m_bLimitShowItems && ext_rel0.GetSize()>m_iMaxCountShowItems)
	{
		ResetList(TRUE);

		id.Format(APL_T("Найдено %i элементов. Отображение займет длительное время. Для показа всех элеменов дважды кликните на это сообщение."),ext_rel0.GetSize());
		k=LIST.InsertItem(-1,id,ICON_NOTE);
		LIST.SetItemData(k,0);
		return;
	}

	aplExtent ext_rel,ext0;

	// Настоящее чтение
	StartBusy();
	prd_mgr.WhereUsedProduct(((CaplProductTreeItem*)item)->m_pdf,ext_rel,ext0,true);
	StopBusy();

	// Определение наличия применяемости
	aplExtent ext_eff;
	CaplInstance *inst0;
	bool bHide= false;

	data.GetEntityExtent(prd_mgr.e_pd_eff, ext_eff);
	COleDateTime odt=COleDateTime::GetCurrentTime();;
	CString sStr, sEnd, sCurTime, sEffDescr;
	aplDate2String(odt, sCurTime);

	StartBusy();
	SetRedraw(FALSE);
	ResetList(FALSE);

	//Отображение
	for(i=0;i<ext_rel.GetSize();i++)
	{
		/*if(i>m_iMaxCountShowItems) 
		{
			bShowShowAll=true;
			break;
		}*/

		i_nauo=ext_rel[i];

		data.GetAttr(i_nauo, prd_mgr.a_pdr_r_ting,i_pdf);
		data.GetAttr(i_pdf, prd_mgr.a_pdf_prd,i_prd);

		int ico=m_api.GetInstIco(i_pdf);

		data.GetAttr(i_prd,prd_mgr.a_prd_id,id);
		k=LIST.InsertItem(-1,id,ico);
		LIST.SetItemData(k,(long)i_pdf);
		//LIST.SetItemText(k,1,id);

		data.GetAttr(i_prd,prd_mgr.a_prd_name,name);
		LIST.SetItemText(k,1,name);
		
		data.GetAttr(i_pdf,prd_mgr.a_pdf_id,ver);
		LIST.SetItemText(k,2,ver);

		buf=_T("");
		double count=1, count1;
		if(data.IsKindOf(i_nauo,prd_mgr.e_acu))
		{
			data.GetAttr(i_nauo, prd_mgr.a_apl_qacu_value, count);
			data.GetAttr(i_nauo, prd_mgr.a_apl_qacu_unit , inst1);

			m_api.m_charact_mgr.GetUnitName(inst1,buf);
			id = Double2Str(count);
			//id.Format(_T("%g"),count);
		}
		else if(data.IsKindOf(i_nauo,prd_mgr.e_make_from))
		{
			data.GetAttr(i_nauo,prd_mgr.a_make_from_value,count);
			data.GetAttr(i_nauo,prd_mgr.a_make_from_unit,inst1);
			m_api.m_charact_mgr.GetUnitName(inst1,buf);
			data.GetAttr(i_nauo,prd_mgr.a_make_from_derive_value,count1);
			if(count1==0) 
				id = Double2Str(count);
//				id.Format(_T("%g"),count);
			else 
				id = Double2Str(count)+_T(" / ")+Double2Str(count1);
				//id.Format(_T("%g / %g"),count,count1);
		}
		else if(data.IsKindOf(i_nauo, prd_mgr.e_design_make_from))
		{
			id=_T("");
		}
		LIST.SetItemText(k,3,id);

		//if(buf==_T("")) buf= APL_NO_T("шт.");
		LIST.SetItemText(k,4,buf);// чуть выше в buf пишется единица измерения, поэтому строки 3-4 помещяю ниже

		data.GetAttr(i_nauo, prd_mgr.a_pdr_id, buf);
		LIST.SetItemText(k,5,buf);
		if(data.IsKindOf(i_nauo,prd_mgr.e_acu))
		{
			data.GetAttr(i_nauo,prd_mgr.a_acu_ref_des,buf);
		}else{
			buf=_T("");
		}
		LIST.SetItemText(k,6,buf);
		
		bool bHasEff=false;
		bool bOnlyDateEff=true;
		bool bDateEffActual=false;
		// Проверяем применяемость
		for(int j=0;j<ext_eff.Size; j++)
		{
			CaplInstance *eff=ext_eff[j];
			data.GetAttr(eff, prd_mgr.a_pde_not_active, bHide);				
			if(bHide) continue;
			data.GetAttr(eff, prd_mgr.a_pde_usage, inst0);
			if(inst0!=i_nauo) continue;

			bHasEff=true;
			
			if(data.IsKindOf(eff, prd_mgr.e_dat_eff))
			{						
				data.GetAttr(eff, prd_mgr.a_dat_eff_start_s, sStr);
				data.GetAttr(eff, prd_mgr.a_dat_eff_end_s, sEnd);
				if(sStr==_T("19000101000000") && sEnd==_T("19010101000000")) 
				{
					//bFictiveDateEff= true;//фиктивное правило по дате
				}
				else
				{
					if((sStr.IsEmpty()||sStr<sCurTime) && (sEnd.IsEmpty()||sEnd>sCurTime)) 
						bDateEffActual=true;
				}
			}
			else bOnlyDateEff=false;
		}
		if(!bHasEff) sEffDescr=APL_T("Всегда");
		else if(!bOnlyDateEff) sEffDescr=APL_T("Есть ограничения");
		else if(bDateEffActual)sEffDescr=APL_T("Актуально"); 
		else sEffDescr=APL_T("Не актуально");

		LIST.SetItemText(k,7,sEffDescr);
	}
	//контекстные замены
	ext_rel.Clear();
	ext0.Clear();
	prd_mgr.WhereUsedAsSubstitute(m_pdf,ext_rel,ext0,true);
	for(i=0;i<ext0.GetSize();i++)
	{
		if(!ext0[i]) continue;if(!ext0[i]->GetType()) continue;if(!ext_rel[i]) continue;if(!ext_rel[i]->GetType()) continue;
		data.GetAttr(ext0[i],  prd_mgr.a_pdr_r_ting, i_pdf);
		if(!i_pdf) continue;if(!i_pdf->GetType()) continue;if(i_pdf->GetAccessmode()>aplRO) continue;
		data.GetAttr(i_pdf, prd_mgr.a_pdf_prd, i_prd);
		if(!i_prd) continue;if(!i_prd->GetType()) continue;if(i_prd->GetAccessmode()>aplRO) continue;
		
		int ico=m_api.GetInstIco(i_pdf);
		
		data.GetAttr(i_prd, prd_mgr.a_prd_id, id);

		k=LIST.InsertItem(-1,id,ico);
		LIST.SetItemData(k,(long)i_pdf);
		data.GetAttr(i_prd, prd_mgr.a_prd_name, name);
		LIST.SetItemText(k,1,name);
		data.GetAttr(i_pdf, prd_mgr.a_pdf_id, ver);
		LIST.SetItemText(k,2,ver);
		if(i>=ext_rel.GetSize()) break;

		double count=1;
		data.GetAttr(ext_rel[i],prd_mgr.a_pdf_subst_value,count);
		buf = Double2Str(count);
//		buf.Format(_T("%g"),count);
		LIST.SetItemText(k,3,buf);
		data.GetAttr(ext0[i],prd_mgr.a_pdr_id,buf);
		LIST.SetItemText(k,5,buf);
		data.GetAttr(ext0[i],prd_mgr.a_acu_ref_des,buf);
		LIST.SetItemText(k,6,buf);
		data.GetAttr(ext_rel[i],prd_mgr.a_pdf_subst_unit,inst1);
		m_api.m_charact_mgr.GetUnitName(inst1,buf);
		LIST.SetItemText(k,4,buf);
		data.GetAttr(ext0[i], prd_mgr.a_pdr_r_ted,i_pdf);
		if(i_pdf) data.GetAttr(i_pdf, prd_mgr.a_pdf_prd, i_prd);
		if(i_prd)
		{
			buf= APL_T("Примен.взамен ");
			data.GetAttr(i_prd, prd_mgr.a_prd_id ,id);
			buf+=id;
			data.GetAttr(i_pdf, prd_mgr.a_pdf_id, ver);
			if(ver!=_T(""))
			{
				buf+=_T(" : ");
				buf+=ver;
			}
			CString subst_id, buf1;
			data.GetAttr(ext_rel[i], prd_mgr.a_pdf_subst_name, subst_id);
			aplExtent ext_subst_rel,ext_subst_pdf;
			int subst_count=0;
			prd_mgr.LoadAllSubstitutes(ext0[i], ext_subst_rel, ext_subst_pdf,false);
			for(int j=0;j<ext_subst_rel.GetSize();j++)
			{
				if(!ext_subst_rel[j]) continue;if(!ext_subst_rel[j]->GetType()) continue;
				data.GetAttr(ext_subst_rel[j],prd_mgr.a_pdf_subst_name,buf1);
				data.GetAttr(ext_subst_rel[j],prd_mgr.a_pdf_subst_pdf,inst1);
				if(inst1!=m_pdf && buf1==subst_id)
				{
					data.GetAttr(inst1, prd_mgr.a_pdf_prd, i_prd);
					if(i_prd)
					{
						subst_count++;
						if(subst_count==1)	buf+= APL_T(" совместно с ");
						else buf+=_T(",");
						data.GetAttr(i_prd, prd_mgr.a_prd_id, id);
						buf+=id;
						data.GetAttr(inst1, prd_mgr.a_pdf_id ,ver);
						if(ver!=_T(""))
						{
							buf+=_T(" : ");
							buf+=ver;
						}
					}
				}
			}
			LIST.SetItemText(k,7,_T("Заменитель"));
			LIST.SetItemText(k,8,buf);
		}
		
	}

	SortColumn(m_aCombinedSortedColumns[0]);
	SortColumn(m_aCombinedSortedColumns[0]);
	SetRedraw(TRUE);
	StopBusy();
}
void CWhereUsedListView::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if(m_cur_item!=0)
	{
		if(m_cur_item->m_type==APL_TREE_ITEM_PRODUCT)
		{
			int i=LIST.HitTest(point); 
			if(i!=-1)
			{
				CaplInstance *inst=(CaplInstance *)LIST.GetItemData(i);
				if(0==inst)
				{
					// Значит надо показать всё
					m_bLimitShowItems=false;
					UpdateTreeItem(m_cur_item);
					m_bLimitShowItems=true;
				}
				else
				{
					// Отображение свойств объекта
					if(CPSMDoc::m_dbl_click_whereused_expand_tree==FALSE)
					{
						CaplProductTreeItem *doc_item=new CaplProductTreeItem(0,m_cur_item->m_doc,0,inst);
						if(doc_item!=0) 
						{
							doc_item->ShowProperties();
							m_cur_item->m_doc->m_items.Remove(m_cur_item->m_doc->m_items.Find(doc_item));
						}
					}
					else
					{
						// Раскрытие дерева
						((CaplProductTreeItem*)m_cur_item)->ShowAllParentProduct();
						HTREEITEM item1=m_cur_item->m_tree->GetChildItem(m_cur_item->m_item);
						while(item1!=0)
						{
							HTREEITEM item2=item1;
							item1=m_cur_item->m_tree->GetNextItem(item1, TVGN_NEXT);
							CaplTreeItem *item=(CaplTreeItem*)(m_cur_item->m_tree->GetItemData(item2));
							if(item==0) continue;
							if(item->m_type!=APL_TREE_ITEM_PRODUCT) continue;
							if(((CaplProductTreeItem*)item)->m_prd_item_type!=_T("parent")) continue;
							if(((CaplProductTreeItem*)item)->m_pdf!=inst) continue;
							//m_cur_item->m_tree->Select(item2,TVGN_FIRSTVISIBLE);
							m_cur_item->m_tree->SelectItem(item2);
							if(0 !=m_cur_item)
								m_cur_item->m_tree->SelectDropTarget(item2);
							return;
						}
					}
				}
			}
		}
	}	
	CListView::OnLButtonDblClk(nFlags, point);
}

LRESULT CWhereUsedListView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	if(message==((CPSMApp*)AfxGetApp())->m_view_update)
	{
		if(wParam==APL_UPDATE_TREE_ITEM)
		{
			CaplTreeItem* item = (CaplTreeItem*)lParam;
			UpdateTreeItem(item);
		}
	}
	
	return CaplListView::WindowProc(message, wParam, lParam);
}
