use std::fmt;

#[derive(Clone,Copy)]
struct Point {
    x: f64,
    y: f64
}

fn distance (p1: Point, p2: Point) -> f64 {
    ((p1.x - p2.x).powi(2) + (p1.y - p2.y).powi(2)).sqrt()
}

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({:.4}, {:.4})", self.x, self.y)
    }
}

fn describe_circle(p1: Point, p2: Point, r: f64) {
    let sep = distance(p1, p2);

    if sep == 0. {
        if r == 0. {
            println!("No circles can be drawn through {}", p1);
        } else {
            println!("Infinitely many circles can be drawn through {}", p1);
        }
    } else if sep == 2.0 * r {
        println!("Given points are opposite ends of a diameter of the circle with center ({:.4},{:.4}) and r {:.4}",
                (p1.x+p2.x) / 2.0, (p1.y+p2.y) / 2.0, r);
    } else if sep > 2.0 * r {
        println!("Given points are farther away from each other than a diameter of a circle with r {:.4}", r);
    } else {
        let mirror_dist = (r.powi(2) - (sep / 2.0).powi(2)).sqrt();

        println!("Two circles are possible.");
        println!("Circle C1 with center ({:.4}, {:.4}), r {:.4} and Circle C2 with center ({:.4}, {:.4}), r {:.4}",
                ((p1.x + p2.x) / 2.0) + mirror_dist * (p1.y-p2.y)/sep, (p1.y+p2.y) / 2.0 + mirror_dist*(p2.x-p1.x)/sep,
                r,
                (p1.x+p2.x) / 2.0 - mirror_dist*(p1.y-p2.y)/sep, (p1.y+p2.y) / 2.0 - mirror_dist*(p2.x-p1.x)/sep, r);
    }
}

fn main() {
    let points: Vec<(Point, Point)> = vec![
        (Point { x: 0.1234, y: 0.9876 }, Point { x: 0.8765, y: 0.2345 }),
        (Point { x: 0.0000, y: 2.0000 }, Point { x: 0.0000, y: 0.0000 }),
        (Point { x: 0.1234, y: 0.9876 }, Point { x: 0.1234, y: 0.9876 }),
        (Point { x: 0.1234, y: 0.9876 }, Point { x: 0.8765, y: 0.2345 }),
        (Point { x: 0.1234, y: 0.9876 }, Point { x: 0.1234, y: 0.9876 })
    ];
    let radii: Vec<f64> = vec![2.0, 1.0, 2.0, 0.5, 0.0];

    for (p, r) in points.into_iter().zip(radii.into_iter()) {
        println!("\nPoints: ({}, {}), Radius: {:.4}", p.0, p.1, r);
        describe_circle(p.0, p.1, r);
    }
}