// plgGenSpec2.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include "SpecGenerator.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif



//Массив элементов, которые обрабатывает данная функция
CaplItemInfo functionArray []=
{
	CaplItemInfo(aplPopUp, "Product", "&Экспорт\\[0]", "", -1, -1,""),
	CaplItemInfo(aplPopUp, "Product", "&Экспорт\\[0]Генерация спецификации v2 ...", "GenSpec", -1, -1,"Генерация спецификации v2"),
//	CaplItemInfo(aplPopUp, "Product", "[0]РегПервичная", "add_reg_begin", -1, -1,""),
//	CaplItemInfo(aplPopUp, "Product", "[0]Тест", "add_test", -1, 1,""),
	CaplItemInfo(aplPopUp, APL_TREE_ITEM_CHANGE, "[2]Сгенерировать новые версии спецификаций для изменяемых сборок v2", "GenSpec4Change", -1, -1,"Сгенерировать новые версии спецификаций для изменяемых сборок v2"),

//#ifdef _DEBUG
	//CaplItemInfo(aplPopUp, "Document", "&[31]Экспорт\\", "", -1, -1,""),
	CaplItemInfo(aplPopUp, "Document", "&[31]Экспорт\\Создать удостоверяющий лист", "Make_UL", -1, -1,""),
//#endif
};

//Размер массива
int functionArraySize= sizeof(functionArray)/sizeof(CaplItemInfo);


extern HINSTANCE _hDllInstance;

//************************************************************************
__declspec(dllexport) bool GetFunctionsList(CArray<CaplItemInfo*, CaplItemInfo*> *strArray)
{
	for(int i= 0; i<functionArraySize; i++)
	{
		strArray->Add(&functionArray[i]);
	}
	return true;
}

TCHAR* _PlugInName = _T("Формирование спецификации");
TCHAR* _PlugInDescr = _T("Формирование спецификации");

__declspec (dllexport) TCHAR* GetAddInName(){ return _PlugInName;}
__declspec (dllexport) TCHAR* GetAddInDescription() {return _PlugInDescr;}


//*************************************************************************
//*************************************************************************
//*************************************************************************

__declspec (dllexport) bool GenSpec(CaplAPI* api, aplExtent& inExtent, bool bUpdateUI)
{
	if(!api || !api->m_data.IsConnected()) return false;
	if(inExtent.GetSize()<1)  return false;

	CaplInstance *pdf=inExtent[0];

	if(0==pdf)  return false;
	if(pdf->IsDeleted())  return false;
	if(!api->m_data.IsKindOf(pdf,api->m_prd_mgr.e_pdf))  return false;

	if(bUpdateUI) return true;

	if(pdf->GetAccessmode()>=aplRO)
	{
		AfxMessageBox(_T("Нет прав доступа на изменение версии изделия!"), MB_ICONSTOP);
		return false;
	}

	/* На будущее
	CString role;
	api->m_options_mgr.GetOptionValueBN( APL_NO_T("Роли\\Роль для генерации извещения об изменении"),role,"");
	if(role!="")
	{
		if(!api->m_appr_mgr.CheckPersonRole(0,role))	{AfxMessageBox(APL_T("Вы не обладаете нужной ролью!"));	return false;	}
	}*/


	CSpecGenerator spec_generator(api);

	return spec_generator.Generate(pdf,true);
}

//*************************************************************************
//*************************************************************************
//*************************************************************************
__declspec (dllexport) bool GenSpec4Change(CaplAPI* api, aplExtent& inExtent, bool bUpdateUI)
{
	if(!api || !api->m_data.IsConnected()) return false;
	if(inExtent.GetSize()<1)  return false;

	CaplInstance *change=inExtent[0];

	if(0==change)  return false;
	if(change->IsDeleted())  return false;
	if(!api->m_data.IsKindOf(change,api->m_change_mgr.e_chng))  return false;

	if(bUpdateUI) return true;

	if(change->GetAccessmode()>=aplRO)
	{
		AfxMessageBox(_T("Нет прав доступа на изменение пакета изменения!"), MB_ICONSTOP);
		return false;
	}

	// Проверка роли
	CString role;
	api->m_options_mgr.GetOptionValueBN( APL_NO_T("Роли\\Роль для генерации извещения об изменении"),role,"");
	if(role!="")
	{
		if(!api->m_appr_mgr.CheckPersonRole(0,role))	{AfxMessageBox(APL_T("Вы не обладаете нужной ролью!"));	return false;	}
	}

	// Определение сборок, для которых есть изменения
	api->m_change_mgr.LoadChangeInfo(change);

	CString buf,buf1;
	api->m_data.GetAttr(change,api->m_change_mgr.a_chng_state,buf);
	if(buf!=_T("not_applied"))
	{
		AfxMessageBox( APL_T("Изменение не находится в состоянии \"Разрабатывается\"!"), MB_OK|MB_ICONSTOP);
		return false;
	}

	aplExtent ext_chng_items,ext_asm,ext_new_ver_spec;
	int i, count_ok=0,count_false=0;
	api->m_data.GetAttr(change,api->m_change_mgr.a_chng_items,ext_chng_items);
	for(i=0;i<ext_chng_items.GetSize();i++)
	{
		CaplInstance *ch_item=ext_chng_items[i];
		if(!api->m_data.IsKindOf(ch_item,api->m_change_mgr.e_psc)) continue;

		CaplInstance *assembly;
		api->m_data.GetAttr(ch_item,api->m_change_mgr.a_psc_changed_product,assembly);

		if(api->m_data.IsKindOf(assembly,api->m_prd_mgr.e_pdf))
		{
		}
		else if(api->m_data.IsKindOf(assembly,api->m_prd_mgr.e_pdr))
		{
			api->m_data.GetAttr(assembly,api->m_prd_mgr.a_pdr_r_ting,assembly);
		}
		else continue; // такого не должно быть

		if(0!=assembly)
		{
			if(assembly->GetAccessmode()>aplRO)
			{
				AfxMessageBox(_T("Нет прав доступа к одной из сборок!"), MB_ICONSTOP);
				return false;
			}
			ext_asm.Add(assembly);
		}
	}

	if(0==ext_asm.GetSize())
	{
		AfxMessageBox(APL_T("Нет изменяемых сборочных единиц!"),MB_OK|MB_ICONWARNING);
		return true;
	}

	// Формирование новых версий спецификаций
	CSpecGenerator spec_generator(api);
	if(!spec_generator.ShowOptionsDlg(true)) return false;

	spec_generator.m_bSaveAsDocument=TRUE;
	spec_generator.m_bSetNewVersionActive=FALSE;

	for(i=0;i<ext_asm.GetSize();i++)
	{
		CaplInstance *assembly=ext_asm[i];
		CaplInstance *new_spec_rev=0;

		bool b=spec_generator.Generate(assembly,false,change,&new_spec_rev);
		
		if(b) count_ok++;
		else
		{
			count_false++;
			CString name;
			api->GetItemName(assembly,name);
			buf.Format(APL_T("Ошибка формирования спецификации для\n\n %s\n\nПродолжить?"),LPCTSTR(name));
			if(IDYES!=AfxMessageBox(buf,MB_ICONSTOP|MB_YESNO)) return false;
		}

		if(0!=new_spec_rev) ext_new_ver_spec.Add(new_spec_rev);
	}

	// Записываем правила для назначения версии активной

	// Ищем правила для изменивщихся спецификаций. Удаляем дубли.
	CaplMap map_doc_cng_items;
	bool bHasChange=false;
	api->m_data.GetAttr(change,api->m_change_mgr.a_chng_items,ext_chng_items);
	for(i=0;i<ext_chng_items.GetSize();i++)
	{
		CaplInstance *doc,*ch_item=ext_chng_items[i];
		if(!api->m_data.IsKindOf(ch_item,api->m_change_mgr.e_avc)) continue;
		api->m_data.GetAttr(ch_item,api->m_change_mgr.a_avc_doc,doc);

		if(map_doc_cng_items.FindByIn((long)doc)>=0)
		{
			// удаляем т.к. не может быть несколько правил для одного документа
			ext_chng_items.Remove(i);
			api->m_data.DeleteInstance(ch_item); 
			i--;
			bHasChange=true;
		}
		else map_doc_cng_items.Add(doc,ch_item);
	}

	// Создаем или изменяем правилила назначения версий активной
	for(i=0;i<ext_new_ver_spec.GetSize();i++)
	{
		CaplInstance *new_spec_rev, *new_spec_doc;
		new_spec_rev=ext_new_ver_spec[i];
		api->m_data.GetAttr(new_spec_rev,api->m_doc_mgr.a_apl_doc_rev_doc,new_spec_doc);

		CaplInstance *ch_item=(CaplInstance*)map_doc_cng_items.GetByInP(new_spec_doc);
		if(0==ch_item)
		{
			ch_item=api->m_data.CreateInstance(api->m_change_mgr.e_avc);
			ext_chng_items.Add(ch_item);
			api->m_data.PutAttr(ch_item,api->m_change_mgr.a_chng_item_of_chng,change);
			api->m_data.PutAttr(ch_item,api->m_change_mgr.a_avc_doc,new_spec_doc);
		}
		api->m_data.PutAttr(ch_item,api->m_change_mgr.a_avc_new_rev,new_spec_rev);
		bHasChange=true;
	}

	if(bHasChange)
	{
		api->m_data.PutAttr(change,api->m_change_mgr.a_chng_items,ext_chng_items);
		api->SaveChanges();
	}

	buf.Format(APL_T("Успешно сформировано %i спецификаций."),count_ok);
	if(count_false>0)
	{
		CString buf1;
		buf1.Format(APL_T("\n\nОшибок генерации %i."),count_false);
		buf+=buf1;
	}
	AfxMessageBox(buf,MB_OK|MB_ICONINFORMATION);
	return true;
}


//**********************************************************************************
//**********************************************************************************
//**********************************************************************************

__declspec (dllexport) bool Make_UL(CaplAPI* api, aplExtent& inExtent, bool bUpdateUI)
{
	if(!api || !api->m_data.IsConnected()) return false;
	if(inExtent.GetSize()<1)  return false;

	CaplInstance *doc=inExtent[0], *doc_rev;

	if(0==doc)  return false;
	if(doc->IsDeleted())  return false;
	if(doc->GetAccessmode()>aplRO) return false;


	if(api->m_data.IsKindOf(doc,api->m_doc_mgr.e_doc))
	{
		api->m_data.GetAttr(doc,api->m_doc_mgr.a_apl_doc_active,doc_rev);
	}
	else if(api->m_data.IsKindOf(doc,api->m_doc_mgr.e_apl_doc_rev))
	{
		doc_rev=doc;
		api->m_data.GetAttr(doc_rev,api->m_doc_mgr.a_apl_doc_rev_doc,doc);
	}
	else return false;

	if(0==doc)  return false;
	if(doc->IsDeleted())  return false;
	if(0==doc_rev)  return false;
	if(doc_rev->IsDeleted())  return false;
	if(doc->GetAccessmode()>aplRO) return false;
	if(doc_rev->GetAccessmode()>aplRO) return false;


	if(bUpdateUI) return true;


	//CSpecGenerator spec_generator(api);

	//return spec_generator.Generate(pdf,true);

	CString sId,sUlId, sName,sType,sVersion,sChangeId,sCrc;
	CaplInstance *dt;
	api->m_data.GetAttr(doc,api->m_doc_mgr.a_doc_id,sId);
	sUlId=sId+"-УЛ";
	api->m_data.GetAttr(doc,api->m_doc_mgr.a_doc_name,sName);
	api->m_data.GetAttr(doc,api->m_doc_mgr.a_doc_kind,dt);
	if(0!=dt) api->m_data.GetAttr(dt,api->m_doc_mgr.a_dt_pdt,sType);
	api->m_data.GetAttr(doc_rev,api->m_doc_mgr.a_apl_doc_rev_id,sVersion);

	int crc;
	api->m_data.GetAttr(doc_rev,api->m_doc_mgr.a_apl_doc_rev_crc,crc);
	sCrc.Format(_T("%08X"),crc);

	//Определение номера изменения
	aplExtent aeItems;
	CString sSql;
	sSql.Format("SELECT_LOAD_ALL Ext FROM Ext {apl_document_change_item( .new_revision =  #%i)} END_SELECT",doc_rev->GetId());
	api->m_data.NET_QueryEditParse(sSql);
	api->m_data.NET_QueryExecute(aeItems);
	if(aeItems.GetSize()>0) api->m_data.GetAttr(aeItems[0],api->m_change_mgr.a_chng_item_id,sChangeId);

	CString sPathRep; aplGetTempPath(sPathRep);
	CString buf=AfxGetApp()->m_pszHelpFilePath;
	CString template_path=buf.Left(buf.ReverseFind(_T('\\')));

	template_path+=_T("\\Шаблон_УЛ_01.xml");

	CaplReport report;
	if(!report.OpenFile(template_path)) {AfxMessageBox(_T("Не найден шаблон отчета ('Шаблон_УЛ_01.xml').\n\nСоздание невозможно!)"),MB_ICONSTOP|MB_OK); return false;}

	// Берем параметры из шаблона
	if(report.m_pages.GetSize()<1) {AfxMessageBox(_T("Некорректный шаблон (нет страниц)!!)"),MB_ICONSTOP|MB_OK); return false;}

	buf= sUlId; 
	buf.Replace(' ','_');
	buf.Replace('?','_');
	buf.Replace('*','_');
	buf.Replace('/','_');
	buf.Replace('\\','_');
	CString sAplRep = buf + ".xmlrep";

	sPathRep+=sAplRep;


	// Формирование финального документа

	//sPathRep=_T("C:\\Users\\Alexey\\Desktop\\СП_rep.xmlrep");  // Для отладки

	SetFileAttributes(sPathRep,FILE_ATTRIBUTE_NORMAL);
	DeleteFile(sPathRep);

	CaplStrStrMap map_params;

	map_params.Add("ul_num", "");
	map_params.Add("id", sId);
	
	if(sType!=""){sName+="\n"; sName+=sType;}
	
	map_params.Add("name", sName);
	map_params.Add("version", sVersion);
	map_params.Add("change_num", sChangeId);
	map_params.Add("ul_id", sUlId);
	map_params.Add("chek_sum_name", "CRC32");
	map_params.Add("chek_sum_value", sCrc);


	if(!report.GenerateReport(&map_params, 0,sPathRep,false,true))
	{
		AfxMessageBox(_T("Ошибка при генерации отчета!"), MB_ICONSTOP); 
		return false;
	}

	long file_size=-1;
	CFileStatus status;
	if(CFile::GetStatus(sPathRep,status)) file_size=(long)status.m_size;

	if(file_size<1) 
	{
		AfxMessageBox(_T("Файл не создан!"),MB_OK|MB_ICONSTOP);
		return false;
	}

/*
	// Тестовый кусок
	// Создание 3 копии на 1 стр.
	CaplReport report2;
	if(!report2.OpenFile(template_path)) {AfxMessageBox(_T("Не найден шаблон отчета ('Шаблон_УЛ_01.xml').\n\nСоздание невозможно!)"),MB_ICONSTOP|MB_OK); return false;}

	CaplReportPage *rp0_page=report.m_pages[0];
	CaplReportPage *rp2_page=report2.m_pages[0];
	rp2_page->Clear();

	int i,j;
	for(i=0;i<3;i++)
	{
		float delta=(float) (i*110); 
		for(j=0;j<rp0_page->m_fields.GetSize();j++)
		{
			CaplReportField *src_field=rp0_page->m_fields[j];
			CaplReportField *trg_field=new CaplReportField(src_field);
			trg_field->m_y+=delta;
			rp2_page->m_fields.Add(trg_field);
		}
	}
	DeleteFile(sPathRep);
	report2.SaveReport(sPathRep,false,false);
*/

	//if(TRUE!=m_bSaveAsDocument) // Для отладки
	{
		if(IDYES==AfxMessageBox(_T("Документ создан!  Открыть для просмотра ?"),MB_ICONINFORMATION|MB_YESNO))
		{
			aplShellExecute(AfxGetMainWnd()->m_hWnd,_T("open"),sPathRep,NULL,NULL,SW_SHOW);
		}
		return true;
	}

	AfxMessageBox("Make_UL - End!");
	return false;
}

