#include "ComponentForModulation.h"
#include <iomanip>

double scalling = 0.00001f;
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
	if (scalling > 1E-9)
		scalling += yoffset / abs(yoffset) * 1E-7;
	else if (yoffset > 0)
		scalling += 1E-6;
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
	std::cout << key << std::endl;
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
		glfwSetWindowShouldClose(window, GL_TRUE);
}


void coord_axis(axis draw_axis, Shader& _Shader){
	std::vector<GLfloat> m_axis; //{x, y, z, color_x, color, y, color_z}
	switch (draw_axis)
	{
	case _OX: m_axis = { -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0 }; break;
	case _OY: m_axis = { 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0 }; break;
	case _OZ: m_axis = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0 }; break;
	}
	
	GLuint VBO, VAO;
	_Shader.Use();
	glGenBuffers(1, &VBO);
	glGenVertexArrays(1, &VAO);

	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, m_axis.size() * sizeof(GLfloat), &m_axis.front(), GL_STREAM_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);

	glDrawArrays(GL_LINE_STRIP, 0, m_axis.size() / 6);
	glBindVertexArray(0);
	glDeleteBuffers(1, &VBO);
	glDeleteVertexArrays(1, &VAO);
}

void draw_line(GLfloat p1_1, GLfloat p1_2, GLfloat p2_1, GLfloat p2_2, Shader _Shader) {
	std::vector<GLfloat> line{ p1_1, p1_2, 0.0f, 0.5f, 0.5f, 0.5f, p2_1, p2_2, 0.0f, 0.5f, 0.5f, 0.5f };
	_Shader.Use();
	GLuint VBO, VAO; 
	glGenBuffers(1, &VBO);
	glGenVertexArrays(1, &VAO);

	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, line.size() * sizeof(GLfloat), &line.front(), GL_STREAM_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);

	glDrawArrays(GL_LINE_STRIP, 0, line.size() / 6);
	glBindVertexArray(0);
	glDeleteBuffers(1, &VBO);
	glDeleteVertexArrays(1, &VAO);
}


void draw_plot_OXY(Shader& _Shader)
{	
	coord_axis(_OX, _Shader);
	coord_axis(_OY, _Shader);
	for (short i = -10; i < 11; i += 2) {
		draw_line(-1.0f, i * 0.1f, 1.0f, i * 0.1f, _Shader);
		draw_line(i * 0.1f, -1.0f, i * 0.1f, 1.0f, _Shader);
	}

}

void modulation(Satellite& sat, double step_time, double end, std::vector<GLfloat>& DCS, std::vector<GLfloat>& DVS) {
	if (step_time <= end) {
		//�������������� �� ���� ���
		sat.integration_step(step_time, 60);
		GLfloat R = sat.getRadius();
		GLfloat omega = sat.getU();
		std::vector<GLfloat> buff; // ��������� ����������
		//�������������� ���������, � �������
		buff = { float(sat.getDCS().at(0, 0)), float(sat.getDCS().at(1, 0)), 0.0f, 0.5f, 0.0f, 0.5f };
		//������� 
		DCS.insert(DCS.end(), buff.begin(), buff.end());
		////�������������� �������� ���������, � �������
		//buff = { float(sat.getDVS().at(0, 0)), float(sat.getDVS().at(1, 0)), float(sat.getDVS().at(2, 0)), 0.0f, 0.0f, 1.0f };
		////�������
		//DVS.insert(DVS.end(), buff.begin(), buff.end());
		//std::cout << "angle = " << cos(omega) << " sin = " << sin(omega) << std::endl;
	}
}

void draw_modulation(std::vector<GLfloat>& DCS, std::vector<GLfloat>& DVS, Shader& _Shader) {
	GLuint VBO, VAO;
	_Shader.Use();

	glm::mat4 scale{1.0f};
	scale = glm::scale(scale, glm::vec3(scalling, scalling, scalling));
	GLuint scaleLoc = glGetUniformLocation(_Shader.Id, "scale");

	glGenBuffers(1, &VBO);
	glGenVertexArrays(1, &VAO);

	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);

 	
	glBufferData(GL_ARRAY_BUFFER, DCS.size() * sizeof(GLfloat), &DCS.front(), GL_STREAM_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);

	glUniformMatrix4fv(scaleLoc, 1, GL_FALSE, glm::value_ptr(scale));

	glDrawArrays(GL_LINE_STRIP, 0, DCS.size() / 6);
	glBindVertexArray(0);
	glDeleteBuffers(1, &VBO);
	glDeleteVertexArrays(1, &VAO);
}