#include"Phy_Base.h"
#include <iostream>
#include <vector>

Phy_WaveOpticsModel::Phy_WaveOpticsModel()
{
	_mPMC = Eigen::VectorXi::Zero(0);

	_mPEC = Eigen::VectorXi::Zero(0);

	_mPBCGroups.clear();

	_mPML = Eigen::VectorXi::Zero(0);
	_mPMLData = Eigen::MatrixXd::Zero(0, 6);

	_mSBC = Eigen::MatrixXi::Zero(0, 2);
	_mSBCDir = Eigen::MatrixXd::Zero(0, 3);


	_mELE = Eigen::VectorXi::Zero(0);
}

int Phy_WaveOpticsModel::GetNbrPEC()
{
	return _mPEC.rows();
}
int Phy_WaveOpticsModel::GetPECDomain(int num)
{
	return _mPEC(num);
}

int Phy_WaveOpticsModel::GetNbrPBC()
{
	return GetNbrPBCInGroup(0);
}

int Phy_WaveOpticsModel::GetNbrPBCGroups() const
{
	return static_cast<int>(_mPBCGroups.size());
}

int Phy_WaveOpticsModel::GetNbrPBCInGroup(int group) const
{
	if (group < 0 || group >= static_cast<int>(_mPBCGroups.size()))
		return 0;
	return _mPBCGroups[group].pbc.rows();
}

int Phy_WaveOpticsModel::GetSrcDomain(int num)
{
	if (_mPBCGroups.empty())
		return 0;
	return _mPBCGroups[0].pbc(num, 0);
}
int Phy_WaveOpticsModel::GetDstDomain(int num)
{
	if (_mPBCGroups.empty())
		return 0;
	return _mPBCGroups[0].pbc(num, 1);
}
std::complex<double> Phy_WaveOpticsModel::GetPBCPhi(int num)
{
	return GetPBCPhi(0, num);
}

std::complex<double> Phy_WaveOpticsModel::GetPBCPhi(int group, int num) const
{
	if (group < 0 || group >= static_cast<int>(_mPBCGroups.size()))
		return 1.0;
	return _mPBCGroups[group].data(num);
}

void Phy_WaveOpticsModel::GetSrcDomainList(int num, Eigen::VectorXi& domains)
{
	GetSrcDomainList(0, num, domains);
}

void Phy_WaveOpticsModel::GetSrcDomainList(int group, int num, Eigen::VectorXi& domains) const
{
	if (group < 0 || group >= static_cast<int>(_mPBCGroups.size()))
	{
		domains = Eigen::VectorXi(0);
		return;
	}
	if (num >= 0 && num < static_cast<int>(_mPBCGroups[group].srcDomains.size()))
		domains = _mPBCGroups[group].srcDomains[num];
	else if (num >= 0 && num < _mPBCGroups[group].pbc.rows())
	{
		domains = Eigen::VectorXi(1);
		domains(0) = _mPBCGroups[group].pbc(num, 0);
	}
}

void Phy_WaveOpticsModel::GetDstDomainList(int num, Eigen::VectorXi& domains)
{
	GetDstDomainList(0, num, domains);
}

void Phy_WaveOpticsModel::GetDstDomainList(int group, int num, Eigen::VectorXi& domains) const
{
	if (group < 0 || group >= static_cast<int>(_mPBCGroups.size()))
	{
		domains = Eigen::VectorXi(0);
		return;
	}
	if (num >= 0 && num < static_cast<int>(_mPBCGroups[group].dstDomains.size()))
		domains = _mPBCGroups[group].dstDomains[num];
	else if (num >= 0 && num < _mPBCGroups[group].pbc.rows())
	{
		domains = Eigen::VectorXi(1);
		domains(0) = _mPBCGroups[group].pbc(num, 1);
	}
}

double Phy_WaveOpticsModel::GetPBCAngle(int num)
{
	return GetPBCAngle(0, num);
}

double Phy_WaveOpticsModel::GetPBCAngle(int group, int num) const
{
	if (group < 0 || group >= static_cast<int>(_mPBCGroups.size()))
		return 0.0;
	if (num >= 0 && num < _mPBCGroups[group].angle.size())
		return _mPBCGroups[group].angle(num);
	return 0.0;
}

void Phy_WaveOpticsModel::GetPBCWaveVec(int num, Eigen::Vector3d& waveVec)
{
	GetPBCWaveVec(0, num, waveVec);
}

void Phy_WaveOpticsModel::GetPBCWaveVec(int group, int num, Eigen::Vector3d& waveVec) const
{
	waveVec = Eigen::Vector3d::Zero();
	if (group < 0 || group >= static_cast<int>(_mPBCGroups.size()))
		return;
	if (num >= 0 && num < _mPBCGroups[group].waveVec.cols())
		waveVec = _mPBCGroups[group].waveVec.col(num);
}

int Phy_WaveOpticsModel::GetNbrPML()
{
	return _mPML.rows();
}

int Phy_WaveOpticsModel::GetPMLEdge(int num)
{
	return _mPMLEdge(num);
}

void Phy_WaveOpticsModel::GetPMLDomain(Eigen::VectorXi& PMLDomain)
{
	PMLDomain = _mPML;
}

bool Phy_WaveOpticsModel::GetPML(int domain, int& PMLType, Eigen::VectorXd& PMLData)
{
	bool isMember = false;
	PMLData = Eigen::VectorXd::Zero(6);
	for (int i = 0; i < _mPML.size(); i++)
	{
		if (domain == _mPML(i))
		{
			PMLType = _mPMLType[i];
			for (int j = 0; j < 6; j++)
				PMLData(j) = _mPMLData(i, j);
			isMember = true;
		}
	}
	return isMember;
}
bool Phy_WaveOpticsModel::GetPML(int domain, int& PMLType, Eigen::VectorXd& PMLData, double& lambda)
{
	bool isMember = false;
	PMLData = Eigen::VectorXd::Zero(6);
	lambda = _mPMLLda;
	for (int i = 0; i < GetNbrPML(); i++)
	{
		if (domain == _mPML(i))
		{
			PMLType = _mPMLType[i];
			for (int j = 0; j < 6; j++)
				PMLData(j) = _mPMLData(i, j);
			isMember = true;
		}
	}
	return isMember;
}

int Phy_WaveOpticsModel::GetNbrSBC()
{
	return _mSBC.rows();
}
int Phy_WaveOpticsModel::GetSBCDomain(int num)
{
	return _mSBC(num, 0);
}
int Phy_WaveOpticsModel::GetSBCType(int num)
{
	return _mSBC(num, 1);
}
void Phy_WaveOpticsModel::GetSBDir(int num, Eigen::Vector3d& dir)
{
	dir(0) = _mSBCDir(num, 0);
	dir(1) = _mSBCDir(num, 1);
	dir(2) = _mSBCDir(num, 2);
}
void Phy_WaveOpticsModel::GetEinc(int num, std::string& Eincx, std::string& Eincy, std::string& Eincz)
{
	Eincx = _mEincx[num];
	Eincy = _mEincy[num];
	Eincz = _mEincz[num];
}
int Phy_WaveOpticsModel::GetNbrElE()
{
	return _mELE.rows();
}
int Phy_WaveOpticsModel::GetELEDomain(int num)
{
	return _mELE(num);
}

int Phy_WaveOpticsModel::GetNbrMAG()
{
	return _mMAG.rows();
}
int Phy_WaveOpticsModel::GetMAGDomain(int num)
{
	return _mMAG(num);
}

int Phy_WaveOpticsModel::GetNbrBELE()
{
	return _mBELE.rows();
}

void Phy_WaveOpticsModel::GetBELE(Eigen::VectorXi& BELE)
{
	BELE = _mBELE;
}

int Phy_WaveOpticsModel::GetBELEDomain(int num)
{
	return _mBELE(num);
}
void Phy_WaveOpticsModel::GetEb(std::string& Ebx, std::string& Eby, std::string& Ebz)
{
	Ebx = _mEbx;
	Eby = _mEby;
	Ebz = _mEbz;
}

void Phy_WaveOpticsModel::GetCurlEb(std::string& curlEbx, std::string& curlEby, std::string& curlEbz)
{
	curlEbx = _mcurlEbx;
	curlEby = _mcurlEby;
	curlEbz = _mcurlEbz;
}

void Phy_WaveOpticsModel::GetCurlCurlEb(std::string& curlcurlEbx, std::string& curlcurlEby, std::string& curlcurlEbz)
{
	curlcurlEbx = _mcurlcurlEbx;
	curlcurlEby = _mcurlcurlEby;
	curlcurlEbz = _mcurlcurlEbz;
}

void Phy_WaveOpticsModel::GetE0(std::string& E0x, std::string& E0y, std::string& E0z,int num)
{
		E0x = _mE0x[num];
		E0y = _mE0y[num];
		E0z = _mE0z[num];
}

void Phy_WaveOpticsModel::GetH0(std::string& H0x, std::string& H0y, std::string& H0z,int num)
{
		H0x = _mH0x[num];
		H0y = _mH0y[num];
		H0z = _mH0z[num];
}

int Phy_WaveOpticsModel::GetNbrSCD()
{
	return _mSCD.rows();
}
int Phy_WaveOpticsModel::GetSCDDomain(int num)
{
	return _mSCD(num);
}
void Phy_WaveOpticsModel::GetJ0(std::string& J0x, std::string& J0y, std::string& J0z,int num)
{
		J0x = _mJ0x[num];
		J0y = _mJ0y[num];
		J0z = _mJ0z[num];
}

int Phy_WaveOpticsModel::GetNbrMPD()
{
	return _mMPD.size();
}

void Phy_WaveOpticsModel::GetMPD(Eigen::VectorXi& MPD)
{
	MPD = _mMPD;
}

void Phy_WaveOpticsModel::GetMPDData(Eigen::MatrixXd& m)
{
	m = _mMPDData;
}

int Phy_WaveOpticsModel::GetNbrEPD()
{
	return _mEPD.size();
}

void Phy_WaveOpticsModel::GetEPD(Eigen::VectorXi& MPD)
{
	MPD = _mEPD;
}

void Phy_WaveOpticsModel::GetEPDData(Eigen::MatrixXd& p)
{
	p = _mEPDData;
}

int Phy_WaveOpticsModel::GetNbrPortinc()
{
	return _mPortinc.rows();
}
int Phy_WaveOpticsModel::GetNbrPortout()
{
	return _mPortout.rows();
}
int Phy_WaveOpticsModel::GetPortincDomain(int num)
{
	return _mPortinc(num);
}
int Phy_WaveOpticsModel::GetPortoutDomain(int num)
{
	return _mPortout(num);
}
void Phy_WaveOpticsModel::GetPortEinc(std::string& Eincx, std::string& Eincy, std::string& Eincz)
{
	Eincx = _mPortEinc[0];
	Eincy = _mPortEinc[1];
	Eincz = _mPortEinc[2];
}
void Phy_WaveOpticsModel::GetPortEout(std::string& Eoutx, std::string& Eouty, std::string& Eoutz)
{
	Eoutx = _mPortEout[0];
	Eouty = _mPortEout[1];
	Eoutz = _mPortEout[2];
}
void Phy_WaveOpticsModel::GetPortEincCurl(std::string& EincCurlx, std::string& EincCurly, std::string& EincCurlz)
{
	EincCurlx = _mPortEincCurl[0];
	EincCurly = _mPortEincCurl[1];
	EincCurlz = _mPortEincCurl[2];
}
void Phy_WaveOpticsModel::GetPortEoutCurl(std::string& EoutCurlx, std::string& EoutCurly, std::string& EoutCurlz)
{
	EoutCurlx = _mPortEoutCurl[0];
	EoutCurly = _mPortEoutCurl[1];
	EoutCurlz = _mPortEoutCurl[2];
}

int Phy_WaveOpticsModel::GetBeamState()
{
	return _mBeam;
}

void Phy_WaveOpticsModel::GetBeamDir(double& kx, double& ky)
{
	kx = _mkx;
	ky = _mky;
}