// 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"));
}

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);

	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);
	return 0;
}

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;
	aplExtent ext_rel,ext0;
	int i,k;

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

	CaplInstance *i_nauo, *i_pdf, *i_prd,*inst1;
	CString id,name,ver,buf,buf1;
	
	StartBusy();	
	m_cur_item->m_doc->m_api.m_prd_mgr.WhereUsedProduct(((CaplProductTreeItem*)item)->m_pdf,ext_rel,ext0,true);

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

	item->m_doc_data.GetEntityExtent(item->m_doc->m_api.m_prd_mgr.e_pd_eff, ext_eff);
	COleDateTime odt=COleDateTime::GetCurrentTime();;
	CString sStr, sEnd, sCurTime, sEffDescr;
	aplDate2String(odt, sCurTime);

	SetRedraw(FALSE);
	//Отображение
	for(i=0;i<ext_rel.Size;i++)
	{
		i_nauo=ext_rel[i];
		item->m_doc_data.GetAttrBN(i_nauo,S::relating_pd,i_pdf);
		item->m_doc_data.GetAttrBN(i_pdf,S::of_product,i_prd);

		int ico=item->m_doc->m_api.GetInstIco(i_pdf);

		item->m_doc_data.GetAttrBN(i_prd,S::id,id);
		k=LIST.InsertItem(-1,id,ico);
		LIST.SetItemData(k,(long)i_pdf);
		//LIST.SetItemText(k,1,id);

		item->m_doc_data.GetAttrBN(i_prd,S::name,name);
		LIST.SetItemText(k,1,name);
		
		item->m_doc_data.GetAttrBN(i_pdf,S::id,ver);
		LIST.SetItemText(k,2,ver);

		buf=_T("");
		double count=1, count1;
		if(item->m_doc_data.IsKindOf(i_nauo,item->m_doc->m_api.m_prd_mgr.e_acu))
		{
			item->m_doc_data.GetAttrBN(i_nauo,S::value_component,count);
			item->m_doc_data.GetAttrBN(i_nauo,S::unit_component,inst1);
			item->m_doc->m_api.m_charact_mgr.GetUnitName(inst1,buf);
			id = Double2Str(count);
			//id.Format(_T("%g"),count);
		}
		else if(item->m_doc_data.IsKindOf(i_nauo,item->m_doc->m_api.m_prd_mgr.e_make_from))
		{
			item->m_doc_data.GetAttr(i_nauo,item->m_doc->m_api.m_prd_mgr.a_make_from_value,count);
			item->m_doc_data.GetAttr(i_nauo,item->m_doc->m_api.m_prd_mgr.a_make_from_unit,inst1);
			item->m_doc->m_api.m_charact_mgr.GetUnitName(inst1,buf);
			item->m_doc_data.GetAttr(i_nauo,item->m_doc->m_api.m_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(item->m_doc_data.IsKindOf(i_nauo,item->m_doc->m_api.m_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 помещяю ниже

		item->m_doc_data.GetAttr(i_nauo,m_cur_item->m_doc->m_api.m_prd_mgr.a_pdr_id,buf);
		LIST.SetItemText(k,5,buf);
		if(item->m_doc_data.IsKindOf(i_nauo,item->m_doc->m_api.m_prd_mgr.e_acu))
		{
			item->m_doc_data.GetAttr(i_nauo,m_cur_item->m_doc->m_api.m_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];
			item->m_doc_data.GetAttr(eff, item->m_doc->m_api.m_prd_mgr.a_pde_not_active, bHide);				
			if(bHide) continue;
			item->m_doc_data.GetAttr(eff, item->m_doc->m_api.m_prd_mgr.a_pde_usage, inst0);
			if(inst0!=i_nauo) continue;

			bHasEff=true;
			
			if(item->m_doc_data.IsKindOf(eff, item->m_doc->m_api.m_prd_mgr.e_dat_eff))
			{						
				item->m_doc_data.GetAttr(eff, item->m_doc->m_api.m_prd_mgr.a_dat_eff_start_s, sStr);
				item->m_doc_data.GetAttr(eff, item->m_doc->m_api.m_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();
	m_cur_item->m_doc->m_api.m_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;
		item->m_doc_data.GetAttrBN(ext0[i],S::relating_pd,i_pdf);
		if(!i_pdf) continue;if(!i_pdf->GetType()) continue;if(i_pdf->GetAccessmode()>aplRO) continue;
		item->m_doc_data.GetAttrBN(i_pdf,S::of_product,i_prd);
		if(!i_prd) continue;if(!i_prd->GetType()) continue;if(i_prd->GetAccessmode()>aplRO) continue;
		
		int ico=item->m_doc->m_api.GetInstIco(i_pdf);
		
		item->m_doc_data.GetAttrBN(i_prd,S::id,id);
		k=LIST.InsertItem(-1,id,ico);
		LIST.SetItemData(k,(long)i_pdf);
		item->m_doc_data.GetAttrBN(i_prd,S::name,name);
		LIST.SetItemText(k,1,name);
		item->m_doc_data.GetAttrBN(i_pdf,S::id,ver);
		LIST.SetItemText(k,2,ver);
		if(i>=ext_rel.GetSize()) break;

		double count=1;
		item->m_doc_data.GetAttr(ext_rel[i],m_cur_item->m_doc->m_api.m_prd_mgr.a_pdf_subst_value,count);
		buf = Double2Str(count);
//		buf.Format(_T("%g"),count);
		LIST.SetItemText(k,3,buf);
		item->m_doc_data.GetAttr(ext0[i],m_cur_item->m_doc->m_api.m_prd_mgr.a_pdr_id,buf);
		LIST.SetItemText(k,5,buf);
		item->m_doc_data.GetAttr(ext0[i],m_cur_item->m_doc->m_api.m_prd_mgr.a_acu_ref_des,buf);
		LIST.SetItemText(k,6,buf);
		item->m_doc_data.GetAttr(ext_rel[i],m_cur_item->m_doc->m_api.m_prd_mgr.a_pdf_subst_unit,inst1);
		item->m_doc->m_api.m_charact_mgr.GetUnitName(inst1,buf);
		LIST.SetItemText(k,4,buf);
		item->m_doc_data.GetAttrBN(ext0[i],S::related_pd,i_pdf);
		if(i_pdf) item->m_doc_data.GetAttrBN(i_pdf,S::of_product,i_prd);
		if(i_prd)
		{
			buf= APL_T("Примен.взамен ");
			item->m_doc_data.GetAttrBN(i_prd,S::id,id);
			buf+=id;
			item->m_doc_data.GetAttrBN(i_pdf,S::id,ver);
			if(ver!=_T(""))
			{
				buf+=_T(" : ");
				buf+=ver;
			}
			CString subst_id,buf1;
			item->m_doc_data.GetAttr(ext_rel[i],m_cur_item->m_doc->m_api.m_prd_mgr.a_pdf_subst_name,subst_id);
			aplExtent ext_subst_rel,ext_subst_pdf;
			int subst_count=0;
			m_cur_item->m_doc->m_api.m_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;
				item->m_doc_data.GetAttr(ext_subst_rel[j],m_cur_item->m_doc->m_api.m_prd_mgr.a_pdf_subst_name,buf1);
				item->m_doc_data.GetAttr(ext_subst_rel[j],m_cur_item->m_doc->m_api.m_prd_mgr.a_pdf_subst_pdf,inst1);
				if(inst1!=m_pdf && buf1==subst_id)
				{
					item->m_doc_data.GetAttrBN(inst1,S::of_product,i_prd);
					if(i_prd)
					{
						subst_count++;
						if(subst_count==1)	buf+= APL_T(" совместно с ");
						else buf+=_T(",");
						item->m_doc_data.GetAttrBN(i_prd,S::id,id);
						buf+=id;
						item->m_doc_data.GetAttrBN(inst1,S::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(inst!=0)
				{
					// Отображение свойств объекта
					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);
}
