// Copyright 2018 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::{Context as _, Error};
use carnelian::{
    color::Color,
    geometry::Corners,
    input::{self},
    make_app_assistant,
    render::{
        BlendMode, Composition, Context as RenderContext, Fill, FillRule, Layer, Path, PreClear,
        Raster, RenderExt, Style,
    },
    App, AppAssistant, Coord, Point, Rect, Size, ViewAssistant, ViewAssistantContext,
    ViewAssistantPtr, ViewKey,
};
use euclid::{Angle, Transform2D, Vector2D};
use fidl::endpoints::{RequestStream, ServiceMarker};
use fidl_test_placeholders::{EchoMarker, EchoRequest, EchoRequestStream};
use fuchsia_async as fasync;
use fuchsia_zircon::{AsHandleRef, Event, Signals, Time};
use futures::prelude::*;
use std::f32::consts::PI;

#[derive(Default)]
struct SpinningSquareAppAssistant;

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

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

    /// Return the list of names of services this app wants to provide
    fn outgoing_services_names(&self) -> Vec<&'static str> {
        [EchoMarker::NAME].to_vec()
    }

    /// Handle a request to connect to a service provided by this app
    fn handle_service_connection_request(
        &mut self,
        _service_name: &str,
        channel: fasync::Channel,
    ) -> Result<(), Error> {
        Self::create_echo_server(channel, false);
        Ok(())
    }
}

impl SpinningSquareAppAssistant {
    fn create_echo_server(channel: fasync::Channel, quiet: bool) {
        fasync::Task::local(
            async move {
                let mut stream = EchoRequestStream::from_channel(channel);
                while let Some(EchoRequest::EchoString { value, responder }) =
                    stream.try_next().await.context("error running echo server")?
                {
                    if !quiet {
                        println!("Spinning Square received echo request for string {:?}", value);
                    }
                    responder
                        .send(value.as_ref().map(|s| &**s))
                        .context("error sending response")?;
                    if !quiet {
                        println!("echo response sent successfully");
                    }
                }
                Ok(())
            }
            .unwrap_or_else(|e: anyhow::Error| eprintln!("{:?}", e)),
        )
        .detach();
    }
}

fn path_for_rectangle(bounds: &Rect, render_context: &mut RenderContext) -> Path {
    let mut path_builder = render_context.path_builder().expect("path_builder");
    path_builder.move_to(bounds.origin);
    path_builder.line_to(bounds.top_right());
    path_builder.line_to(bounds.bottom_right());
    path_builder.line_to(bounds.bottom_left());
    path_builder.line_to(bounds.origin);
    path_builder.build()
}

fn path_for_rounded_rectangle(
    bounds: &Rect,
    corner_radius: Coord,
    render_context: &mut RenderContext,
) -> Path {
    let kappa = 4.0 / 3.0 * (std::f32::consts::PI / 8.0).tan();
    let control_dist = kappa * corner_radius;

    let mut path_builder = render_context.path_builder().expect("path_builder");
    let top_left_arc_start = bounds.origin + Vector2D::new(0.0, corner_radius);
    let top_left_arc_end = bounds.origin + Vector2D::new(corner_radius, 0.0);
    path_builder.move_to(top_left_arc_start);
    let top_left_curve_center = bounds.origin + Vector2D::new(corner_radius, corner_radius);
    let p1 = top_left_curve_center + Vector2D::new(-corner_radius, -control_dist);
    let p2 = top_left_curve_center + Vector2D::new(-control_dist, -corner_radius);
    path_builder.cubic_to(p1, p2, top_left_arc_end);

    let top_right = bounds.top_right();
    let top_right_arc_start = top_right + Vector2D::new(-corner_radius, 0.0);
    let top_right_arc_end = top_right + Vector2D::new(0.0, corner_radius);
    path_builder.line_to(top_right_arc_start);
    let top_right_curve_center = top_right + Vector2D::new(-corner_radius, corner_radius);
    let p1 = top_right_curve_center + Vector2D::new(control_dist, -corner_radius);
    let p2 = top_right_curve_center + Vector2D::new(corner_radius, -control_dist);
    path_builder.cubic_to(p1, p2, top_right_arc_end);

    let bottom_right = bounds.bottom_right();
    let bottom_right_arc_start = bottom_right + Vector2D::new(0.0, -corner_radius);
    let bottom_right_arc_end = bottom_right + Vector2D::new(-corner_radius, 0.0);
    path_builder.line_to(bottom_right_arc_start);
    let bottom_right_curve_center = bottom_right + Vector2D::new(-corner_radius, -corner_radius);
    let p1 = bottom_right_curve_center + Vector2D::new(corner_radius, control_dist);
    let p2 = bottom_right_curve_center + Vector2D::new(control_dist, corner_radius);
    path_builder.cubic_to(p1, p2, bottom_right_arc_end);

    let bottom_left = bounds.bottom_left();
    let bottom_left_arc_start = bottom_left + Vector2D::new(corner_radius, 0.0);
    let bottom_left_arc_end = bottom_left + Vector2D::new(0.0, -corner_radius);
    path_builder.line_to(bottom_left_arc_start);
    let bottom_left_curve_center = bottom_left + Vector2D::new(corner_radius, -corner_radius);
    let p1 = bottom_left_curve_center + Vector2D::new(-control_dist, corner_radius);
    let p2 = bottom_left_curve_center + Vector2D::new(-corner_radius, control_dist);
    path_builder.cubic_to(p1, p2, bottom_left_arc_end);

    path_builder.line_to(top_left_arc_start);
    path_builder.build()
}

struct SpinningSquareViewAssistant {
    background_color: Color,
    square_color: Color,
    rounded: bool,
    start: Time,
    square_raster: Option<Raster>,
    square_path: Option<Path>,
    composition: Composition,
}

impl SpinningSquareViewAssistant {
    fn new() -> Result<ViewAssistantPtr, Error> {
        let square_color = Color { r: 0xff, g: 0x00, b: 0xff, a: 0xff };
        let background_color = Color { r: 0xb7, g: 0x41, b: 0x0e, a: 0xff };
        let start = Time::get_monotonic();
        let composition = Composition::new(background_color);
        Ok(Box::new(SpinningSquareViewAssistant {
            background_color,
            square_color,
            rounded: false,
            start,
            square_raster: None,
            square_path: None,
            composition,
        }))
    }

    fn clone_square_raster(&self) -> Raster {
        self.square_raster.as_ref().expect("square_raster").clone()
    }

    fn clone_square_path(&self) -> Path {
        self.square_path.as_ref().expect("square_path").clone()
    }

    fn toggle_rounded(&mut self) {
        self.rounded = !self.rounded;
        self.square_path = None;
    }
}

impl ViewAssistant for SpinningSquareViewAssistant {
    fn render(
        &mut self,
        render_context: &mut RenderContext,
        ready_event: Event,
        context: &ViewAssistantContext,
    ) -> Result<(), Error> {
        const SPEED: f32 = 0.25;
        const SECONDS_PER_NANOSECOND: f32 = 1e-9;
        const SQUARE_PATH_SIZE: Coord = 1.0;
        const SQUARE_PATH_SIZE_2: Coord = SQUARE_PATH_SIZE / 2.0;
        const CORNER_RADIUS: Coord = SQUARE_PATH_SIZE / 4.0;

        let center_x = context.size.width * 0.5;
        let center_y = context.size.height * 0.5;
        let square_size = context.size.width.min(context.size.height) * 0.6;
        let t = ((context.presentation_time.into_nanos() - self.start.into_nanos()) as f32
            * SECONDS_PER_NANOSECOND
            * SPEED)
            % 1.0;
        let angle = t * PI * 2.0;

        if self.square_path.is_none() {
            let top_left = Point::new(-SQUARE_PATH_SIZE_2, -SQUARE_PATH_SIZE_2);
            let square = Rect::new(top_left, Size::new(SQUARE_PATH_SIZE, SQUARE_PATH_SIZE));
            let square_path = if self.rounded {
                path_for_rounded_rectangle(&square, CORNER_RADIUS, render_context)
            } else {
                path_for_rectangle(&square, render_context)
            };
            self.square_path.replace(square_path);
        }

        let transformation = Transform2D::create_rotation(Angle::radians(angle))
            .post_scale(square_size, square_size)
            .post_translate(Vector2D::new(center_x, center_y));
        let mut raster_builder = render_context.raster_builder().expect("raster_builder");
        raster_builder.add(&self.clone_square_path(), Some(&transformation));
        self.square_raster = Some(raster_builder.build());

        let layers = std::iter::once(Layer {
            raster: self.clone_square_raster(),
            style: Style {
                fill_rule: FillRule::NonZero,
                fill: Fill::Solid(self.square_color),
                blend_mode: BlendMode::Over,
            },
        });

        self.composition.replace(.., layers);

        let image = render_context.get_current_image(context);
        let ext = RenderExt {
            pre_clear: Some(PreClear { color: self.background_color }),
            ..Default::default()
        };
        render_context.render(&self.composition, None, image, &ext);
        ready_event.as_handle_ref().signal(Signals::NONE, Signals::EVENT_SIGNALED)?;
        context.request_render();
        Ok(())
    }

    fn handle_keyboard_event(
        &mut self,
        _context: &mut ViewAssistantContext,
        _event: &input::Event,
        keyboard_event: &input::keyboard::Event,
    ) -> Result<(), Error> {
        if let Some(code_point) = keyboard_event.code_point {
            if code_point == ' ' as u32 && keyboard_event.phase == input::keyboard::Phase::Pressed {
                self.toggle_rounded();
            }
        }
        Ok(())
    }
}

fn main() -> Result<(), Error> {
    fuchsia_trace_provider::trace_provider_create_with_fdio();
    App::run(make_app_assistant::<SpinningSquareAppAssistant>())
}
