#ifndef __HCM4A_CalcFs4A_dtPack_h_
#define __HCM4A_CalcFs4A_dtPack_h_

#include <Xlnt/Xlnt.h>

#include "dtTerrain.h"
#include "dtHcmIN.h"


DblCoordRec StrToDblCoordRec(const String& strCoord){
	if(strCoord.IsEmpty()) return DblCoordRec();
	DblCoordRec coordRec;
	HcmError tError;
	String vstr = strCoord;
	String sLong = vstr.Mid(0, 8);
	int err = StrToDblCoord(vstr.Mid(0, 8), coordRec.longitude, tError);
	if(err != 0 || vstr.GetCount() != 15) return DblCoordRec();
	String sLat = vstr.Mid(8, 7);
	err = StrToDblCoord(vstr.Mid(8, 7), coordRec.latitude, tError);
	if(err != 0) return DblCoordRec();
	return coordRec;
}
//!---------------------------------------------------------------------------------------------

struct StationRec: Moveable<StationRec>{
    String name;
    double longitude;
    double latitude;
    double azimut;
    double heigth;
    double radius;
    bool isRef;
	void Clear();
	String ToString()const;
    StationRec(){Clear();};
    StationRec(const String& name, const double longitude, const double latitude, const double azimut, const double heigth, const double radius, const bool isRef):
        name(name), longitude(longitude), latitude(latitude), azimut(azimut), heigth(heigth), radius(radius), isRef(isRef){};
};
void StationRec::Clear(){
    name = "";
    longitude = 0.0;
    latitude = 0.0;
    azimut = 0.0;
    heigth = 0.0;
    radius = 0.0;
    isRef = false;
}
String StationRec::ToString()const{
	return Format("\nStationRec:\n name %s\n longitude %f\n latitude %f\n azimut %f\n heigth %f\n radius %f\n isRef %d\n",
		name, longitude, latitude, azimut, heigth, radius, isRef);
}
//!---------------------------------------------------------------------------------------------

struct EntFreqRec: Moveable<EntFreqRec>{
	int GetIDX()const{return idx;}
	double GetFreq()const{return freq;}
	HcmEntity GetEntity()const{return entity;}
	EntFreqRec(){Clear();}
	EntFreqRec(const int idx, const HcmIN& in);
protected:
	void Clear(){idx=-1; freq=0.0; entity=HcmEntity::None;}
	int idx;
	double freq;
	HcmEntity entity;
};
EntFreqRec::EntFreqRec(const int idx, const HcmIN& in):idx(idx){
	if(idx >-1){
		freq = StrToFreqGHz(in.GetField("1A").GetStr(), in.GetField("1A1").GetStr());
		entity = in.GetEntity();
	}
}
//!---------------------------------------------------------------------------------------------

enum class HcmPackFormat {TXT, JSON, XLS};

struct HcmPack{
	bool IsEmpty()const{return hcmMap.GetCount()==0;};
	bool IsValid()const;
	const String GetPackFile()const{return packfile;}
	const HcmField GetField(const int recNpp, const int fieldID)const;
	const HcmField GetField(const int recNpp, const String& fcode)const;
	bool FromXLS(const String& file);
	bool FromCSV(const String& file);
	bool FromJson(const String& file);
	bool ToXLS(const String& file);
	bool ToXLS();
	bool ToCSV()const;
	bool ToCSV(const String& file)const;
	bool ToJson(const String& file);
	bool ToJson();
	void Jsonize(JsonIO& json);
	String ToString()const;
	
	void FillStationList(const bool isRef, Vector<StationRec>& list)const; /// for GisMap

	const HcmHeader& GetHeader()const{return header;}
	HcmHeader& GetHeader(){return header;}
	const VectorMap<int, HcmIN>& GetMap()const;
	const HcmIN& GetHcmIN(int id)const;
	HcmIN& GetHcmIN(int id);
	HcmPackFormat GetFormat()const{return format;}
	int Find(HcmEntity en)const;
	void SetCoStatus(const int id, const String& f13Y, const String& f13Z);
	void SetCoStatus(const int id, const String& f13Y);
	void SetCoStatus(const String& f13Y);

	void SetHeader(const HcmHeader& head){header.Set(head);}
	void Clear();
	bool Delete(int id);
	void Add();
	void Add(const HcmIN& hcmIN);
	HcmPack(){Clear();};
	~HcmPack(){Clear();};
protected:
	HcmPackFormat format;
	String packfile;
	HcmHeader header;
	Vector<String> columns;						// column names of the table
	VectorMap<int, HcmIN> hcmMap;				// key = npp

	bool FindAndRem(Vector<EntFreqRec>& list, const EntFreqRec& rec)const;
	bool FindAndRem(Vector<EntFreqRec>& txList, Vector<EntFreqRec>& rxList)const;
	bool FindAndRem(Vector<EntFreqRec>& txList, Vector<EntFreqRec>& prxList, Vector<EntFreqRec>& ptxList, Vector<EntFreqRec>& rxList)const;

	bool IsRxTx(Vector<EntFreqRec>& txList, Vector<EntFreqRec>& rxList)const;
	bool IsRxPTxPRxTx(Vector<EntFreqRec>& txList, Vector<EntFreqRec>& prxList, Vector<EntFreqRec>& ptxList, Vector<EntFreqRec>& rxList)const;

	bool UnidirectCheck()const;
	bool BidirectCheck()const;
	bool RepeatBidirectCheck()const;
};
void HcmPack::Clear(){
	packfile = "";
	columns.Clear();
	format = HcmPackFormat::TXT;
	header.Clear();
	hcmMap.Clear();
}
bool HcmPack::FindAndRem(Vector<EntFreqRec>& list, const EntFreqRec& rec)const{
	for(int i=0; i< list.GetCount(); i++){
		if(list[i].GetFreq() == rec.GetFreq()){
			list.Remove(i);
			return true;
		}
	}
	return false;
}
bool HcmPack::FindAndRem(Vector<EntFreqRec>& txList, Vector<EntFreqRec>& rxList)const{
	for(int i=0; i< txList.GetCount(); i++){
		for(int j=0; i< rxList.GetCount(); j++){
			if(txList[i].GetFreq() == rxList[j].GetFreq()){
				txList.Remove(i);
				rxList.Remove(j);
				return true;
			}
		}
	}
	return false;
}
bool HcmPack::FindAndRem(Vector<EntFreqRec>& txList, Vector<EntFreqRec>& prxList, Vector<EntFreqRec>& ptxList, Vector<EntFreqRec>& rxList)const{
	for(int i=0; i< prxList.GetCount(); i++){
		for(int j=0; i< ptxList.GetCount(); j++){
			if(prxList[i].GetFreq() == ptxList[j].GetFreq()	&& FindAndRem(txList, prxList[i]) && FindAndRem(rxList, prxList[i])){
				prxList.Remove(i);
				ptxList.Remove(j);
				return true;
			}
		}
	}
	return false;
}
bool HcmPack::IsRxTx(Vector<EntFreqRec>& txList, Vector<EntFreqRec>& rxList)const{
	while(txList.GetCount() && rxList.GetCount()){
		if(!FindAndRem(txList, rxList)){
			return false;
		}
	}
	return true;
}
bool HcmPack::IsRxPTxPRxTx(Vector<EntFreqRec>& txList, Vector<EntFreqRec>& prxList, Vector<EntFreqRec>& ptxList, Vector<EntFreqRec>& rxList)const{
	while(ptxList.GetCount() && prxList.GetCount()){
		if(!FindAndRem(txList, prxList, ptxList, rxList)){
			return false;
		}
	}
	while(txList.GetCount() && rxList.GetCount()){
		if(!FindAndRem(txList, rxList)){
			return false;
		}
	}
	return true;
}
bool HcmPack::UnidirectCheck()const{
	// 1 / Unidirectional link
	//	There are 2 records
	//		TXA ->(F1)-> RXB
	// Link between station  A and station B with F1 :
	//	[13X]: D  2005 1234567 010201	for TXA on F1
	//	[13X]: D  2005 1234567 010202	for RXB on F1
	if(hcmMap.GetCount() == 2){
		int iTX = Find(HcmEntity::TX);
		int iRX = Find(HcmEntity::RX);
		if(iTX==-1 || iRX==-1){
			// the pair shall have 1 TX and 1 RX
			return false;
		}
		if(GetHcmIN(iTX).GetField("1A").GetStr() != GetHcmIN(iRX).GetField("1A").GetStr()){
			// Frequency::TX != Frequency::RX
			return false;
		}
		return true;
	}
	return false;
}
bool HcmPack::BidirectCheck()const{
	// 2 / Bidirectional link
	//	There are 4 records
	//		TXA ->(F1 )-> RXB
	//		RXA <-(F’1)<- TXB
	// Then the 2 pairs representing the bidirectional link are associated using the parameter 4C
	// Link between PtA and PtB with F1/ F’1 :
	// F1: 1A = 27562.5
	//	[13X]: D  2005 1234568 010401	for TXA on F1
	//	[13X]: D  2005 1234568 010402	for RXB on F1
	// F’1: 1A = 28570.5
	//	[13X]: D  2005 1234568 010403	for TXB on F’1
	//	[13X]: D  2005 1234568 010404	for RXA on F’1
	if(hcmMap.GetCount()%2==0){
		if(Find(HcmEntity::None)!=-1 || Find(HcmEntity::PTX)!=-1 || Find(HcmEntity::PRX)!=-1){
			// without passive repeater and without unknown HcmEntity
			return false;
		}
		Vector<EntFreqRec> rxList;
		Vector<EntFreqRec> txList;
		for(int i=0; i< hcmMap.GetCount(); i++){
			if(hcmMap[i].GetEntity() == HcmEntity::RX)
				rxList.Add(EntFreqRec(i, hcmMap[i]));
			else if(hcmMap[i].GetEntity() == HcmEntity::TX)
				txList.Add(EntFreqRec(i, hcmMap[i]));
		}
		if(rxList.GetCount() != txList.GetCount()){
			return false;
		}
		return IsRxTx(txList, rxList);
	}
	return false;
}
// Vector<Tuple<EntFreqRec, EntFreqRec, EntFreqRec, EntFreqRec>> fourList;	// Vector Tuple<iTx, iPRx, iPTx, iRx>
bool HcmPack::RepeatBidirectCheck()const{
	// 3 / Bidirectional link with passive repeater
	//This bidirectional link with passive repeater shall be identified by these 8 records.
	// Link between PtA and PtB with F1/ F’1 :
	// F1: 1A = 14431.0
	//	[13X]: D  2005 0001251 01 08 01	for TXA on F1
	//	[13X]: D  2005 0001251 01 08 02	for PRXR1 on F1
	//	[13X]: D  2005 0001251 01 08 03	for PTXR1 on F1
	//	[13X]: D  2005 0001251 01 08 04	for RXB on F1
	// F’1: 1A = 14291.0
	//	[13X]: D  2005 0001251 01 08 05	for TXB on F’1
	//	[13X]: D  2005 0001251 01 08 06	for PRXR2 on F’1
	//	[13X]: D  2005 0001251 01 08 07	for PTXR2 on F’1
	//	[13X]: D  2005 0001251 01 08 08	for RXA on F’1
	if(hcmMap.GetCount()%2==0){
		if(Find(HcmEntity::None)!=-1){
			// without unknown HcmEntity
			return false;
		}
		Vector<EntFreqRec> rxList;
		Vector<EntFreqRec> txList;
		Vector<EntFreqRec> prxList;
		Vector<EntFreqRec> ptxList;
		for(int i=0; i< hcmMap.GetCount(); i++){
			if(hcmMap[i].GetEntity() == HcmEntity::RX)
				rxList.Add(EntFreqRec(i, hcmMap[i]));
			else if(hcmMap[i].GetEntity() == HcmEntity::TX)
				txList.Add(EntFreqRec(i, hcmMap[i]));
			else if(hcmMap[i].GetEntity() == HcmEntity::PTX)
				ptxList.Add(EntFreqRec(i, hcmMap[i]));
			else if(hcmMap[i].GetEntity() == HcmEntity::PRX)
				prxList.Add(EntFreqRec(i, hcmMap[i]));
		}
		if(rxList.GetCount() != txList.GetCount()){
			return false;
		}
		if(prxList.GetCount() != ptxList.GetCount()){
			return false;
		}
		return IsRxPTxPRxTx(txList, prxList, ptxList, rxList);
	}
	return false;
}
bool HcmPack::IsValid()const{
	return UnidirectCheck() || BidirectCheck() || RepeatBidirectCheck();
}
String HcmPack::ToString()const{
	return Format("\nFile: %s\nHeader: %s, HcmMap: %s\n", packfile, header.ToString(), hcmMap.ToString());
}
const VectorMap<int, HcmIN>& HcmPack::GetMap()const{
	return hcmMap;
}
const HcmIN& HcmPack::GetHcmIN(int id)const{
	static HcmIN hcmIN;
	int idx = hcmMap.Find(id);
	if(idx > -1) return hcmMap[idx];
	return hcmIN;
}
HcmIN& HcmPack::GetHcmIN(int id){
	static HcmIN hcmIN;
	int idx = hcmMap.Find(id);
	if(idx > -1) return hcmMap[idx];
	return hcmIN;
}
int HcmPack::Find(HcmEntity en)const{
	for(int i=0; i< hcmMap.GetCount(); i++){
		if(hcmMap[i].GetEntity() == en)
			return i;
	}
	return -1;
}
void HcmPack::SetCoStatus(const int id, const String& f13Y, const String& f13Z){
	int idx = hcmMap.Find(id);
	if(idx > -1){
		hcmMap[idx].EditVal("13Y", f13Y);
		hcmMap[idx].EditVal("13Z", f13Z);
	}
}
void HcmPack::SetCoStatus(const int id, const String& f13Y){
	int idx = hcmMap.Find(id);
	if(idx > -1){
		hcmMap[idx].EditVal("13Y", f13Y);
		hcmMap[idx].EditVal("2Z", DateFormat(GetSysDate()));
	}
}
void HcmPack::SetCoStatus(const String& f13Y){
	for(int i=0; i< hcmMap.GetCount(); i++){
		hcmMap[i].EditVal("13Y", f13Y);
		hcmMap[i].EditVal("2Z", DateFormat(GetSysDate()));
	}
}


/// for GisMap
void HcmPack::FillStationList(const bool isRef, Vector<StationRec>& list)const{
	for(int i=0; i< hcmMap.GetCount(); i++){
		DblCoordRec coordRec = StrToDblCoordRec(hcmMap[i].GetField("4C").GetStr());
		StationRec rec(
				hcmMap[i].GetField("4A").GetStr(),
				coordRec.longitude,
				coordRec.latitude,
				hcmMap[i].GetField("9A").GetDbl(),
				hcmMap[i].GetField("4Z").GetDbl(), // TODO: "4Z" + "9Y" ???
				0.0,
				isRef);
		list.Add(rec);
	}
}
bool HcmPack::Delete(int id){
	int idx = hcmMap.Find(id);
	if(idx > -1){
		hcmMap.Remove(idx);
		return true;
	}
	return false;
}
void HcmPack::Add(){
	int newKey = -1;
	while(true){
		newKey++;
		if(hcmMap.Find(newKey)==-1){
			break;
		}
	}
	hcmMap.Add(newKey, HcmIN());
}
void HcmPack::Add(const HcmIN& hcmIN){
	int newKey = -1;
	while(true){
		newKey++;
		if(hcmMap.Find(newKey)==-1){
			break;
		}
	}
	hcmMap.Add(newKey, clone(hcmIN));
}
bool HcmPack::FromXLS(const String& file){
	hcmMap.Clear();
	columns.Clear();
	if(!FileExists(file)){
		LOG(Format("Error: File %s, not found", file));
		return false;
	}
	header.Clear();
	FileIn f_in(file);
    xlnt::workbook wb;
	wb.load(~file);
	xlnt::worksheet ws = wb.active_sheet();
	int nrow = 0;
	Vector<Vector<String>> head;
	Vector<Vector<String>> vhcm;
	for(auto row: ws.rows(false)){
		nrow++;
		Vector<String> vRow;
		for(auto cell: row){
			vRow.Add(cell.to_string());
		}
		if(nrow <= header.GetMap().GetCount()){
			// read header
			head.Add(pick(vRow));
		}
		else if(nrow == header.GetMap().GetCount()+1){
			// read table title
			columns = pick(vRow);
		}
		else{
			// read hcm data
			vhcm.Add(pick(vRow));
		}
	}
	header.FromVecXLS(head);
	// parse Vector<Vector<String>> hcm data
	for(int i=0; i < vhcm.GetCount(); i++){
		HcmIN hcmIN; hcmIN.FromVecXLS(vhcm[i]);
		if(hcmIN.GetEntity() != HcmEntity::None)
			hcmMap.Add(hcmMap.GetCount(), clone(hcmIN));
	}
    packfile = file;
    format = HcmPackFormat::XLS;
    return nrow > 0;
}
bool HcmPack::ToXLS(const String& file){
    xlnt::workbook wbOut;
    xlnt::worksheet wsOut = wbOut.active_sheet();
    wsOut.title("hcmfs data");
	// header - as col
	Vector<NameVal> vecNV = header.ToNV();
    for(int i=0; i<vecNV.GetCount(); i++){
		wsOut.cell(xlnt::cell_reference(1, i+1)).value(vecNV[i].code.ToStd());
		wsOut.cell(xlnt::cell_reference(2, i+1)).value(vecNV[i].val.ToStd());
		wsOut.cell(xlnt::cell_reference(3, i+1)).value(vecNV[i].name.ToStd());
    }
	Vector<Vector<String>> vec;
	for(auto v: hcmMap){
		vec.Add(v.ToVecXLS(columns));
	}
	int tRow = vecNV.GetCount()+1; // title row
    for(int i=0; i<columns.GetCount(); i++){
		wsOut.cell(xlnt::cell_reference(i+1, tRow)).value(columns[i].ToStd());
    }
	int dRow = vecNV.GetCount()+2;	// start data row
    for(int i=0; i<vec.GetCount(); i++){
	    for(int j=0; j<vec[i].GetCount(); j++)
	        wsOut.cell(xlnt::cell_reference(j+1, i+dRow)).value(vec[i][j].ToStd());
    }
    wbOut.save(file.ToStd());
    return true;
}
bool HcmPack::ToXLS(){
    return ToXLS(packfile);
}

bool HcmPack::FromCSV(const String& file){
	hcmMap.Clear();
	if(!FileExists(file)){
		LOG(Format("Error: File %s, not found", file));
		return false;
	}
	header.Clear();
	FileIn f_in(file);
	int lcnt = 0;
	while(!f_in.IsEof()){
        String tmpS = f_in.GetLine();
		HcmIN hcmIN; hcmIN.FromCSV(tmpS);
        if(IsHcmEntity(hcmIN.GetField(0).GetStr())){
            hcmMap.Add(lcnt, clone(hcmIN));
			lcnt++;
        }
        else{
            if(lcnt==0)
                header.FromCSV(tmpS);
        }
    }
    packfile = file;
    format = HcmPackFormat::TXT;
    return lcnt > 0;
}
bool HcmPack::ToCSV(const String& file)const{
	FileOut f_out(file);
	if(!f_out) return false;
	f_out.PutLine(header.ToCSV());
	for(auto v: hcmMap){
		f_out.PutLine(v.ToCSV());
	}
    f_out.Close();
    return true;
}
bool HcmPack::ToCSV()const{
    return ToCSV(packfile);
}
const HcmField HcmPack::GetField(const int recNpp, const int fieldID)const{
	HcmField hcmField;
	if(recNpp < hcmMap.GetCount()){
		return hcmMap[recNpp].GetField(fieldID);
	}
	return hcmField;
}
const HcmField HcmPack::GetField(const int recNpp, const String& fcode)const{
	HcmField hcmField;
	if(recNpp < hcmMap.GetCount()){
		return hcmMap[recNpp].GetField(fcode);
	}
	return hcmField;
}
void HcmPack::Jsonize(JsonIO& json){
	Vector<HcmIN> vecIN;
	if(json.IsStoring()){
		for(auto v: hcmMap)
			vecIN.Add(clone(v));
		json
			("Header", header)
			("Entry", vecIN)
			;
	}
	else{
		// if(json.IsLoading())
		header.Clear();
		hcmMap.Clear();
		json
			("Header", header)
			("Entry", vecIN)
			;
		for(int i=0; i< vecIN.GetCount(); i++)
			hcmMap.Add(i, clone(vecIN[i]));
	}
}
bool HcmPack::ToJson(const String& file){
	return StoreAsJsonFile(*this, file);
}
bool HcmPack::ToJson(){
    return ToJson(packfile);
}
bool HcmPack::FromJson(const String& file){
	if(LoadFromJsonFile(*this, file)){
	    format = HcmPackFormat::JSON;
	    packfile = file;
		return true;
	}
	return false;
}
//!---------------------------------------------------------------------------------------

struct PtrRec: Moveable<PtrRec>{
	HcmRec ptx;
	HcmRec prx;
	void Clear(){ptx.Clear(); prx.Clear();}
	void SetTx(const HcmRec& tx){ptx.Set(tx);};
	void SetRx(const HcmRec& rx){prx.Set(rx);};
	PtrRec(){Clear();}
	PtrRec(const PtrRec& rec): ptx(clone(rec.ptx)), prx(clone(rec.prx)){}
	PtrRec(const HcmRec& ptx, const HcmRec& prx): ptx(clone(ptx)), prx(clone(prx)){}
};
//!---------------------------------------------------------------------------------------------

struct MultHcmPack: Moveable<MultHcmPack>{
	Vector<HcmRec> txList;
	Vector<HcmRec> rxList;
	Vector<PtrRec> ptrList;
	void Clear(){txList.Clear(); rxList.Clear(); ptrList.Clear();}
	bool FromCSV(const String& fileRef);
	bool FromPack(const HcmPack& pack);
	String ToString()const;
	String GetHcmFile()const{return hcmFile;};
	bool IsValid()const;
	HcmError GetError()const;
	MultHcmPack(){Clear();}
protected:
	String hcmFile;
};
bool MultHcmPack::IsValid()const{
	if(txList.GetCount() && rxList.GetCount() && txList.GetCount() == rxList.GetCount()){
		if(ptrList.GetCount()){
			for(auto v: ptrList){
				if(v.prx.IsEmpty() || v.ptx.IsEmpty())
					return false;
			}
		}
		return true;
	}
	return false;
}
HcmError MultHcmPack::GetError()const{
	HcmError error;
	for(auto v: txList){
		if(!v.tError.IsOk()) return v.tError;
	}
	for(auto v: rxList){
		if(!v.tError.IsOk()) return v.tError;
	}
	for(auto v: ptrList){
		if(!v.prx.tError.IsOk()) return v.prx.tError;
		if(!v.ptx.tError.IsOk()) return v.ptx.tError;
	}
	return error;
}
bool MultHcmPack::FromPack(const HcmPack& pack){
	const VectorMap<int, HcmIN>& map = pack.GetMap();
	TStdAnt ant;
	Vector<HcmRec> prxList;
	Vector<HcmRec> ptxList;
	for(int i=0; i<map.GetCount(); i++){
		HcmEntity en = map[i].GetEntity();
		if(en == HcmEntity::TX || en == HcmEntity::PRX || en == HcmEntity::PTX || en == HcmEntity::RX){
			HcmIN hcmIN = clone(map[i]);
			HcmRec hcmRec(ant, hcmIN);
			if(en == HcmEntity::TX)
				txList.Add(hcmRec);
			else if(en == HcmEntity::PRX)
				prxList.Add(hcmRec);
			else if(en == HcmEntity::PTX)
				ptxList.Add(hcmRec);
			else if(en == HcmEntity::RX)
				rxList.Add(hcmRec);
		}
	}
	if(ptxList.GetCount() && ptxList.GetCount() == prxList.GetCount()){
		for(int i=0; i< ptxList.GetCount(); i++){
			ptrList.Add(PtrRec(ptxList[i], prxList[i]));
		}
	}
	if(IsValid()) hcmFile = pack.GetPackFile();
	return txList.GetCount() && rxList.GetCount();
}
bool MultHcmPack::FromCSV(const String& fileRef){
	FileIn file(fileRef);
	if(file.IsError()||file.IsEof()) return false;
	Vector<HcmRec> ptxList;
	Vector<HcmRec> prxList;
	TStdAnt ant;
	while(!file.IsEof()){
		String hsmString = file.GetLine();
		HcmIN hcmIN; hcmIN.FromCSV(hsmString);
        if(IsHcmEntity(hcmIN.GetField(0).GetStr())){
			HcmRec hcmRec(ant, hcmIN);
			if(hcmRec.IsEmpty()) continue;
			if(hcmRec.isTx && !hcmRec.isPassive)
				txList.Add(hcmRec);
			else if(!hcmRec.isTx && !hcmRec.isPassive)
				rxList.Add(hcmRec);
			else if(hcmRec.isTx && hcmRec.isPassive)
				ptxList.Add(hcmRec);
			else if(!hcmRec.isTx && hcmRec.isPassive)
				prxList.Add(hcmRec);
        }
	}
	// it is considered that the number of PTx and RTx must match
	if(ptxList.GetCount() && ptxList.GetCount() == prxList.GetCount()){
		for(int i=0; i< ptxList.GetCount(); i++){
			ptrList.Add(PtrRec(ptxList[i], prxList[i]));
		}
	}
	if(IsValid()) hcmFile = fileRef;
	return txList.GetCount() && rxList.GetCount();
}
String MultHcmPack::ToString()const{
	String rStr = "";
	rStr << "-txList: \n";
	for(auto v: txList)
		rStr << v.ToPrint() << "\n";
	rStr << "-rxList: \n";
	for(auto v: rxList)
		rStr << v.ToPrint() << "\n";
	rStr << "-ptrList: \n";
	for(auto v: ptrList){
	rStr << "-- prx: \n";
		rStr << v.prx.ToPrint() << "\n";
	rStr << "-- ptx: \n";
		rStr << v.ptx.ToPrint() << "\n";
	}
	return rStr;
}
//!---------------------------------------------------------------------------------------------



#endif
