use chrono::{Duration, NaiveTime};
use glib::Object;
use gtk::{prelude::*, subclass::prelude::*};
use std::{cell::RefCell, f64::consts::PI, rc::Rc};

#[derive(Clone, Debug)]
pub struct Color {
    pub r: f64,
    pub g: f64,
    pub b: f64,
}

#[derive(Clone, Debug)]
pub struct Wedge {
    pub start_angle: f64,
    pub end_angle: f64,
    pub color: Color,
}

#[derive(Default)]
pub struct PieChartPrivate {
    rotation: Rc<RefCell<f64>>,
    wedges: Rc<RefCell<Vec<Wedge>>>,
}

#[glib::object_subclass]
impl ObjectSubclass for PieChartPrivate {
    const NAME: &'static str = "PieChart";
    type Type = PieChart;
    type ParentType = gtk::DrawingArea;
}

impl ObjectImpl for PieChartPrivate {}
impl WidgetImpl for PieChartPrivate {}
impl DrawingAreaImpl for PieChartPrivate {}

glib::wrapper! {
    pub struct PieChart(ObjectSubclass<PieChartPrivate>) @extends gtk::DrawingArea, gtk::Widget;
}

impl PieChart {
    pub fn new(builder: PieChartBuilder) -> Self {
        let s: Self = Object::builder().build();
        s.set_content_width(500);
        s.set_content_height(500);

        *s.imp().rotation.borrow_mut() = builder.rotation;
        *s.imp().wedges.borrow_mut() = builder.wedges;

        s.set_draw_func({
            let s = s.clone();
            move |_, context, width, height| {
                println!("redrawing: {} {}", width, height);
                let radius = width.min(height) as f64 / 2. * 0.9;
                let center_x = (width / 2) as f64;
                let center_y = (height / 2) as f64;

                let rotation = s.imp().rotation.borrow().clone();
                let wedges = s.imp().wedges.borrow().clone();

                context.set_source_rgba(0., 0., 0., 0.);
                let _ = context.paint();

                context.set_line_width(2.);

                wedges.iter().for_each(
                    |Wedge {
                         start_angle,
                         end_angle,
                         color,
                     }| {
                        println!(
                            "wedge: {:.02?} {:.02?} {:.02?}",
                            start_angle, end_angle, color
                        );
                        println!(
                            "wedge: {:.02?} {:.02?} [{:.02?}]",
                            start_angle + rotation,
                            end_angle + rotation,
                            rotation
                        );
                        context.move_to(center_x, center_y);
                        context.set_source_rgb(color.r, color.g, color.b);
                        context.arc(
                            center_x,
                            center_y,
                            radius,
                            start_angle + rotation,
                            end_angle + rotation,
                        );
                        let _ = context.fill();
                    },
                );

                context.set_source_rgb(1., 1., 1.);
                context.arc(center_x, center_y, radius, 0., 2. * PI);
                let _ = context.stroke();
            }
        });

        s
    }

    pub fn set_rotation(&mut self, rotation: f64) {
        *self.imp().rotation.borrow_mut() = rotation;
        self.queue_draw();
    }

    pub fn add_wedge(&mut self, wedge: Wedge) {
        (*self.imp().wedges.borrow_mut()).push(wedge);
        self.queue_draw();
    }

    pub fn builder() -> PieChartBuilder {
        PieChartBuilder {
            rotation: 0.,
            wedges: vec![],
        }
    }
}

pub struct PieChartBuilder {
    rotation: f64,
    wedges: Vec<Wedge>,
}

impl PieChartBuilder {
    pub fn rotation(mut self, rotation: f64) -> Self {
        self.rotation = rotation;
        self
    }

    pub fn wedges(mut self, wedges: Vec<Wedge>) -> Self {
        self.wedges = wedges;
        self
    }

    pub fn build(self) -> PieChart {
        PieChart::new(self)
    }
}