// RequirementPropertiesDlg.cpp : implementation file
//

#include "stdafx.h"
#include <finder.h>
#include "RequirementPropertiesDlgEx.h"
#include "RequirementStageDlg.h"

// CRequirementPropertiesDlgEx dialog

IMPLEMENT_DYNAMIC(CRequirementPropertiesDlgEx, CRequirementPropertiesDlg)

CRequirementPropertiesDlgEx::CRequirementPropertiesDlgEx(CaplAPI *api, CaplInstance *ciReq, CaplInstance *ciParent, CWnd* pParent /*=NULL*/)
	: CRequirementPropertiesDlg(api, ciReq, ciParent, pParent, CRequirementPropertiesDlgEx::IDD)
{
	m_cfgObject = 0;
}

CRequirementPropertiesDlgEx::~CRequirementPropertiesDlgEx()
{
	
}


void CRequirementPropertiesDlgEx::InitButtons()
{
	m_addStageBtn.SetFlat(FALSE);
	m_propStageBtn.SetFlat(FALSE);
	m_delStageBtn.SetFlat(FALSE);
	m_setCfgObjBtn.SetFlat(TRUE);
	m_delCfgObjBtn.SetFlat(TRUE);
	
	m_setCfgObjBtn.SetIcon(aplGetButtonIco(APL_24_SELECT));
	m_delCfgObjBtn.SetIcon(aplGetButtonIco(APL_24_DELETE));	
	m_addStageBtn.SetIcon(aplGetButtonIco(APL_24_PLUS));
	m_propStageBtn.SetIcon(aplGetButtonIco(APL_24_PROPERTIES));
	m_delStageBtn.SetIcon(aplGetButtonIco(APL_24_DELETE));	
}

void CRequirementPropertiesDlgEx::InitList()
{
	// стиль
	ListView_SetExtendedListViewStyle(m_list.m_hWnd,
		ListView_GetExtendedListViewStyle(m_list.m_hWnd)
		| LVS_EX_UNDERLINECOLD | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

	// колонки
	CRect rect;
	m_list.GetClientRect(&rect);

	m_list.InsertFColumn(0, APL_T("Этап проверки"),			(int)(rect.Width() * 0.1));	
	m_list.InsertFColumn(1, APL_T("МОС"),					(int)(rect.Width() * 0.3));	
	m_list.InsertFColumn(2, APL_T("Вид документа"),			(int)(rect.Width() * 0.15));		
	
	m_list.DisableToolTips();
	m_list.SetReadOnly(FALSE);
	m_list.SetImageList(aplGetInstImageList());
	m_list.SetRowHeight(20);
	m_list.SetTree(0);
	m_list.DeselectIfNullRowClicked();
}

void CRequirementPropertiesDlgEx::DoDataExchange(CDataExchange* pDX)
{
	CRequirementPropertiesDlg::DoDataExchange(pDX);

	
}

void CRequirementPropertiesDlgEx::VirtualDDX(CDataExchange* pDX)
{
	DDX_Control(pDX, IDC_LIST, m_list);
	DDX_Control(pDX, IDC_ADD_STAGE, m_addStageBtn);
	DDX_Control(pDX, IDC_EDIT_STAGE, m_propStageBtn);
	DDX_Control(pDX, IDC_DEL_STAGE, m_delStageBtn);
	DDX_Control(pDX, IDC_CFG_OBJECT, m_cfgObjEdit);
	DDX_Control(pDX, IDC_CHOOSE_CFG_OBJECT, m_setCfgObjBtn);
	DDX_Control(pDX, IDC_DEL_CFG_OBJECT, m_delCfgObjBtn);
}

void CRequirementPropertiesDlgEx::AddAnchorVirtual()
{
	AddAnchor(IDC_STATIC_NOTES2, BOTTOM_LEFT);
	AddAnchor(IDC_CFG_OBJECT, BOTTOM_LEFT, BOTTOM_RIGHT);
	AddAnchor(IDC_CHOOSE_CFG_OBJECT, BOTTOM_RIGHT);
	AddAnchor(IDC_DEL_CFG_OBJECT, BOTTOM_RIGHT);
	AddAnchor(IDC_STATIC_STAGE, BOTTOM_LEFT, BOTTOM_RIGHT);
	AddAnchor(IDC_ADD_STAGE, BOTTOM_RIGHT);
	AddAnchor(IDC_EDIT_STAGE, BOTTOM_RIGHT);
	AddAnchor(IDC_DEL_STAGE, BOTTOM_RIGHT);
}

BEGIN_MESSAGE_MAP(CRequirementPropertiesDlgEx, CRequirementPropertiesDlg)
	ON_BN_CLICKED(IDC_ADD_STAGE, OnAddStage)
	ON_BN_CLICKED(IDC_EDIT_STAGE, OnBnClickedEditStage)
	ON_BN_CLICKED(IDC_DEL_STAGE, OnBnClickedDelStage)
	ON_BN_CLICKED(IDC_CHOOSE_CFG_OBJECT, OnBnClickedChooseCfgObject)
	ON_BN_CLICKED(IDC_DEL_CFG_OBJECT, OnBnClickedDelCfgObject)
END_MESSAGE_MAP()

BOOL CRequirementPropertiesDlgEx::OnInitDialog()
{
	CRequirementPropertiesDlg::OnInitDialog();

	InitButtons();
	InitList();
	AddAnchorVirtual();

	if(m_ciReq)
	{
		LoadStages();

		CaplInstance *cfgObject = 0;
		m_api->m_data.GetAttr(m_ciReq, m_api->m_req_mgr.a_req_cfg_oject, cfgObject);
		SetCfgObject(cfgObject);
	}			

	return TRUE;
}


void CRequirementPropertiesDlgEx::OnCancel()
{
	for(int i=0; i<m_newStages.Size; ++i)
		m_api->m_data.DeleteInstance(m_newStages[i], false);
	m_api->SaveChanges();

	__super::OnCancel();
}

void CRequirementPropertiesDlgEx::OnOK()
{
	OK();

	// удаляем связи с документами
	for(int i=0; i<m_deletedDocRefs.Size; ++i)
		m_api->m_data.DeleteInstance(m_deletedDocRefs[i], false);

	// сохраняем этапы
	HFROW row = m_list.GetNextFRow(FL_ROOT, FL_FIRST_CHILD);
	while(row)
	{
		CaplInstance *reqStage = reinterpret_cast<CaplInstance*>(m_list.GetFItemData(row, 0));
		m_api->m_data.PutAttr(reqStage, m_api->m_req_mgr.a_req_stage_requirement, m_ciReq);

		// документы этапов
		StageDocMap::iterator it = m_stageDocuments.find(reqStage);
		if(it != m_stageDocuments.end())
		{
			DocsSet &vec = it->second;
			for(DocsSet::iterator DocIt=vec.begin(); DocIt!=vec.end(); ++DocIt)
			{
				if(m_api->m_data.IsKindOf(*DocIt, m_api->m_doc_mgr.e_doc))
					m_api->m_doc_mgr.CreateAssociation(reqStage, *DocIt, 0, 0, APL_DOCUMENT_RELATION, false);
			}
		}

		row = m_list.GetNextFRow(row, FL_NEXT);
	}

	// объект конфигурации
	m_api->m_data.PutAttr(m_ciReq, m_api->m_req_mgr.a_req_cfg_oject, m_cfgObject);

	m_api->SaveChanges();
	CaplResizableDialog::OnOK();
}

void CRequirementPropertiesDlgEx::OnAddStage()
{
	aplExtent emptyDocuments;
	CRequirementStageDlg dlg(m_api, 0, emptyDocuments);

	if(dlg.DoModal() == IDOK)
	{
		for(int i=0; i<emptyDocuments.Size; ++i)
			m_stageDocuments[dlg.m_reqStage].insert(emptyDocuments[i]);

		AddStage(dlg.m_reqStage, 0);
		m_newStages.Add(dlg.m_reqStage);
	}
}

void CRequirementPropertiesDlgEx::LoadStages()
{
	if(0 == m_ciReq)
		return;

	// поищем в БД
	CaplFinder ff(DEF_SOURCE);

	int index = ff.CreateExt(m_api->m_req_mgr.e_requirement_stage);
	ff.AddAttr(index, m_api->m_req_mgr.a_req_stage_requirement, m_ciReq, CaplFinder::cmpEqual);

	int refIndex = ff.CreateExt(m_api->m_doc_mgr.e_apl_doc_ref);
	ff.AddAttr(refIndex, m_api->m_doc_mgr.a_apl_doc_ref_item, index);

	ff.SetResultGrpType(CaplFinder::grpOR);
	ff.AddToResult(index);
	ff.AddToResult(refIndex);
	ff.Find(m_api->m_data, true, false, false, true, true);

	// сгруппируем
	aplExtent stages, documents, projects;
	m_stageDocuments.clear();

	for(int i=0; i<ff.m_innerExtent.Size; ++i)
	{
		if(m_api->m_data.IsKindOf(ff.m_innerExtent[i], m_api->m_doc_mgr.e_apl_doc_ref))
		{
			CaplInstance *reqStage = 0, *document;
			m_api->m_data.GetAttr(ff.m_innerExtent[i], m_api->m_doc_mgr.a_apl_doc_ref_item, reqStage);
			m_api->m_data.GetAttr(ff.m_innerExtent[i], m_api->m_doc_mgr.a_apl_doc_ref_doc, document);

			documents.Add(document);
			m_stageDocuments[reqStage].insert(ff.m_innerExtent[i]);
		}
		else if(m_api->m_data.IsKindOf(ff.m_innerExtent[i], m_api->m_req_mgr.e_requirement_stage))
		{
			CaplInstance *project = 0;
			m_api->m_data.GetAttr(ff.m_innerExtent[i], m_api->m_req_mgr.a_req_stage_project, project);

			stages.Add(ff.m_innerExtent[i]);
			projects.Add(project);
		}
	}
	m_api->m_doc_mgr.LoadDocInfo(documents);
	m_api->m_project_mgr->LoadProjectInfo(projects);

	// покажем
	for(int i=0; i<stages.Size; ++i)
		AddStage(stages[i], 0);
}

void CRequirementPropertiesDlgEx::AddStage(CaplInstance *reqStage, HFROW row)
{
	if(0 == row)
	{		
		row = m_list.InsertFRow(FL_ROOT, FL_LAST, _T(""), ICON_REQUIMENT);
		m_list.SetFItemData(row, 0, reinterpret_cast<DWORD>(reqStage));
	}
	else
	{
		// очищаем дочерние элементы - документы		
		HFROW childRow = m_list.GetNextFRow(row, FL_FIRST_CHILD);
		while(childRow)
		{
			HFROW tmpRow = m_list.GetNextFRow(childRow, FL_NEXT);
			m_list.DeleteFRow(childRow);
			childRow = tmpRow;
		}
	}

	CString mos;
	m_api->m_data.GetAttr(reqStage, m_api->m_req_mgr.a_req_stage_mos, mos);

	CaplInstance *project = 0;
	m_api->m_data.GetAttr(reqStage, m_api->m_req_mgr.a_req_stage_project, project);

	m_list.SetFItemText(row, 0, m_api->GetItemName(project));
	m_list.SetFItemText(row, 1, mos);

	// документы
	StageDocMap::iterator it = m_stageDocuments.find(reqStage);
	if(it != m_stageDocuments.end())
	{
		DocsSet &vec = it->second;
		for(DocsSet::iterator DocIt=vec.begin(); DocIt!=vec.end(); ++DocIt)
		{
			HFROW docRow = m_list.InsertFRow(row, FL_LAST, "", ICON_DOCUMENT);
			m_list.SetFItemData(docRow, 0, reinterpret_cast<DWORD>(*DocIt));
			
			CString docId;
			CaplInstance *document = 0;

			if(m_api->m_data.IsKindOf(*DocIt, m_api->m_doc_mgr.e_apl_doc_ref))
			{
				m_api->m_data.GetAttr(*DocIt, m_api->m_doc_mgr.a_apl_doc_ref_doc, document);
			}
			else
			{
				document = *DocIt;
			}
			
			CaplInstance *docType = 0;
			if(document)
			{
				m_api->m_data.GetAttr(document, m_api->m_doc_mgr.a_doc_kind, docType);
				
				if(docType)
				{
					CString docTypeName;
					m_api->m_data.GetAttr(docType, m_api->m_doc_mgr.a_dt_pdt, docTypeName);
					m_list.SetFItemText(docRow, 2, docTypeName);
				}
			}
		}

		m_list.Collapse(row, FALSE);
	}
}

void CRequirementPropertiesDlgEx::SetCfgObject(CaplInstance *object)
{
	CString name;
	m_cfgObject = object;

	if(m_cfgObject)
		name = m_api->GetItemName(m_cfgObject);

	m_cfgObjEdit.SetWindowText(name);
}

void CRequirementPropertiesDlgEx::OnBnClickedDelStage()
{
	HFROW row = m_list.GetSelectedFRow();
	if(0 == row)
		return;

	CaplInstance *stage = reinterpret_cast<CaplInstance*>(m_list.GetFItemData(row, 0));
	if(0 == stage)
		return;

	if(false == m_api->m_data.IsKindOf(stage, m_api->m_req_mgr.e_requirement_stage))
		return;

	if(AfxMessageBox(APL_T("Удалить объект?"), MB_ICONSTOP|MB_YESNO) == IDYES)
	{
		m_list.DeleteFRow(row);
		m_deletedDocRefs.Add(stage);
	}
}

void CRequirementPropertiesDlgEx::OnBnClickedEditStage()
{
	HFROW row = m_list.GetSelectedFRow();
	if(0 == row)
		return;

	CaplInstance *stage = reinterpret_cast<CaplInstance*>(m_list.GetFItemData(row, 0));
	if(0 == stage)
		return;

	if(false == m_api->m_data.IsKindOf(stage, m_api->m_req_mgr.e_requirement_stage))
		return;

	// получим документы
	aplExtent documents;
	StageDocMap::iterator it = m_stageDocuments.find(stage);
	if(it != m_stageDocuments.end())
	{
		DocsSet &vec = it->second;
		for(DocsSet::iterator DocIt=vec.begin(); DocIt!=vec.end(); ++DocIt)
		{
			CaplInstance *document = 0;
			if(m_api->m_data.IsKindOf(*DocIt, m_api->m_doc_mgr.e_apl_doc_ref))
			{
				m_api->m_data.GetAttr(*DocIt, m_api->m_doc_mgr.a_apl_doc_ref_doc, document);
			}
			else
			{
				document = *DocIt;
			}

			documents.Add(document);
		}
	}

	CRequirementStageDlg dlg(m_api, stage, documents);
	if(dlg.DoModal() == IDOK)
	{
		// обновим карту с документами
		if(it != m_stageDocuments.end())
		{
			// если какие-то документы удалили
			DocsSet &vec = it->second;
			for(DocsSet::iterator DocIt=vec.begin(); DocIt!=vec.end(); )
			{
				CaplInstance *document = 0;
				if(m_api->m_data.IsKindOf(*DocIt, m_api->m_doc_mgr.e_apl_doc_ref))
				{
					m_api->m_data.GetAttr(*DocIt, m_api->m_doc_mgr.a_apl_doc_ref_doc, document);
				}
				else
				{
					document = *DocIt;
				}
				
				int index = documents.Find(document);
				if(index == -1)
				{
					m_deletedDocRefs.Add(*DocIt);
					DocIt = vec.erase(DocIt);
				}
				else
				{
					documents.Remove(index);
					DocIt++;
				}
			}			
		}		

		// новые документы
		for(int i=0; i<documents.Size; ++i)
			m_stageDocuments[stage].insert(documents[i]);

		AddStage(stage, row);
	}
}

CaplInstance* CRequirementPropertiesDlgEx::GetSystemOfOptions()
{
	CString sSystemName;
	m_api->m_options_mgr.GetOptionValueBN(_T("Конфигуратор\\Справочник опционов\\Наименование"), sSystemName, _T("Справочник опционов"));
	
	CaplInstance* op_system= m_api->m_classifier_mgr.GetClassifierSystemBN(sSystemName,true);
	if(!op_system)
	{
		op_system = m_api->m_classifier_mgr.SelectInstance(APL_MODE_SELECT_CLASSIF_SYSTEM,APL_T("Выберите справочник опционов"));
		if (!op_system)
			return NULL;

		CString sName;
		m_api->m_data.GetAttr(op_system, m_api->m_classifier_mgr.a_apl_classifier_system_name, sName);
		m_api->m_options_mgr.CreateOption(_T("Конфигуратор\\Справочник опционов\\Наименование"), sName);
	}

	return op_system;
}

void CRequirementPropertiesDlgEx::OnBnClickedChooseCfgObject()
{
	aplExtent rootObjects;
	CaplInstance *system = GetSystemOfOptions();

	if(system)
		rootObjects.Add(system);
	
	SetCfgObject(m_api->m_classifier_mgr.SelectInstance(APL_MODE_SELECT_CLASSIF_ELEMENT, 0, &rootObjects));
}

void CRequirementPropertiesDlgEx::OnBnClickedDelCfgObject()
{
	SetCfgObject(NULL);
}
