#pragma once

#include"../Eigen/Dense"
#include"PortModeData.h"

#include<complex>
#include<string>
#include<vector>

class Phy_WaveOpticsModel
{
public:
	struct PbcGroupConfig
	{
		Eigen::MatrixXi pbc;
		Eigen::VectorXcd data;
		std::vector<Eigen::VectorXi> srcDomains;
		std::vector<Eigen::VectorXi> dstDomains;
		Eigen::VectorXd angle;
		Eigen::MatrixXd waveVec;
	};

	Phy_WaveOpticsModel();

	void GetPhy();

	int GetNbrPEC();
	int GetPECDomain(int num);

	int GetNbrPBC();
	int GetNbrPBCGroups() const;
	int GetNbrPBCInGroup(int group) const;
	int GetSrcDomain(int num);
	int GetDstDomain(int num);
	std::complex<double> GetPBCPhi(int num);
	std::complex<double> GetPBCPhi(int group, int num) const;
	void GetSrcDomainList(int num, Eigen::VectorXi& domains);
	void GetSrcDomainList(int group, int num, Eigen::VectorXi& domains) const;
	void GetDstDomainList(int num, Eigen::VectorXi& domains);
	void GetDstDomainList(int group, int num, Eigen::VectorXi& domains) const;
	double GetPBCAngle(int num);
	double GetPBCAngle(int group, int num) const;
	void GetPBCWaveVec(int num, Eigen::Vector3d& waveVec);
	void GetPBCWaveVec(int group, int num, Eigen::Vector3d& waveVec) const;

	int GetNbrPML();
	int GetPMLEdge(int num);
	void GetPMLDomain(Eigen::VectorXi& PMLDomain);
	bool GetPML(int domain, int& PMLType, Eigen::VectorXd& PMLData);
	bool GetPML(int domain, int& PMLType, Eigen::VectorXd& PMLData, double& lambda);

	int GetNbrSBC();
	int GetSBCDomain(int num);
	int GetSBCType(int num);
	void GetSBDir(int num, Eigen::Vector3d& dir);
	void GetEinc(int num, std::string& Eincx, std::string& Eincy, std::string& Eincz);

	int GetNbrBELE();
	void GetBELE(Eigen::VectorXi& BELE);
	int GetBELEDomain(int num);
	void GetEb(std::string& Ebx, std::string& Eby, std::string& Ebz);
	void GetCurlEb(std::string& curlEbx, std::string& curlEby, std::string& curlEbz);
	void GetCurlCurlEb(std::string& curlcurlEbx, std::string& curlcurlEby, std::string& curlcurlEbz);

	int GetNbrElE();
	int GetELEDomain(int num);
	void GetE0(std::string& E0x, std::string& E0y, std::string& E0z,int num);

	int GetNbrMAG();
	int GetMAGDomain(int num);
	void GetH0(std::string& H0x, std::string& H0y, std::string& H0z,int num);

	int GetNbrSCD();
	int GetSCDDomain(int num);
	void GetJ0(std::string& J0x, std::string& J0y, std::string& J0z,int num);

	int GetNbrMPD();
	void GetMPD(Eigen::VectorXi& MPD);
	void GetMPDData(Eigen::MatrixXd& m);

	int GetNbrEPD();
	void GetEPD(Eigen::VectorXi& EPD);
	void GetEPDData(Eigen::MatrixXd& p);

	int GetNbrPortinc();
	int GetNbrPortout();
	int GetPortincDomain(int num);
	int GetPortoutDomain(int num);
	void GetPortEinc(std::string& Eincx, std::string& Eincy, std::string& Eincz);
	void GetPortEout(std::string& Eoutx, std::string& Eouty, std::string& Eoutz);
	void GetPortEincCurl(std::string& EincCurlx, std::string& EincCurly, std::string& EincCurlz);
	void GetPortEoutCurl(std::string& EoutCurlx, std::string& EoutCurly, std::string& EoutCurlz);

	bool HasNumericPort() const { return _mPortModes.HasModes(); }
	int GetNbrNumericPort() const { return _mPortModes.GetNbrModes(); }
	const PortNumericMode& GetNumericPort(int i) const { return _mPortModes.GetMode(i); }
	PortModeLibrary& MutablePortModes() { return _mPortModes; }

	int GetBeamState();
	void GetBeamDir(double& kx,double& ky);

	void Test_ReadData(std::string str);

	int GetElementOrder() const { return _mElementOrder; }

private:
	Eigen::VectorXi _mPMC;//n*1 ?????????

	Eigen::VectorXi _mPEC;//n*1 ?????????

	std::vector<PbcGroupConfig> _mPBCGroups;

	Eigen::VectorXi _mPML;//n*1 ????????
	Eigen::VectorXi _mPMLType;
	Eigen::VectorXi _mPMLEdge;
	double _mPMLLda;//???????
	Eigen::MatrixXd _mPMLData;//n*6  x0 1/dx y0 1/dy  z0 1/dz ??d??1/d=0

	Eigen::MatrixXi _mSBC;//n*2 ????????? 0??????? 1???????  
	Eigen::MatrixXd _mSBCDir; //n*3
	std::string* _mEincx, * _mEincy, * _mEincz;

	Eigen::VectorXi _mELE;//n*1  ????T
	std::string* _mE0x, *_mE0y, *_mE0z;

	Eigen::VectorXi _mMAG;//n*1  ?????
	std::string* _mH0x, *_mH0y, *_mH0z;

	Eigen::VectorXi _mSCD;//n*1  ??????????
	std::string* _mJ0x, *_mJ0y, *_mJ0z;

	Eigen::VectorXi _mMPD; //n*3 ???????
	Eigen::MatrixXd _mMPDData; //n*3

	Eigen::VectorXi _mEPD; //n*3 ???????
	Eigen::MatrixXd _mEPDData; //n*3

	Eigen::VectorXi _mBELE; //n*1 ??????
	std::string _mEbx, _mEby, _mEbz;
	std::string _mcurlEbx, _mcurlEby, _mcurlEbz;
	std::string _mcurlcurlEbx, _mcurlcurlEby, _mcurlcurlEbz;

	Eigen::VectorXi _mPortinc;//n*1 ?????????
	Eigen::VectorXi _mPortout;//n*1 ?????????
	std::string* _mPortEinc, * _mPortEout, * _mPortEincCurl, * _mPortEoutCurl; //??????????????
	PortModeLibrary _mPortModes;

	int _mBeam = 0;//0??????????? 1?????????
	double _mkx = 0.;//????????kx
	double _mky = 0;//????????ky
	int _mElementOrder = 1;
};
