#pragma once
#include "SystemCoords.h"

class Moon : private ConvertSC {
private:
	const double gravitational_parameter_Moon{ 4902.799 }; // гравитационный парметр луны
	const double m_scalefactor{ 6378.43817285 };

	double m_sin_πс{0};
	double m_Δλ_c{0};
	double m_β{0};
	double m_Rm{ 0 }; // расстояние до луны в текущий момент времени 
	double m_Ro{ 0 }; // расстояние от луны до объекта в ткущий момент времени


	std::vector<double> m_s{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
	std::vector<double> m_r{ 0.0, 0.0, 0.0, 0.0, 0.0 };
	fundamental_arguments m_cfa{ 0.0, 0.0, 0.0, 0.0, 0.0 };

	Matrix m_F{ 3, 1 }; // вектор ускорения вызванного гравитацией луны

	int calculate_s();
	int calculate_r();
	int calculateСorrecteFundamentalArg();
	int calculate_sin_πс();
	int calculate_Δλ_c();
	int calculate_β();

	int calculateRm();
	int calculateRo(const Matrix& DC_coord_object);
	

public:
	Moon(double input_TDB = 0) :ConvertSC{ input_TDB } {
		calculateDC();
	};
	~Moon() {};

	
	int calculateGEC(double input_TDD);
	Matrix calculateFm(const Matrix& DC_coord_object, double input_TDB);

	friend std::ostream& operator<<(std::ostream& out, Moon& i_moon);
	friend std::ofstream& operator<<(std::ofstream& out, Moon& i_moon);
};

class Sun:private ConvertSC {
private:
	const double AU{ 149597870.691 }; // астрономическая единица
	const double gravitational_parameter_Sun{ 132712438000 };  // гравитационный параметр солнца 
	const double light_pressure{ 4.5606e-6 };
	double m_Rs{0}; // расстояние до солнца в текущий момент времени
	double m_Ro{0}; // расстояний от солнца до обхекта в текщий момент времени

	std::vector<double> m_M{ 0.0,0.0,0.0,0.0,0.0 }; 
	Matrix m_perturbation{ 3,1 }; // возмущение в эклептической долготе, возмущение в эклептической широте, возмущение в расстоянии до Солнца
	Matrix m_F{ 3, 1 }; //вектор ускорения вызванного притяжением солнца
	Matrix m_P{ 3, 1 }; // вектор ускрения возванного давлением солнечного свет 

	//возмущения в долготе обусловленные Венерой
	double DILong_V();
	//возмущение в долготе обусловленные Марсом
	double DILong_M();
	//Возмущения в долготе обусловленные Юпитером и Сатурном
	double DILong_JS();
	//Возмущения в широте
	double DILat();
	//Возмущения в расстоянии обусловленные Венрой 
	double DIR_V();
	//Возмушения в расстоянии обусловленный Марсом
	double DIR_M();
	//Возмущения в расстоянии обусловленные Юпитером и Свтурном
	double DIR_JS();

	int calculateRs();
	int calculateRo(const Matrix& DC_coord_object);
	int calculateAverageAnomalies();
	int calculatePerturbation();

public:
	Sun(double input_TDB = 0) : ConvertSC{ input_TDB } {};
	~Sun() {};
		
	int calculateGEC(double input_TDB);
	Matrix& calculateFs(const Matrix& DC_coord_object, double input_TDB);
	Matrix& calculatePs(const Matrix& DC_coord_object, double kr, double As, double ms, double input_TDB);
};

struct ratio {
	double Rr;
	double Xr;
	double Yr;
	double Zr;
};
struct coord {
	double x;
	double y;
	double z;
};

class Earth : private ConvertSC {
private:
	
	double m_r; // радиус до объекта в текущий момент времени 
	double m_h; // высота полета
	ratio m_ratio; 
	coord m_u;
	uint32_t m_cols; //n
	uint32_t m_rows; //k
	
	Matrix coefficient_С = fill_matrix("coef_c.txt");
	Matrix coefficient_S = fill_matrix("coef_s.txt");
	Matrix m_GDC; // прямуоугольные координаты объекта в земной СК 
	
	Matrix PartialDeriv{4,3}; 
	
	Matrix m_R{ 1, m_cols };
	Matrix m_Partial_R{ 1, m_cols };

	Matrix m_Z{ m_rows, m_cols };
	Matrix m_Partial_Z{ m_rows, m_cols };

	Matrix m_X{ m_rows, 1 };
	Matrix m_Y{ m_rows, 1 };
	Matrix m_Partial_Xx{ m_rows, 1 };
	Matrix m_Partial_Xy{ m_rows, 1 };
	Matrix m_Partial_Yx{ m_rows, 1 };
	Matrix m_Partial_Yy{ m_rows, 1 };

	Matrix m_Q{ m_rows, m_cols };
	Matrix m_Partial_Qx{ m_rows, m_cols };
	Matrix m_Partial_Qy{ m_rows, m_cols };
	
	Matrix m_F{3, 1}; // компонеты ускорения вызванного притяжением земли в земных координатах
	Matrix m_FCS{ 3, 1 }; // компонеты ускорения вызванного притяжением земли в небесных координатах
	
	int calculate_r();
	int calculate_v(const Matrix& GEV);
	Matrix fill_matrix(const char fileName []);
	int setRatio();
	int setF();
	
	int calculateRn();
	int calculatePartialRn();
	int calculateZn0();
	int calculatePartialZn0();

	int calculateZn_k(int k);
	int calculatePartialZn_k(int k);

	int calculateXY_k(int k);
	int claculatePartialXxy_k(int k);
	int claculatePartialYxy_k(int k);

	int calculateQn_k(int k);
	int calculatePartialQn_k(int k);
	
	int calcuclateUkn(int k, int n);
	int calculateF(int k);
	int calculatePartialDeriv();
	int calculateStartParameters();
	int calculateAccelerationByEarth();
public:
	Earth() {};
	Earth(double input_TDB, Matrix input_GCC) : ConvertSC{ input_TDB}, m_GDC{ CC_to_TC(m_precession, m_nutation, input_GCC) }
	{
		calculate_r();
		calculateAccelerationByEarth();
		m_FCS = TC_to_CC(m_F);
	}
	~Earth() {};
	
	const double gravitational_parameter_Earth{ 398600.4415 }; // гравитационный парматер Земли
	const double Radius_Earth = 6378.13630; // средний радиус земли

	Matrix& recalculateAccelerationCC(double input_TDB, Matrix i_GDC) {
		m_GDC = i_GDC;
		recalc(input_TDB);
		calculateAccelerationByEarth();
		Matrix m_CC_to_TC{ CC_to_TC(m_precession, m_nutation, m_GDC) };
		m_FCS = m_F * TC_to_CC(m_CC_to_TC);
		return m_FCS;
	}

};