// G. Hagopian making an ellipse with tangent lines
#define _USE_MATH_DEFINES  //for M_PI

#include <SFML/Graphics.hpp>
#include <random>
#include <iostream>
#include <cmath>
//#include <ctime>
using namespace std;

mt19937 mt_rand(time(0));  //seed the random number generator on the global scope

#define w_width 800
#define w_height 800
#define circleRadius 360
#define maxPoints 1000

// Compute a new random point on the circumference, the midpoint M of the line
// segment connecting that point to the fixed random point on the interior
// then compute where the perpendicular bisector of that line segment intersects
// the circle.  Then draw all lines connecting the vertices in subsequent pairs.
void generateNewEndPts(sf::Vector2f pt, sf::Vertex vertices[], unsigned int keyPresses) {
	//pick random point on big circle
	unsigned int angle = mt_rand() % 360;  // random angle (in degrees)
										   // random point on circumference of a circle of radius 360
										   // centered at (w_width/2,w_height)
	sf::Vector2f rand_pt(circleRadius * cos(angle*M_PI / 180),
		circleRadius * sin(angle*M_PI / 180));

	// Draw the point on the circumference
	sf::CircleShape circumfPt(4);
	circumfPt.setOrigin(2, 2);
	circumfPt.setPosition(rand_pt.x, rand_pt.y);
	circumfPt.setFillColor(sf::Color::Black);
	///w.draw(circumfPt);

	// Construct the M, the midpoint of the line segement connecting 
	// random point on interior with random point on the circumference.
	sf::Vector2f M((pt.x + rand_pt.x) / 2,
		(pt.y + rand_pt.y) / 2);

	// Compute the slope of the perpendicular bisector of that line segment.
	float m = (pt.x - rand_pt.x) /
		(rand_pt.y - pt.y);
	// Compute the coefficents of the quadratic equation that finds
	// where the circle intersects the perpendicular bisector.
	float a = 1 + m * m;
	float b = 2 * m*(M.y - m * M.x);
	//float c = (M.y - m * M.x)*(M.y - m * M.x) - 129600;
	float c = m * m*M.x*M.x - 2 * m*M.x*M.y + M.y*M.y - 129600;
	// Compute the discriminant and use the QF to find coordinates
	//      (u1,v1) and (u2,v2) 
	// of new points
	float D = b * b - 4 * a*c;  // The discriminant
	float u1 = (-b + sqrt(D)) / (2 * a);
	float u2 = (-b - sqrt(D)) / (2 * a);
	float v1 = M.y + m * (u1 - M.x);
	float v2 = M.y + m * (u2 - M.x);
	vertices[2 * keyPresses] = sf::Vertex(sf::Vector2f(400 + u1, 400 + v1), sf::Color::Red, sf::Vector2f(0, 0));
	vertices[2 * keyPresses + 1] = sf::Vertex(sf::Vector2f(400 + u2, 400 + v2), sf::Color::Red, sf::Vector2f(0, 0));
}

int main() {
	// Make a window that is 800 by 200 pixels
	// And has the title "Hello from SFML"
	sf::RenderWindow window(sf::VideoMode(w_width, w_height), "Ellipse From Tangents");
	window.setFramerateLimit(20);
	unsigned int keyPresses{ 0 };

	//Construct the big circle
	sf::CircleShape circle(circleRadius, 60); //radius = 360, 60-gon
	circle.setOrigin(circleRadius, circleRadius); // handle at center
	circle.setPosition(w_width/2, w_height/2); // center in the window
	circle.setOutlineColor(sf::Color::Cyan);
	circle.setFillColor(sf::Color::Cyan);

	//Pick a random point on the interior
	unsigned int angle = mt_rand() % 360;  // random angle in degrees
	unsigned int dist = mt_rand() % circleRadius; // random distance from the center less than radius
	sf::Vector2f rand_pt(dist*cos(angle*M_PI / 180), dist*sin(angle*M_PI / 180));
	sf::CircleShape point(8);
	point.setOrigin(4, 4);
	point.setPosition(w_width/2 + rand_pt.x, w_height/2 + rand_pt.y);
	point.setFillColor(sf::Color::Red);

	//Create the vertex array where we'll store the endpoints of the line segment we draw
	sf::Vertex vertices[maxPoints];

	// This "while" loop goes round and round- perhaps forever
	while (window.isOpen()) {
		// The next 5 lines detects and responds to a request to close the window
		sf::Event event;
		while (window.pollEvent(event)) {
			if (event.type == sf::Event::Closed)
				window.close();
		}
		// Clear everything from the last run of the while loop
		window.clear();

		// Draw our circle and point
		window.draw(circle);
		window.draw(point);
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) {
			generateNewEndPts(sf::Vector2f(rand_pt.x, rand_pt.y),
				vertices, keyPresses);
			++keyPresses;
		}
		// draw it
		window.draw(vertices, 2 * keyPresses, sf::Lines);

		// Show everything we just drew
		window.display();
	}// This is the end of the "while" loop

	return 0;
}