/***************************************
 * File: WhereAmI.h
 * C++ Starter Code for CS106L "Where Am I?" assignment.
 * Original assignment design by Jerry Cain and Nick Parlante
 *
 * Last Modified: Wednesday, March 5 by htiek
 *
 * This file exposes the function prototypes and class definitions you will
 * be using for the Where Am I? assignment.  Be sure to read over this file
 * to see what prewritten code is available to you, since we've written some
 * of the more tedious (input) or difficult (circle intersection) functions
 * for you.
 */

#ifndef __whereami_included__
#define __whereami_included__

#include <iostream>
#include <vector>
using namespace std;

/* Type: pointT
 * A single point in 2-D space.  We've provided a working < operator so
 * that you can store pointTs in sets or maps if you so choose.
 */
struct pointT
{
	double x, y;

	/* Empty constructor necessary since utility constructor will
	 * override the default.
	 */
	pointT() {}

	/* Utility constructor: pointT(double x, double y)
	 * Constructs a new pointT with the specified x and y coordinates.
	 */
	pointT(double newX, double newY) : x(newX), y(newY) {}

	/* operator< for use in sort or associative containers. */
	bool operator< (const pointT &other) const;
};

/* Type: circleT
 * A point and a radius bundled into a single struct.
 */
struct circleT
{
	double radius;
	pointT pt;	

	/* Empty constructor necessary since utility constructor will
	 * override the default.
	 */
	circleT() {}

	/* Utility constructor: pointT(double x, double y)
	 * Constructs a new pointT with the specified x and y coordinates.
	 */
	circleT(double newRadius, const pointT &newPt) :
          pt(newPt), radius(newRadius) {}

	/* operator< for use in sort or associative containers. */
	bool operator< (const circleT &other) const;
};


/* Function: ComputeDistance
 * Computes the distance between two pointTs.  Note that the parameters
 * are not by reference, so you can make this function adaptable with
 * ptr_fun.
 *
 * @param one One of the points to compute the distance between.
 * @param two The other point to get the distance between
 * @return The distance between the two points.
 */
double ComputeDistance(pointT one, pointT two);

/* Function: GenerateAllGuesses
 * Given a vector of distances to points and a vector of points, returns a
 * vector of vectors of circleTs representing all lists of guesses of
 * which distances correspond to which stars.  This function assumes that
 * there are more points than distances and will cause a runtime error
 * otherwise.  It also will cause an error if either vector is empty.
 *
 * @param points The points in 2-D space.
 * @param distances The distances from your current location to those points.
 * @return A vector<vector<circleT> > of all guesses about which distances go with which points.
 */
vector<vector<circleT> > GenerateAllGuesses(const vector<pointT> &points, const vector<double> &distances);

/* Function: ReadDistances
 * Reads in a vector of distances from your location to the various points.
 *
 * @return A vector<double> of distances to the various points.
 */
vector<double> ReadDistances();

/* Function: ReadPoints
 * Reads in a vector of points in space, rejecting duplicates.
 *
 * @param numPoints The minimum number of points to read in.
 * @return A vector<double> of points in space.
 */
vector<pointT> ReadPoints(unsigned numPoints);

/* Function: ComputeIntersectionPoints
 * Given two circles, computes the intersection points and returns them as a
 * vector<pointT>.  If the two circles are identical, the function will cause
 * a runtime error.  The function will always return either zero or two points,
 * duplicating a point if the two circles are tangent to one another.
 *
 * @param one The first circle to intersect.
 * @param two The second circle to intersect.
 * @return A vector<pointT> of the intersection points of the two circles.
 */
vector<pointT> ComputeIntersectionPoints(const circleT &one, const circleT &two);

/* Function: GetNumPoints
 * Returns the number of points to read in.
 *
 * @param minPoints The minimum number of points to read.
 * @return The number of points to read.
 */
unsigned GetNumPoints(unsigned minPoints);

/* Utility stream insertion operators for the pointT, circleT, and pair class. */
ostream& operator <<(ostream &out, const pointT &pt);
ostream& operator <<(ostream &out, const circleT &circle);
template<typename First, typename Second>
ostream& operator <<(ostream &out, const pair<First, Second> &thePair)
{
	return (out << '(' << thePair.first << ", " << thePair.second << ')');
}

#endif
