#pragma once

typedef std::map<CString, CString> TStrStrMap;
typedef std::map<CString, CaplInstance*> TStrInstMap;

class CaplNrmmManager
{
public:
	CaplNrmmManager(CaplAPI *api);
	~CaplNrmmManager(void);

	// генерация нормы по конструкторскому составу
	bool GenerateLimitByPdf(CaplInstance *nrm, CaplInstance *pdf);

	// удаление НРМ и всех входящих в нее элементов
	bool DeleteLimit(CaplInstance *nrm);

protected:
	// рекурсивное удаление
	bool DeleteLimitRecursive(aplExtent &parentPdf, const CString &pdfId);

	// можно ли генерить норму по выбранному изделию
	bool CanGenerateNrm(CaplInstance *nrm, CaplInstance *pdf);

	// поиск и загрузка всего необходимого для материалов, входящих в сборку
	bool FindMaterials(CaplInstance *parentPdf, aplExtent &materials, aplExtent &nrmItems);

	// разузлуем pdf и найдем все связи вхождение для material
	void FindMaterialRelations(aplExtent &parentPdfs, aplExtent &structureRelations, aplExtent &nrmItems);

	// проверка материала (не из отходов деталь, не компонентный материал и т.п.)
	bool TestMaterialRelation(CaplInstance *relation);

	// проверка на полуфабрикат
	CaplInstance* IsPreFabricated(CaplInstance *relation);

	// сохранить структуру изделия в кеш
	void SaveDisassembly(CaplInstance *pdf, aplExtent &structureRelations);

	// возвращает входимость pdfToCount в topPdf
	double GetCountForCustomPdf(CaplInstance *topPdf, CaplInstance *pdfToCount);

	// загрузка атрибутов для изделий, содержащих исходный материал
	void LoadAttrsMaterialRelations(aplExtent &materialRelations, bool bLoadFromDb);

	// загрузка характеристик
	void LoadCharacts(aplExtent &materialRelations);

	// загрузка необходимых справочников и их уровней
	bool LoadClassifiers(TStrStrMap &classifiers);

	// создание дочернего элемента
	CaplInstance* AddChild(CaplInstance *parent, LPCTSTR id, LPCTSTR name);

	// единица измерения по умолчанию
	CaplInstance* GetBasePrdUnit();

	// поиск существующих НРМ
	void FindExistingNrm(aplExtent &pdfs, aplExtent &nrmItems);

	// установка доступа для "Ведущие сводных НРМ"
	bool SetNewItemsAccess(aplExtent &accessItems);

	// синхронизация количества материала с реальным составом
	bool GetMaterialCountByShop(std::map<CString, double> &info, CaplInstance *material, CaplInstance *pdf);
	bool SynchronizeCount(std::map<CaplInstance*, CaplInstance*> &nrmmMaterial, long dId, CaplInstance *pdf);
	bool SynchronizeCount(CaplInstance *nrmm, CaplInstance *material, CaplInstance *pdf, double koeff);

	// группировка связей материала по складу
	void GroupRelationsByShop(aplExtent &materialRelations, std::map<CString, std::vector<CaplInstance*>> &groupedMaterialRelations);

	// главная функция по получению количества материала на основе структуры изделия
	void GetTotalMaterialCount(std::map<CaplInstance*, std::vector<CaplInstance*>> &relationsOrderedByEdItem,
								std::map<CString, std::vector<CaplInstance*>> &groupedMaterialRelations,
								std::map<CString, double> &info,
								CaplInstance *topPdf);

	// рекурсивно вверх идем и перемножаем количество
	double GetTotalPdfCount(CaplInstance *item, std::map<CaplInstance*, std::vector<CaplInstance*>> &relationsOrderedByEdItem, CaplInstance *topPdf);

	void ParseRasc(CString& csInRasc,CString csDepotSep,CString csGrpSep,
		CStringArray* csapOutDepots,CStringArray* csapOutGrps);

protected:
	CaplAPI *m_api;
	CaplInstance *m_baseUnit;
	CaplInstance *m_shopCharact;
	CaplInstance *m_rascCharact;	
	CaplInstance *m_warehouseCharact;

	std::set<CaplInstance*> m_pdfWithLoadedAttrs;
	std::set<CaplInstance*> m_relationsWithLoadedCharacts;
	std::map<CaplInstance*, std::vector<CaplInstance*>> m_disassembliedPdfs;	
	std::map<CaplInstance*, CaplInstance*> m_nrmForAssembly;
};
