// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    anyhow::Error,
    carnelian::{
        color::Color,
        input::{self},
        make_app_assistant,
        render::*,
        App, AppAssistant, Point, Size, ViewAssistant, ViewAssistantContext, ViewAssistantPtr,
        ViewKey,
    },
    euclid::{
        default::{Rect, Transform2D, Vector2D},
        point2, size2, vec2, Angle,
    },
    fidl_fuchsia_hardware_input as hid,
    fuchsia_trace::duration,
    fuchsia_zircon::{self as zx, AsHandleRef, Event, Signals, Time},
    itertools::izip,
    rand::{thread_rng, Rng},
    std::{
        collections::{BTreeMap, VecDeque},
        f32, fs,
        ops::Range,
        time::Duration,
    },
};

const BACKGROUND_COLOR: Color = Color { r: 255, g: 255, b: 255, a: 255 };

// Stroke constants.
const STROKE_START_RADIUS: f32 = 0.25;
const STROKE_RADIUS_ADJUSTMENT_AMOUNT: f32 = 0.1;
const MAX_STROKES: usize = 1000;

// Toolbar constants.
const TOOL_RADIUS: f32 = 25.0;
const TOOL_PADDING: f32 = 12.5;

// Color palette constants.
const COLORS: [Color; 6] = [
    Color { r: 0, g: 0, b: 0, a: 255 },
    Color { r: 255, g: 255, b: 255, a: 255 },
    Color { r: 187, g: 74, b: 72, a: 205 },
    Color { r: 225, g: 210, b: 92, a: 205 },
    Color { r: 61, g: 133, b: 177, a: 205 },
    Color { r: 36, g: 128, b: 108, a: 205 },
];

// Pencil constants.
const PENCILS: [f32; 3] = [1.5, 3.0, 10.0];

// Delay before starting to draw flowers after clearing the screen.
const FLOWER_DELAY_SECONDS: i64 = 10;

fn lerp(t: f32, p0: Point, p1: Point) -> Point {
    point2(p0.x * (1.0 - t) + p1.x * t, p0.y * (1.0 - t) + p1.y * t)
}

trait InkPathBuilder {
    fn line_to(&mut self, p: Point);
    fn cubic_to(&mut self, p0: Point, p1: Point, p2: Point, p3: Point, offset: Vector2D<f32>) {
        let deviation_x = (p0.x + p2.x - 3.0 * (p1.x + p2.x)).abs();
        let deviation_y = (p0.y + p2.y - 3.0 * (p1.y + p2.y)).abs();
        let deviation_squared = deviation_x * deviation_x + deviation_y * deviation_y;

        const PIXEL_ACCURACY: f32 = 0.25;

        if deviation_squared < PIXEL_ACCURACY {
            self.line_to(point2(p3.x, p3.y) + offset);
            return;
        }

        const TOLERANCE: f32 = 3.0;

        let subdivisions = 1 + (TOLERANCE * deviation_squared).sqrt().sqrt().floor() as usize;
        let increment = (subdivisions as f32).recip();

        let mut t = 0.0;

        for _ in 0..subdivisions - 1 {
            t += increment;
            let p_next = lerp(
                t,
                lerp(t, lerp(t, p0, p1), lerp(t, p1, p2)),
                lerp(t, lerp(t, p1, p2), lerp(t, p2, p3)),
            );

            self.line_to(point2(p_next.x, p_next.y) + offset);
        }
        self.line_to(point2(p3.x, p3.y) + offset);
    }
}

struct PointPathBuilder<'a> {
    points: &'a mut Vec<Point>,
}

impl<'a> PointPathBuilder<'a> {
    fn new(points: &'a mut Vec<Point>) -> Self {
        Self { points }
    }
}

impl<'a> InkPathBuilder for PointPathBuilder<'a> {
    fn line_to(&mut self, p: Point) {
        self.points.push(p);
    }
}

struct PathBuilderWrapper<'a> {
    path_builder: &'a mut PathBuilder,
}

impl<'a> PathBuilderWrapper<'a> {
    fn new(path_builder: &'a mut PathBuilder) -> Self {
        Self { path_builder }
    }
}

impl<'a> InkPathBuilder for PathBuilderWrapper<'a> {
    fn line_to(&mut self, p: Point) {
        self.path_builder.line_to(p);
    }

    fn cubic_to(&mut self, _p0: Point, p1: Point, p2: Point, p3: Point, offset: Vector2D<f32>) {
        let p1 = p1 + offset;
        let p2 = p2 + offset;
        let p3 = p3 + offset;
        self.path_builder.cubic_to(p1, p2, p3);
    }
}

struct Circle {
    points: Vec<Point>,
}

impl Circle {
    fn new(center: Point, radius: f32) -> Self {
        let offset = center.to_vector();
        let dist = 4.0 / 3.0 * (f32::consts::PI / 8.0).tan();
        let control_dist = dist * radius;

        let t = point2(0.0, -radius);
        let r = point2(radius, 0.0);
        let b = point2(0.0, radius);
        let l = point2(-radius, 0.0);
        let ct = point2(0.0, -control_dist).to_vector();
        let cr = point2(control_dist, 0.0).to_vector();
        let cb = point2(0.0, control_dist).to_vector();
        let cl = point2(-control_dist, 0.0).to_vector();

        let mut points = Vec::new();
        points.push(t + offset);
        let mut path_builder = PointPathBuilder::new(&mut points);
        path_builder.cubic_to(t, t + cr, r + ct, r, offset);
        path_builder.cubic_to(r, r + cb, b + cr, b, offset);
        path_builder.cubic_to(b, b + cl, l + cb, l, offset);
        path_builder.cubic_to(l, l + ct, t + cl, t, offset);

        Self { points }
    }
}

struct Flower {
    points: Vec<Point>,
}

impl Flower {
    fn new(width: f32, height: f32) -> Self {
        const FLOWER_SIZE: f32 = 100.0;
        const FLOWER_MIN_PETALS: usize = 3;
        const FLOWER_MAX_PETALS: usize = 8;
        const FLOWER_MIN_R1: f32 = 60.0;
        const FLOWER_MAX_R1: f32 = 95.0;
        const FLOWER_MIN_R2: f32 = 20.0;
        const FLOWER_MAX_R2: f32 = 60.0;

        let mut rng = thread_rng();
        let petal_count: usize = rng.gen_range(FLOWER_MIN_PETALS..FLOWER_MAX_PETALS);
        let r1: f32 = rng.gen_range(FLOWER_MIN_R1..FLOWER_MAX_R1);
        let r2: f32 = rng.gen_range(FLOWER_MIN_R2..FLOWER_MAX_R2);
        // Random location in canvas.
        let offset = vec2(
            rng.gen_range(FLOWER_SIZE..width - FLOWER_SIZE),
            rng.gen_range(FLOWER_SIZE..height - FLOWER_SIZE),
        );

        let mut points = Vec::new();
        let u: f32 = rng.gen_range(10.0..FLOWER_SIZE) / FLOWER_SIZE;
        let v: f32 = rng.gen_range(0.0..FLOWER_SIZE - 10.0) / FLOWER_SIZE;
        let dt: f32 = f32::consts::PI / (petal_count as f32);
        let mut t: f32 = 0.0;

        let mut p0 = point2(t.cos() * r1, t.sin() * r1);
        points.push(p0 + offset);
        let mut path_builder = PointPathBuilder::new(&mut points);
        for _ in 0..petal_count {
            let x1 = t.cos() * r1;
            let y1 = t.sin() * r1;
            let x2 = (t + dt).cos() * r2;
            let y2 = (t + dt).sin() * r2;
            let x3 = (t + 2.0 * dt).cos() * r1;
            let y3 = (t + 2.0 * dt).sin() * r1;

            let p1 = point2(x1 - y1 * u, y1 + x1 * u);
            let p2 = point2(x2 + y2 * v, y2 - x2 * v);
            let p3 = point2(x2, y2);
            let p4 = point2(x2 - y2 * v, y2 + x2 * v);
            let p5 = point2(x3 + y3 * u, y3 - x3 * u);
            let p6 = point2(x3, y3);

            path_builder.cubic_to(p0, p1, p2, p3, offset);
            path_builder.cubic_to(p3, p4, p5, p6, offset);

            p0 = p6;
            t += dt * 2.0;
        }

        Self { points }
    }
}

#[derive(Default)]
struct InkAppAssistant;

impl AppAssistant for InkAppAssistant {
    fn setup(&mut self) -> Result<(), Error> {
        Ok(())
    }

    fn create_view_assistant(&mut self, _: ViewKey) -> Result<ViewAssistantPtr, Error> {
        Ok(Box::new(InkViewAssistant::new()))
    }
}

struct InkFill {
    raster: Raster,
    color: Color,
}

impl InkFill {
    fn new(context: &mut Context, color: &Color, points: &Vec<Point>) -> Self {
        let path = {
            let mut path_builder = context.path_builder().unwrap();
            let mut p0 = Point::zero();
            for (i, &p) in points.iter().enumerate() {
                if i == 0 {
                    path_builder.move_to(p);
                    p0 = p;
                } else {
                    path_builder.line_to(p);
                }
            }
            path_builder.line_to(p0);
            path_builder.build()
        };

        let mut raster_builder = context.raster_builder().unwrap();
        raster_builder.add(&path, None);
        let raster = raster_builder.build();

        Self { raster, color: *color }
    }
}

struct Segment {
    path: Path,
    raster: Option<Raster>,
}

struct StrokePoint {
    point: Point,
    normal0: Vector2D<f32>,
    normal1: Vector2D<f32>,
    thickness: f32,
}

struct CurveFitter {
    first_control_points: Vec<Vector2D<f32>>,
    second_control_points: Vec<Vector2D<f32>>,
    end_points: Vec<Vector2D<f32>>,
    coefficients: Vec<f32>,
}

impl CurveFitter {
    fn new() -> Self {
        Self {
            first_control_points: Vec::new(),
            second_control_points: Vec::new(),
            end_points: Vec::new(),
            coefficients: Vec::new(),
        }
    }

    // Takes a set of |points| and generates a fitted curve with two control points in between each
    // point. Returns an iterator to (first control point, second control point, end point)
    // for |range|. These items are ready to be used to build a path using cubic_to().
    //
    // Guided and simplified from
    // https://ovpwp.wordpress.com/2008/12/17/how-to-draw-a-smooth-curve-through-a-set-of-2d-points-with-bezier-methods/
    fn compute_control_points(
        &mut self,
        points: impl Iterator<Item = Point>,
        range: Range<usize>,
    ) -> impl Iterator<Item = (Point, Point, Point)> + '_ {
        duration!(c"gfx", c"CurveFitter::compute_control_points");
        self.end_points.splice(.., points.map(|p| p.to_vector()));
        self.first_control_points.clear();
        self.second_control_points.clear();
        self.coefficients.clear();

        let num_control_points = self.end_points.len() - 1;
        match num_control_points {
            // Do nothing for a single point.
            0 => {}
            // Calculate average for two points.
            1 => {
                let p0 = self.end_points[0];
                let p1 = self.end_points[1];
                self.first_control_points.push((p0 * 2.0 + p1) / 3.0);
                self.second_control_points.push((p0 + p1 * 2.0) / 3.0);
            }
            // Run the algorithm to generate two control points.
            _ => {
                // Compute first control points.
                let mut b: f32 = 2.0;
                let p0 = self.end_points[0];
                let p1 = self.end_points[1];
                let mut rhs = p0 + p1 * 2.0;
                self.coefficients.push(0.0);
                self.first_control_points.push(rhs / b);
                for i in 1..num_control_points - 1 {
                    self.coefficients.push(1.0 / b);
                    b = 4.0 - self.coefficients[i];
                    let p = self.end_points[i];
                    let p_next = self.end_points[i + 1];
                    rhs = p * 4.0 + p_next * 2.0;
                    self.first_control_points.push((rhs - self.first_control_points[i - 1]) / b);
                }
                self.coefficients.push(1.0 / b);
                let p_prev = self.end_points[num_control_points - 1];
                let p_last = self.end_points[num_control_points];
                rhs = (p_prev * 8.0 + p_last) / 2.0;
                b = 3.5 - self.coefficients[num_control_points - 1];
                self.first_control_points
                    .push((rhs - self.first_control_points[num_control_points - 2]) / b);

                // Back substitution.
                for i in 1..num_control_points {
                    let fcp = self.first_control_points[num_control_points - i - 1];
                    let fcp_next = self.first_control_points[num_control_points - i];
                    let c = self.coefficients[num_control_points - i];
                    self.first_control_points[num_control_points - i - 1] = fcp - fcp_next * c;
                }

                // Compute second control points.
                for i in 0..num_control_points - 1 {
                    let p_next = self.end_points[i + 1];
                    let fcp_next = self.first_control_points[i + 1];
                    self.second_control_points.push(p_next * 2.0 - fcp_next);
                }
                let fcp_last = self.first_control_points[num_control_points - 1];
                self.second_control_points.push((p_last + fcp_last) / 2.0);
            }
        }

        izip!(
            self.first_control_points[range.start..range.end - 1].iter().map(|v| v.to_point()),
            self.second_control_points[range.start..range.end - 1].iter().map(|v| v.to_point()),
            self.end_points[range.start + 1..range.end].iter().map(|v| v.to_point())
        )
    }
}

struct InkStroke {
    points: Vec<StrokePoint>,
    segments: Vec<(usize, Segment)>,
    color: Color,
    thickness: f32,
    transform: Transform2D<f32>,
    curve_fitter: CurveFitter,
}

impl InkStroke {
    fn new(color: Color, thickness: f32, transform: Transform2D<f32>) -> Self {
        Self {
            points: Vec::new(),
            segments: Vec::new(),
            color,
            thickness,
            transform,
            curve_fitter: CurveFitter::new(),
        }
    }

    fn raster(context: &mut Context, path: &Path, transform: &Transform2D<f32>) -> Raster {
        let mut raster_builder = context.raster_builder().unwrap();
        raster_builder.add(path, Some(transform));
        raster_builder.build()
    }

    fn push_point(&mut self, p: &Point) {
        match self.points.len() {
            // Just add the first point.
            0 => self.points.push(StrokePoint {
                point: *p,
                normal0: Vector2D::zero(),
                normal1: Vector2D::zero(),
                thickness: STROKE_START_RADIUS,
            }),
            // Add second point and compute the normal for line between points.
            1 => {
                let p0 = self.points.pop().unwrap();
                let e = p0.point - *p;
                let n = vec2(-e.y, e.x).normalize();
                self.points.push(StrokePoint {
                    point: p0.point,
                    normal0: n,
                    normal1: n,
                    thickness: p0.thickness,
                });
                self.points.push(StrokePoint {
                    point: *p,
                    normal0: n,
                    normal1: n,
                    thickness: STROKE_START_RADIUS,
                });
            }
            // Add new point, compute the normal, and the average normal for last
            // two lines. We also make a limited adjustment to the average normal
            // distance to maintain the correct line thickness.
            _ => {
                let p1 = self.points.pop().unwrap();
                let p0 = self.points.pop().unwrap();
                let e = p1.point - *p;
                let n = vec2(-e.y, e.x).normalize();
                let mut t1 = (p1.normal1 + n) / 2.0;
                let l = t1.square_length().max(0.1);
                t1 *= 1.0 / l;
                self.points.push(StrokePoint {
                    point: p0.point,
                    normal0: p0.normal0,
                    normal1: p0.normal1,
                    thickness: p0.thickness,
                });
                self.points.push(StrokePoint {
                    point: p1.point,
                    normal0: p1.normal1,
                    normal1: t1,
                    thickness: p1.thickness,
                });
                self.points.push(StrokePoint {
                    point: *p,
                    normal0: n,
                    normal1: n,
                    thickness: STROKE_START_RADIUS,
                });
            }
        }
    }

    fn push_segment(&mut self, context: &mut Context, i0: usize, i1: usize) {
        let path = {
            let mut path_builder = context.path_builder().unwrap();

            //
            // Convert stroke to fill and compute a bounding box.
            //
            let mut p_draw_start = Point::zero();
            if i1 > i0 {
                p_draw_start =
                    self.points[i0].point + self.points[i0].normal1 * self.points[i0].thickness;
                path_builder.move_to(p_draw_start);
            }

            for p in self.curve_fitter.compute_control_points(
                self.points.iter().map(|p| p.point + p.normal1 * p.thickness),
                i0..i1,
            ) {
                path_builder.cubic_to(p.0, p.1, p.2);
            }

            let p_first = &self.points.first().unwrap();
            let p_last = &self.points.last().unwrap();

            macro_rules! cap {
                ( $p:expr, $w:expr ) => {
                    let offset = $p.point.to_vector();
                    let n = vec2($p.normal0.y, -$p.normal0.x);
                    let p0 = Point::zero() + $p.normal1 * $w;
                    let p1 = Point::zero() - n * $w;
                    let p2 = Point::zero() - $p.normal1 * $w;

                    let dist = 4.0 / 3.0 * (f32::consts::PI / 8.0).tan();
                    let control_dist = dist * $w;

                    let c0 = p0 - n * control_dist;
                    let c1 = p1 + $p.normal1 * control_dist;
                    let c2 = p1 - $p.normal1 * control_dist;
                    let c3 = p2 - n * control_dist;

                    let mut wrapper = PathBuilderWrapper::new(&mut path_builder);
                    wrapper.cubic_to(p0, c0, c1, p1, offset);
                    wrapper.cubic_to(p1, c2, c3, p2, offset);
                };
            }

            // Produce end-cap if at the end of the line and not connected to first point.
            if i1 == self.points.len() && p_first.point != p_last.point {
                cap!(p_last, p_last.thickness);
            }
            // Walk from point i1 back to i0 and offset by radius at each point.
            if i1 > i0 {
                let p = &self.points[i1 - 1];
                path_builder.line_to(p.point - p.normal1 * p.thickness);
            }

            for p in self.curve_fitter.compute_control_points(
                self.points.iter().rev().map(|p| p.point - p.normal1 * p.thickness),
                self.points.len() - i1..self.points.len() - i0,
            ) {
                path_builder.cubic_to(p.0, p.1, p.2);
            }

            // Produce start-cap if at the beginning of line and not connected to last point.
            if i0 == 0 && p_first.point != p_last.point {
                cap!(p_first, -p_first.thickness);
            }

            path_builder.line_to(p_draw_start);

            path_builder.build()
        };

        self.segments.push((i0, Segment { path, raster: None }));
    }

    fn update_thickness(&mut self, context: &mut Context) {
        assert_eq!(self.points.is_empty(), false);

        // No update needed if last point has correct thickness. This assumes
        // that last point always needs most adjustment.
        if self.points.last().unwrap().thickness == self.thickness {
            return;
        }

        let adjustment_amount = self.thickness * STROKE_RADIUS_ADJUSTMENT_AMOUNT;

        for p in self.points.iter_mut().rev() {
            if p.thickness == self.thickness {
                break;
            }
            p.thickness = if p.thickness > self.thickness {
                (p.thickness - adjustment_amount).max(self.thickness)
            } else {
                (p.thickness + adjustment_amount).min(self.thickness)
            };
        }

        // Remove and get index of first point in last segment.
        let mut i0 = self.segments.pop().map_or(0, |v| v.0);

        // Index of last point with final thickness.
        let i1 = self.points.iter().rposition(|v| v.thickness == self.thickness).unwrap_or(i0);

        const SEGMENT_SIZE: usize = 256;

        // Add segments with final thickness.
        while (i1 - i0) > SEGMENT_SIZE {
            let i = i0 + SEGMENT_SIZE;
            self.push_segment(context, i0, i);
            i0 = i - 1;
        }

        // Add any remaining points to last segment.
        if (self.points.len() - i0) > 0 {
            self.push_segment(context, i0, self.points.len());
        }
    }

    fn update(&mut self, context: &mut Context) -> bool {
        self.update_thickness(context);

        let mut changed = false;
        for (_, segment) in self.segments.iter_mut() {
            if segment.raster.is_none() {
                segment.raster = Some(Self::raster(context, &segment.path, &self.transform));
                changed = true;
            }
        }

        changed
    }

    fn transform(&mut self, transform: &Transform2D<f32>) {
        self.transform = self.transform.then(transform);

        // Re-create rasters during next call to update.
        for (_, segment) in self.segments.iter_mut() {
            segment.raster = None;
        }
    }
}

struct Scene {
    tools: Vec<(InkStroke, InkFill, Point)>,
    strokes: Vec<InkStroke>,
}

impl Scene {
    fn new() -> Self {
        Self { tools: Vec::new(), strokes: Vec::new() }
    }

    fn setup(&mut self, context: &mut Context, size: Size, tools: &Vec<(&Color, &f32)>) {
        const TOOL_SIZE: f32 = (TOOL_RADIUS + TOOL_PADDING) * 2.0;

        // Layout tools at top-center.
        let mut x = size.width / 2.0 - (tools.len() as f32 * TOOL_SIZE) / 2.0;
        let y = TOOL_PADDING * 2.0 + TOOL_RADIUS;
        for (color, size) in tools {
            let center = point2(x, y);
            let circle = Circle::new(center, TOOL_RADIUS);
            let mut stroke =
                InkStroke::new(Color { r: 0, g: 0, b: 0, a: 255 }, 1.0, Transform2D::identity());
            while stroke.points.len() < circle.points.len() {
                let p = &circle.points[stroke.points.len()];
                stroke.push_point(p);
            }
            let circle = Circle::new(center, **size);
            let fill = InkFill::new(context, color, &circle.points);
            self.tools.push((stroke, fill, center));

            x += TOOL_SIZE;
        }
    }

    fn hit_test(&mut self, point: Point) -> Option<usize> {
        for (i, (_, _, center)) in self.tools.iter().enumerate() {
            if (point - *center).length() < TOOL_RADIUS {
                return Some(i);
            }
        }

        None
    }

    fn select_tools(&mut self, indices: &Vec<usize>) {
        for (i, (stroke, _, _)) in self.tools.iter_mut().enumerate() {
            stroke.thickness = if indices.contains(&i) { 2.0 } else { 1.0 };
        }
    }

    fn push_stroke(&mut self, color: Color, radius: f32, p: &Point) {
        let mut stroke = InkStroke::new(color, radius, Transform2D::identity());
        stroke.push_point(p);
        self.strokes.push(stroke);
    }

    fn last_stroke(&mut self) -> Option<&mut InkStroke> {
        self.strokes.last_mut()
    }

    fn clear_strokes(&mut self) {
        self.strokes.clear();
    }

    fn update_tools(&mut self, context: &mut Context) -> Option<Range<usize>> {
        let mut damage: Option<Range<usize>> = None;

        for (i, (stroke, _, _)) in self.tools.iter_mut().enumerate() {
            let changed = stroke.update(context);
            if changed {
                if let Some(damage) = &mut damage {
                    damage.end = i + 1;
                } else {
                    damage = Some(Range { start: i, end: i + 1 });
                }
            }
        }

        damage
    }

    fn update_strokes(&mut self, context: &mut Context) -> Option<Range<usize>> {
        let mut damage: Option<Range<usize>> = None;

        for (i, stroke) in self.strokes.iter_mut().enumerate() {
            let changed = stroke.update(context);
            if changed {
                if let Some(value) = damage.take() {
                    damage = Some(Range { start: value.start, end: i + 1 });
                } else {
                    damage = Some(Range { start: i, end: i + 1 });
                }
            }
        }

        damage
    }

    fn transform(&mut self, transform: &Transform2D<f32>) {
        for stroke in self.strokes.iter_mut() {
            stroke.transform(transform);
        }
    }
}

struct Contents {
    image: Image,
    composition: Composition,
    size: Size,
    tool_damage: Option<Range<usize>>,
    stroke_count: usize,
    stroke_damage: Option<Range<usize>>,
}

impl Contents {
    fn new(image: Image) -> Self {
        let composition = Composition::new(BACKGROUND_COLOR);

        Self {
            image,
            composition,
            size: Size::zero(),
            tool_damage: None,
            stroke_count: 0,
            stroke_damage: None,
        }
    }

    fn update(&mut self, context: &mut Context, scene: &Scene, size: &Size) {
        let clip =
            Rect::new(point2(0, 0), size2(size.width.floor() as u32, size.height.floor() as u32));

        let ext = if self.size != *size {
            self.size = *size;
            self.tool_damage = Some(Range { start: 0, end: scene.tools.len() });
            self.stroke_damage = Some(Range { start: 0, end: scene.strokes.len() });
            RenderExt {
                pre_clear: Some(PreClear { color: BACKGROUND_COLOR }),
                ..Default::default()
            }
        } else {
            RenderExt::default()
        };

        // Update damaged stroke layers.
        if let Some(damage) = self.stroke_damage.take() {
            let layers = scene.strokes[damage.start..damage.end].iter().map(|stroke| Layer {
                raster: stroke
                    .segments
                    .iter()
                    .fold(None, |raster_union: Option<Raster>, segment| {
                        if let Some(raster) = &segment.1.raster {
                            if let Some(raster_union) = raster_union {
                                Some(raster_union + raster.clone())
                            } else {
                                Some(raster.clone())
                            }
                        } else {
                            raster_union
                        }
                    })
                    .unwrap(),
                clip: None,
                style: Style {
                    fill_rule: FillRule::NonZero,
                    fill: Fill::Solid(stroke.color),
                    blend_mode: BlendMode::Over,
                },
            });
            for (i, layer) in layers.enumerate() {
                self.composition.insert(
                    Order::try_from(damage.start + i).unwrap_or_else(|e| panic!("{}", e)),
                    layer,
                );
            }
            // Add more stroke layers if needed.
            if self.stroke_count < scene.strokes.len() {
                self.stroke_count = scene.strokes.len();
            }
        }

        // Remove strokes that are no longer part of the scene.
        while self.stroke_count > scene.strokes.len() {
            self.stroke_count -= 1;
            self.composition
                .remove(Order::try_from(self.stroke_count).unwrap_or_else(|e| panic!("{}", e)));
        }

        // Update damaged tool layers.
        if let Some(damage) = self.tool_damage.take() {
            let layers =
                scene.tools[damage.start..damage.end].iter().flat_map(|(stroke, fill, _)| {
                    std::iter::once(Layer {
                        raster: stroke
                            .segments
                            .iter()
                            .fold(None, |raster_union: Option<Raster>, segment| {
                                if let Some(raster) = &segment.1.raster {
                                    if let Some(raster_union) = raster_union {
                                        Some(raster_union + raster.clone())
                                    } else {
                                        Some(raster.clone())
                                    }
                                } else {
                                    raster_union
                                }
                            })
                            .unwrap(),
                        clip: None,
                        style: Style {
                            fill_rule: FillRule::NonZero,
                            fill: Fill::Solid(stroke.color),
                            blend_mode: BlendMode::Over,
                        },
                    })
                    .chain(std::iter::once(Layer {
                        raster: fill.raster.clone(),
                        clip: None,
                        style: Style {
                            fill_rule: FillRule::NonZero,
                            fill: Fill::Solid(fill.color),
                            blend_mode: BlendMode::Over,
                        },
                    }))
                });

            for (i, layer) in layers.enumerate() {
                self.composition.insert(
                    Order::try_from(MAX_STROKES + damage.start + i)
                        .unwrap_or_else(|e| panic!("{}", e)),
                    layer,
                );
            }
        }

        context.render(&mut self.composition, Some(clip), self.image, &ext);
    }

    fn add_tool_damage(&mut self, range: &Range<usize>) {
        self.tool_damage = Some(if let Some(damage) = self.tool_damage.take() {
            Range { start: range.start.min(damage.start), end: range.end.max(damage.end) }
        } else {
            range.clone()
        });
    }

    fn add_stroke_damage(&mut self, range: &Range<usize>) {
        self.stroke_damage = Some(if let Some(damage) = self.stroke_damage.take() {
            Range { start: range.start.min(damage.start), end: range.end.max(damage.end) }
        } else {
            range.clone()
        });
    }

    fn full_damage(&mut self) {
        // Empty size will trigger a clear during next update.
        self.size = Size::zero();
    }
}

struct Stylus {
    _rpt_id: u8,
    status: u8,
    x: u16,
    y: u16,
}

// TODO: Remove stylus device when supported by carnelian.
struct StylusDevice {
    device: hid::DeviceSynchronousProxy,
    x_max: u16,
    y_max: u16,
}

impl StylusDevice {
    fn open_input_device(path: &str) -> Result<hid::DeviceSynchronousProxy, Error> {
        let (client, server) = zx::Channel::create();
        fdio::service_connect(path, server)?;
        Ok(hid::DeviceSynchronousProxy::new(client))
    }

    fn create() -> Result<StylusDevice, Error> {
        static INPUT_DEVICES_DIRECTORY: &str = "/dev/class/input";
        let path = std::path::Path::new(INPUT_DEVICES_DIRECTORY);
        let entries = fs::read_dir(path)?;
        for entry in entries {
            let entry = entry?;
            let entry_path = entry.path();
            let path = entry_path.to_str().expect("bad path");
            let device = Self::open_input_device(path)?;
            if let Ok(hid::DeviceIds { vendor_id: 0x00002d1f, product_id, .. }) =
                device.get_device_ids(zx::Time::INFINITE)
            {
                // Paradise
                if product_id == 0x00005143 {
                    println!("found stylus at {0}", path);
                    const PARADISE_STYLUS_X_MAX: u16 = 25919;
                    const PARADISE_STYLUS_Y_MAX: u16 = 17279;
                    return Ok(StylusDevice {
                        device,
                        x_max: PARADISE_STYLUS_X_MAX,
                        y_max: PARADISE_STYLUS_Y_MAX,
                    });
                }
                // Slate
                if product_id == 0x0000486c {
                    println!("found stylus at {0}", path);
                    const SLATE_STYLUS_X_MAX: u16 = 26009;
                    const SLATE_STYLUS_Y_MAX: u16 = 17339;
                    return Ok(StylusDevice {
                        device,
                        x_max: SLATE_STYLUS_X_MAX,
                        y_max: SLATE_STYLUS_Y_MAX,
                    });
                }
            }
        }
        Err(std::io::Error::new(std::io::ErrorKind::NotFound, "no touch found").into())
    }

    fn get_events(&mut self) -> Result<Vec<Stylus>, Error> {
        let mut stylus_events = Vec::<Stylus>::new();
        let reports = self.device.read_reports(zx::Time::INFINITE)?;
        let reports = reports.1;
        let mut report_index = 0;
        while report_index < reports.len() {
            let report = &reports[report_index..];
            if report[0] != 6 {
                report_index += 55;
                continue;
            }

            report_index += 20;
            stylus_events.push(Stylus {
                _rpt_id: report[0],
                status: report[1],
                x: report[2] as u16 + ((report[3] as u16) << 8),
                y: report[4] as u16 + ((report[5] as u16) << 8),
            });
        }
        Ok(stylus_events)
    }
}

struct Ink {
    scene: Scene,
    contents: BTreeMap<u64, Contents>,
    pending_pointer_events: VecDeque<input::Event>,
    touch_points: BTreeMap<input::touch::ContactId, Point>,
    stylus_device: Option<StylusDevice>,
    last_stylus_x: u16,
    last_stylus_y: u16,
    last_stylus_point: Option<Point>,
    flower: Option<Flower>,
    flower_start: Time,
    color: usize,
    pencil: usize,
    pan_origin: Vector2D<f32>,
    scale_distance: f32,
    rotation_angle: f32,
    clear_origin: Vector2D<f32>,
}

impl Ink {
    pub fn new(context: &mut Context, size: Size) -> Self {
        let mut scene = Scene::new();

        let color_iter = COLORS.iter().map(|color| (color, &TOOL_RADIUS));
        let pencil_iter = PENCILS.iter().map(|size| (&Color { r: 0, g: 0, b: 0, a: 255 }, size));
        let tools = color_iter.chain(pencil_iter).collect::<Vec<_>>();
        scene.setup(context, size, &tools);
        let color = 0;
        let pencil = 1;
        scene.select_tools(&vec![color, COLORS.len() + pencil]);

        let stylus_device = StylusDevice::create().ok();
        let flower_start = Time::from_nanos(
            Time::get_monotonic()
                .into_nanos()
                .saturating_add(zx::Duration::from_seconds(FLOWER_DELAY_SECONDS).into_nanos()),
        );

        Self {
            scene,
            contents: BTreeMap::new(),
            pending_pointer_events: VecDeque::new(),
            touch_points: BTreeMap::new(),
            stylus_device,
            last_stylus_x: std::u16::MAX,
            last_stylus_y: std::u16::MAX,
            last_stylus_point: None,
            flower: None,
            flower_start,
            color,
            pencil,
            pan_origin: Vector2D::zero(),
            scale_distance: 0.0,
            rotation_angle: 0.0,
            clear_origin: Vector2D::zero(),
        }
    }

    fn update(
        &mut self,
        render_context: &mut Context,
        context: &ViewAssistantContext,
    ) -> Result<(), Error> {
        duration!(c"gfx", c"update");

        let time_now = Time::get_monotonic();
        let size = &context.size;
        let mut full_damage = false;

        // Process touch events.
        let previous_touch_points_count = self.touch_points.len();

        while let Some(event) = self.pending_pointer_events.pop_front() {
            if let input::EventType::Touch(touch_event) = event.event_type {
                self.touch_points.clear();
                for contact in touch_event.contacts.iter() {
                    match contact.phase {
                        input::touch::Phase::Down(point, _) => {
                            self.touch_points.insert(contact.contact_id, point.to_f32());
                        }
                        input::touch::Phase::Moved(point, _) => {
                            self.touch_points.insert(contact.contact_id, point.to_f32());
                        }
                        _ => {}
                    }
                }
            }
        }

        let mut transform = Transform2D::identity();

        // Pan and select color.
        match self.touch_points.len() {
            1 | 2 => {
                let mut origin = Vector2D::zero();
                for (_, point) in &self.touch_points {
                    origin += point.to_vector();
                }
                origin /= self.touch_points.len() as f32;
                if self.touch_points.len() != previous_touch_points_count {
                    if let Some(index) = self.scene.hit_test(origin.to_point()) {
                        if index < COLORS.len() {
                            self.color = index;
                        } else {
                            self.pencil = index - COLORS.len();
                        }
                        self.scene.select_tools(&vec![self.color, COLORS.len() + self.pencil]);
                    }
                    self.pan_origin = origin;
                }
                let distance = origin - self.pan_origin;
                transform = transform.then_translate(distance);
                self.pan_origin = origin;
            }
            _ => {}
        }

        // Rotation & zoom.
        if self.touch_points.len() == 2 {
            let mut iter = self.touch_points.iter();
            let point0 = iter.next().unwrap().1;
            let point1 = iter.next().unwrap().1;

            let origin = (point0.to_vector() + point1.to_vector()) / 2.0;
            transform = transform.then_translate(-origin);

            // Rotation.
            let line = *point0 - *point1;
            let angle = line.x.atan2(line.y);
            if self.touch_points.len() != previous_touch_points_count {
                self.rotation_angle = angle;
            }
            let rotation_angle = angle - self.rotation_angle;
            transform = transform.then_rotate(Angle::radians(rotation_angle));
            self.rotation_angle = angle;

            // Pinch to zoom.
            let distance = (*point0 - *point1).length();
            if distance != 0.0 {
                if self.touch_points.len() != previous_touch_points_count {
                    self.scale_distance = distance;
                }
                let sxsy = distance / self.scale_distance;
                transform = transform.then_scale(sxsy, sxsy);
                self.scale_distance = distance;
            }

            transform = transform.then_translate(origin);
        }

        // Clear using 3 finger swipe across screen.
        if self.touch_points.len() >= 3 {
            let mut origin = Vector2D::zero();
            for (_, point) in &self.touch_points {
                origin += point.to_vector();
            }
            origin /= self.touch_points.len() as f32;
            if self.touch_points.len() != previous_touch_points_count {
                self.clear_origin = origin;
            }
            const MIN_CLEAR_SWIPE_DISTANCE: f32 = 512.0;
            let distance = (origin - self.clear_origin).length();
            if distance >= MIN_CLEAR_SWIPE_DISTANCE {
                self.flower_start =
                    Time::from_nanos(time_now.into_nanos().saturating_add(
                        zx::Duration::from_seconds(FLOWER_DELAY_SECONDS).into_nanos(),
                    ));
                self.flower = None;
                self.scene.clear_strokes();
                full_damage = true;
            }
        }

        if transform != Transform2D::identity() {
            self.scene.transform(&transform);
            full_damage = true;
        }

        // Process stylus device input.
        if let Some(device) = self.stylus_device.as_mut() {
            let reports = device.get_events()?;
            for report in &reports {
                const STYLUS_STATUS_TSWITCH: u8 = 0x01;
                if (report.status & STYLUS_STATUS_TSWITCH) != 0 {
                    if report.x != self.last_stylus_x || report.y != self.last_stylus_y {
                        let point = point2(
                            size.width * report.x as f32 / device.x_max as f32,
                            size.height * report.y as f32 / device.y_max as f32,
                        );

                        // Start new stroke or select color.
                        if self.last_stylus_x == std::u16::MAX
                            || self.last_stylus_y == std::u16::MAX
                        {
                            if let Some(index) = self.scene.hit_test(point) {
                                if index < COLORS.len() {
                                    self.color = index;
                                } else {
                                    self.pencil = index - COLORS.len();
                                }
                                self.scene
                                    .select_tools(&vec![self.color, COLORS.len() + self.pencil]);
                            } else {
                                // Start stroke if we haven't reached the limit.
                                if self.scene.strokes.len() < MAX_STROKES {
                                    self.scene.push_stroke(
                                        COLORS[self.color],
                                        PENCILS[self.pencil],
                                        &point,
                                    );
                                    self.last_stylus_point = Some(point);
                                }
                                // Disable flower demo.
                                self.flower_start = zx::Time::INFINITE;
                                self.flower = None;
                            }
                        }

                        // Update stroke if distance from last point surpassed radius.
                        if let Some(last_stylus_point) = self.last_stylus_point {
                            if (point - last_stylus_point).length() > PENCILS[self.pencil] {
                                self.scene.last_stroke().unwrap().push_point(&point);
                                self.last_stylus_point = Some(point);
                            }
                        }

                        self.last_stylus_x = report.x;
                        self.last_stylus_y = report.y;
                    }
                } else {
                    self.last_stylus_x = std::u16::MAX;
                    self.last_stylus_y = std::u16::MAX;
                    self.last_stylus_point = None;
                }
            }
        }

        // Generate flower when idle after clearing screen.
        if time_now.into_nanos() > self.flower_start.into_nanos() {
            let flower = self.flower.take().unwrap_or_else(|| {
                let flower = Flower::new(size.width, size.height);
                self.scene.push_stroke(COLORS[self.color], PENCILS[self.pencil], &flower.points[0]);
                flower
            });

            // Points per second.
            const SPEED: f32 = 100.0;
            const SECONDS_PER_NANOSECOND: f32 = 1e-9;

            let n = ((time_now.into_nanos() - self.flower_start.into_nanos()) as f32
                * SECONDS_PER_NANOSECOND
                * SPEED) as usize;

            let stroke = self.scene.last_stroke().unwrap();

            // Extend set of points for current stroke.
            while n > stroke.points.len() && stroke.points.len() < flower.points.len() {
                let p = &flower.points[stroke.points.len()];
                stroke.push_point(p);
            }

            if stroke.points.len() == flower.points.len() {
                self.flower_start = if self.scene.strokes.len() < MAX_STROKES {
                    time_now
                } else {
                    zx::Time::INFINITE
                };
            } else {
                self.flower = Some(flower);
            }
        }

        // Full damage for changes that require some amount of clearing.
        if full_damage {
            for content in self.contents.values_mut() {
                content.full_damage();
            }
        }

        // Update tools and add damage to each content.
        if let Some(tool_damage) = self.scene.update_tools(render_context) {
            for content in self.contents.values_mut() {
                content.add_tool_damage(&tool_damage);
            }
        }

        // Update strokes and add damage to each content.
        if let Some(stroke_damage) = self.scene.update_strokes(render_context) {
            for content in self.contents.values_mut() {
                content.add_stroke_damage(&stroke_damage);
            }
        }

        let image_id = context.image_id;
        let image = render_context.get_current_image(context);
        let content = self.contents.entry(image_id).or_insert_with(|| Contents::new(image));

        content.update(render_context, &self.scene, size);

        Ok(())
    }

    fn handle_pointer_event(&mut self, event: &input::Event) {
        self.pending_pointer_events.push_back(event.clone());
    }
}

struct InkViewAssistant {
    size: Size,
    ink: Option<Ink>,
}

impl InkViewAssistant {
    pub fn new() -> Self {
        Self { size: Size::zero(), ink: None }
    }
}

impl ViewAssistant for InkViewAssistant {
    fn render(
        &mut self,
        render_context: &mut Context,
        ready_event: Event,
        context: &ViewAssistantContext,
    ) -> Result<(), Error> {
        if context.size != self.size || self.ink.is_none() {
            let ink = Ink::new(render_context, context.size);

            self.size = context.size;
            self.ink = Some(ink);
        }

        if let Some(ink) = self.ink.as_mut() {
            ink.update(render_context, context).expect("ink.update");
        }

        ready_event.as_handle_ref().signal(Signals::NONE, Signals::EVENT_SIGNALED)?;

        context.request_render();

        Ok(())
    }

    fn handle_pointer_event(
        &mut self,
        _context: &mut ViewAssistantContext,
        event: &input::Event,
        _pointer_event: &input::pointer::Event,
    ) -> Result<(), Error> {
        if let Some(ink) = self.ink.as_mut() {
            ink.handle_pointer_event(event);
        }
        Ok(())
    }

    fn get_render_offset(&mut self) -> Option<i64> {
        Some(Duration::from_millis(15).as_nanos() as i64)
    }
}

fn main() -> Result<(), Error> {
    fuchsia_trace_provider::trace_provider_create_with_fdio();

    println!("Ink Example");
    App::run(make_app_assistant::<InkAppAssistant>())
}
