#pragma once
#include"../Eigen/Sparse"
#include <string>

struct EigenSolver_Param
{
	int A_n;//dimension of matrix A
	int B_n;//dimension of matrix B
	int A_nzero;//non-zero element number of matrix A 
	int B_nzero;//non-zero element number of matrix B
	double target;//search eigenvalue
};


class Solver_EigenMode
{
public:
	void GetSolver(std::string input);

	void GetRealFlag(bool flag);
	void SetParam(Eigen::SparseMatrix<double, Eigen::RowMajor>* A_real,
		Eigen::SparseMatrix<double, Eigen::RowMajor>* B_real,
		Eigen::SparseMatrix<double, Eigen::RowMajor>* P_real, double target);
	void SetParam(Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* A_complex,
		Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* B_complex,
		Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* P_complex, double target);
	void Run(Eigen::MatrixXcd* x, Eigen::VectorXcd* lambda);
	
	double GetLda0();
	double GetSearchValue();
	int GetNbrMode();

private:
	int _mNbrMode = 6;//模式数目
	double _mSearchValue = 1;//搜索值-有效折射率
	double _mLda0 = 1;//真空波长
	int _mPreproType = 0;//重排序类型

	bool _mIsReal;

	EigenSolver_Param _mParam;
	Eigen::SparseMatrix<double, Eigen::RowMajor>* _mA_real;
	Eigen::SparseMatrix<double, Eigen::RowMajor>* _mB_real;
	Eigen::SparseMatrix<double, Eigen::RowMajor>* _mP_real;
	Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* _mA_complex;
	Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* _mB_complex;
	Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* _mP_complex;
};

class Solver_EigenFreq
{
public:
	void GetSolver(std::string input);

	void GetRealFlag(bool flag);
	void SetParam(Eigen::SparseMatrix<double, Eigen::RowMajor>* A_real,
		Eigen::SparseMatrix<double, Eigen::RowMajor>* B_real,
		Eigen::SparseMatrix<double, Eigen::RowMajor>* P_real, double target);
	void SetParam(Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* A_complex,
		Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* B_complex,
		Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* P_complex, double target);
	void Run(Eigen::MatrixXcd* x, Eigen::VectorXcd* lambda);

	int GetElectricType();
	int GetNbrMode();
	double GetSearchValue();

      void Test_OutputX(Eigen::VectorXcd* x);

private:
	int _mNbrMode = 6;//模式数目
	double _mSearchValue = 3.0E8;//搜索值-本征频率
	int _mPreproType = 0; //重排序类型
	int _mElectricType = 0; //求解电场类型 0-Et 1-Ez 2-E 

	bool _mIsReal;

	EigenSolver_Param _mParam;
	Eigen::SparseMatrix<double, Eigen::RowMajor>* _mA_real;
	Eigen::SparseMatrix<double, Eigen::RowMajor>* _mB_real;
	Eigen::SparseMatrix<double, Eigen::RowMajor>* _mP_real;
	Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* _mA_complex;
	Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* _mB_complex;
	Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* _mP_complex;
};

class Solver_LdaDom
{
public:
	void GetSolver(std::string input);
	void GetSolver2(std::string input);

	void GetRealFlag(bool flag);
	void SetParam(Eigen::SparseMatrix<double, Eigen::RowMajor>* A_real,
		Eigen::VectorXd* B_real,Eigen::SparseMatrix<double, Eigen::RowMajor>* P_real);
	void SetParam(Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* A_complex,
		Eigen::VectorXcd* B_complex,Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* P_complex);
	void Run(Eigen::VectorXcd* x);

	double GetLda0();
	int GetElectricType();

	void Test_OutputX(Eigen::VectorXcd* x);

private:
	double _mLda0 = 1;//真空波长
	int _mElectricType = 0;//求解电场类型 0-Et 1-Ez 2-E 

	bool _mIsReal;

	struct LdaDomSolver_Param
	{
		int A_n;//dimension of matrix A
		int A_nzero;//non-zero element number of matrix A 
	};
	LdaDomSolver_Param _mParam;
	Eigen::SparseMatrix<double, Eigen::RowMajor>* _mA_real;
	Eigen::VectorXd* _mB_real;
	Eigen::SparseMatrix<double, Eigen::RowMajor>* _mP_real;
	Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* _mA_complex;
	Eigen::VectorXcd* _mB_complex;
	Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>* _mP_complex;


};
