// 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;
use argh::FromArgs;
use carnelian::{
    color::Color,
    drawing::{
        load_font, path_for_corner_knockouts, path_for_rectangle, DisplayRotation, FontFace,
        GlyphMap, Paint, Text,
    },
    input::{self},
    make_app_assistant, make_message,
    render::{
        BlendMode, Composition, Context as RenderContext, Fill, FillRule, Layer, PreClear, Raster,
        RenderExt, Style,
    },
    App, AppAssistant, Coord, Message, Point, Rect, Size, ViewAssistant, ViewAssistantContext,
    ViewAssistantPtr, ViewKey,
};
use euclid::default::Vector2D;
use fuchsia_zircon::{AsHandleRef, Event, Signals, Time};
use std::path::PathBuf;

fn display_rotation_from_str(s: &str) -> Result<DisplayRotation, String> {
    match s {
        "0" => Ok(DisplayRotation::Deg0),
        "90" => Ok(DisplayRotation::Deg90),
        "180" => Ok(DisplayRotation::Deg180),
        "270" => Ok(DisplayRotation::Deg270),
        _ => Err(format!("Invalid DisplayRotation {}", s)),
    }
}

/// Button Sample
#[derive(Debug, FromArgs)]
#[argh(name = "recovery")]
struct Args {
    /// rotate
    #[argh(option, from_str_fn(display_rotation_from_str))]
    rotation: Option<DisplayRotation>,
}

/// enum that defines all messages sent with `App::queue_message` that
/// the button view assistant will understand and process.
pub enum ButtonMessages {
    Pressed(Time),
}

#[derive(Default)]
struct ButtonAppAssistant {
    display_rotation: DisplayRotation,
}

impl AppAssistant for ButtonAppAssistant {
    fn setup(&mut self) -> Result<(), Error> {
        let args: Args = argh::from_env();
        self.display_rotation = args.rotation.unwrap_or(DisplayRotation::Deg0);
        Ok(())
    }

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

    fn get_display_rotation(&self) -> DisplayRotation {
        self.display_rotation
    }
}

fn raster_for_rectangle(bounds: &Rect, render_context: &mut RenderContext) -> Raster {
    let mut raster_builder = render_context.raster_builder().expect("raster_builder");
    raster_builder.add(&path_for_rectangle(bounds, render_context), None);
    raster_builder.build()
}

fn raster_for_corner_knockouts(
    bounds: &Rect,
    corner_radius: Coord,
    render_context: &mut RenderContext,
) -> Raster {
    let path = path_for_corner_knockouts(bounds, corner_radius, render_context);
    let mut raster_builder = render_context.raster_builder().expect("raster_builder");
    raster_builder.add(&path, None);
    raster_builder.build()
}

struct RasterAndStyle {
    location: Point,
    raster: Raster,
    style: Style,
}

struct Button {
    pub font_size: u32,
    pub padding: f32,
    bounds: Rect,
    bg_color: Color,
    bg_color_active: Color,
    bg_color_disabled: Color,
    fg_color: Color,
    fg_color_disabled: Color,
    tracking_pointer: Option<input::pointer::PointerId>,
    active: bool,
    focused: bool,
    glyphs: GlyphMap,
    label_text: String,
    face: FontFace,
    label: Option<Text>,
}

impl Button {
    pub fn new(text: &str) -> Result<Button, Error> {
        let face = load_font(PathBuf::from("/pkg/data/fonts/RobotoSlab-Regular.ttf"))?;
        let button = Button {
            font_size: 20,
            padding: 5.0,
            bounds: Rect::zero(),
            fg_color: Color::white(),
            bg_color: Color::from_hash_code("#B7410E")?,
            bg_color_active: Color::from_hash_code("#f0703c")?,
            fg_color_disabled: Color::from_hash_code("#A0A0A0")?,
            bg_color_disabled: Color::from_hash_code("#C0C0C0")?,
            tracking_pointer: None,
            active: false,
            focused: false,
            glyphs: GlyphMap::new(),
            label_text: text.to_string(),
            face,
            label: None,
        };

        Ok(button)
    }

    pub fn set_focused(&mut self, focused: bool) {
        self.focused = focused;
        if !focused {
            self.active = false;
            self.tracking_pointer = None;
        }
    }

    fn create_rasters_and_styles(
        &mut self,
        render_context: &mut RenderContext,
    ) -> Result<(RasterAndStyle, RasterAndStyle), Error> {
        // set up paint with different backgrounds depending on whether the button
        // is active. The active state is true when a pointer has gone down in the
        // button's bounds and the pointer has not moved outside the bounds since.
        let paint = if self.focused {
            Paint {
                fg: self.fg_color,
                bg: if self.active { self.bg_color_active } else { self.bg_color },
            }
        } else {
            Paint { fg: self.fg_color_disabled, bg: self.bg_color_disabled }
        };

        self.label = Some(Text::new(
            render_context,
            &self.label_text,
            self.font_size as f32,
            100,
            &self.face,
            &mut self.glyphs,
        ));

        let label = self.label.as_ref().expect("label");

        // calculate button size based on label's text size
        // plus padding.
        let bounding_box_size = label.bounding_box.size;

        let button_label_size = Size::new(bounding_box_size.width, self.font_size as f32);
        let double_padding = 2.0 * self.padding;
        let button_size = button_label_size + Size::new(double_padding, double_padding);
        let half_size = Size::new(button_size.width * 0.5, button_size.height * 0.5);
        let button_origin = Point::zero() - half_size.to_vector();
        let button_bounds = Rect::new(button_origin, button_size).round_out();

        // record bounds for hit testing
        self.bounds = button_bounds;

        // Calculate the label offset in display aligned coordinates, since the label,
        // as a raster, is pre-rotated and we just need to translate it to align with the buttons
        // bounding box.

        let center = self.bounds.center();
        let label_center = label.bounding_box.center().to_vector();
        let label_offset = center - label_center;
        let raster = raster_for_rectangle(&self.bounds, render_context);
        let button_raster_and_style = RasterAndStyle {
            location: Point::zero(),
            raster,
            style: Style {
                fill_rule: FillRule::NonZero,
                fill: Fill::Solid(paint.bg),
                blend_mode: BlendMode::Over,
            },
        };
        let label_raster_and_style = RasterAndStyle {
            location: label_offset,
            raster: label.raster.clone(),
            style: Style {
                fill_rule: FillRule::NonZero,
                fill: Fill::Solid(paint.fg),
                blend_mode: BlendMode::Over,
            },
        };
        Ok((button_raster_and_style, label_raster_and_style))
    }

    pub fn handle_pointer_event(
        &mut self,
        context: &mut ViewAssistantContext,
        pointer_event: &input::pointer::Event,
    ) {
        if !self.focused {
            return;
        }

        let bounds = self
            .bounds
            .translate(Vector2D::new(context.size.width * 0.5, context.size.height * 0.7));

        if self.tracking_pointer.is_none() {
            match pointer_event.phase {
                input::pointer::Phase::Down(location) => {
                    self.active = bounds.contains(location.to_f32());
                    if self.active {
                        self.tracking_pointer = Some(pointer_event.pointer_id.clone());
                    }
                }
                _ => (),
            }
        } else {
            let tracking_pointer = self.tracking_pointer.as_ref().expect("tracking_pointer");
            if tracking_pointer == &pointer_event.pointer_id {
                match pointer_event.phase {
                    input::pointer::Phase::Moved(location) => {
                        self.active = bounds.contains(location.to_f32());
                    }
                    input::pointer::Phase::Up => {
                        if self.active {
                            context.queue_message(make_message(ButtonMessages::Pressed(
                                Time::get_monotonic(),
                            )));
                        }
                        self.tracking_pointer = None;
                        self.active = false;
                    }
                    input::pointer::Phase::Remove => {
                        self.active = false;
                        self.tracking_pointer = None;
                    }
                    input::pointer::Phase::Cancel => {
                        self.active = false;
                        self.tracking_pointer = None;
                    }
                    _ => (),
                }
            }
        }
    }
}

struct ButtonViewAssistant {
    focused: bool,
    bg_color: Color,
    button: Button,
    red_light: bool,
    composition: Composition,
}

const BUTTON_LABEL: &'static str = "Depress Me";

impl ButtonViewAssistant {
    fn new() -> Result<ButtonViewAssistant, Error> {
        let bg_color = Color::from_hash_code("#EBD5B3")?;
        let composition = Composition::new(bg_color);
        Ok(ButtonViewAssistant {
            focused: false,
            bg_color,
            button: Button::new(BUTTON_LABEL)?,
            red_light: false,
            composition,
        })
    }

    fn target_size(&self, size: Size) -> Size {
        size
    }

    fn button_center(&self, size: Size) -> Point {
        Point::new(size.width * 0.5, size.height * 0.7)
    }
}

impl ViewAssistant for ButtonViewAssistant {
    fn render(
        &mut self,
        render_context: &mut RenderContext,
        ready_event: Event,
        context: &ViewAssistantContext,
    ) -> Result<(), Error> {
        // Emulate the size that Carnelian passes when the display is rotated
        let target_size = self.target_size(context.size);

        // Calculate all locations in the presentation-aligned coordinate space
        let center_x = target_size.width * 0.5;

        let min_dimension = target_size.width.min(target_size.height);
        let font_size = (min_dimension / 5.0).ceil().min(64.0) as u32;
        let padding = (min_dimension / 20.0).ceil().max(8.0);

        self.button.padding = padding;
        self.button.font_size = font_size;

        let corner_knockouts =
            raster_for_corner_knockouts(&Rect::from_size(target_size), 10.0, render_context);

        let corner_knockouts_layer = Layer {
            raster: corner_knockouts,
            style: Style {
                fill_rule: FillRule::NonZero,
                fill: Fill::Solid(Color::new()),
                blend_mode: BlendMode::Over,
            },
        };

        // Position and size the indicator in presentation space
        let indicator_y = target_size.height / 5.0;
        let indicator_len = target_size.height.min(target_size.width) / 8.0;
        let indicator_size = Size::new(indicator_len * 2.0, indicator_len);
        let indicator_pos = Point::new(center_x - indicator_len, indicator_y - indicator_len / 2.0);

        let indicator_raster =
            raster_for_rectangle(&Rect::new(Point::zero(), indicator_size), render_context)
                .translate(indicator_pos.to_vector().to_i32());

        let indicator_color = if self.red_light {
            Color::from_hash_code("#ff0000")?
        } else {
            Color::from_hash_code("#00ff00")?
        };

        // Create a layer for the indicator using its pre-transformed raster and
        // transformed position.
        let indicator_layer = Layer {
            raster: indicator_raster,
            style: Style {
                fill_rule: FillRule::NonZero,
                fill: Fill::Solid(indicator_color),
                blend_mode: BlendMode::Over,
            },
        };

        let button_center = self.button_center(target_size);
        self.button.set_focused(self.focused);

        // Let the button render itself, returning rasters, styles and zero-relative
        // positions.
        let (button_raster_and_style, label_raster_and_style) =
            self.button.create_rasters_and_styles(render_context)?;

        // Calculate the button location in presentation space
        let button_location = button_center + button_raster_and_style.location.to_vector();

        // Calculate the label location in presentation space
        let label_location = button_center + label_raster_and_style.location.to_vector();

        // Create layers from the rasters, styles and transformed locations.
        let button_layer = Layer {
            raster: button_raster_and_style.raster.translate(button_location.to_vector().to_i32()),
            style: button_raster_and_style.style,
        };
        let label_layer = Layer {
            raster: label_raster_and_style.raster.translate(label_location.to_vector().to_i32()),
            style: label_raster_and_style.style,
        };
        self.composition.replace(
            ..,
            std::iter::once(corner_knockouts_layer)
                .chain(std::iter::once(label_layer))
                .chain(std::iter::once(button_layer))
                .chain(std::iter::once(indicator_layer)),
        );

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

        Ok(())
    }

    fn handle_message(&mut self, message: Message) {
        if let Some(button_message) = message.downcast_ref::<ButtonMessages>() {
            match button_message {
                ButtonMessages::Pressed(value) => {
                    println!("value = {:#?}", value);
                    self.red_light = !self.red_light
                }
            }
        }
    }

    fn handle_pointer_event(
        &mut self,
        context: &mut ViewAssistantContext,
        _event: &input::Event,
        pointer_event: &input::pointer::Event,
    ) -> Result<(), Error> {
        self.button.handle_pointer_event(context, &pointer_event);
        context.request_render();
        Ok(())
    }

    fn handle_focus_event(
        &mut self,
        context: &mut ViewAssistantContext,
        focused: bool,
    ) -> Result<(), Error> {
        self.focused = focused;
        context.request_render();
        Ok(())
    }
}

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