// 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 {
    carnelian::{
        color::Color,
        drawing::{path_for_rectangle, FontFace, Glyph},
        render::{BlendMode, Context as RenderContext, Fill, FillRule, Layer, Raster, Style},
        Coord, Point, Rect, Size,
    },
    euclid::default::Vector2D,
    fuchsia_trace as ftrace,
    term_model::{
        ansi::CursorStyle,
        term::{CursorKey, RenderableCellContent, RenderableCellsIter},
    },
};

const UNDERLINE_CURSOR_CHAR: char = '\u{10a3e2}';
const BEAM_CURSOR_CHAR: char = '\u{10a3e3}';
const BOX_CURSOR_CHAR: char = '\u{10a3e4}';

const MAXIMUM_THUMB_RATIO: f32 = 0.8;
const MINIMUM_THUMB_RATIO: f32 = 0.05;

const SCROLL_BAR_MOVEMENT_THRESHOLD: f32 = 1.0;

static FONT_DATA: &'static [u8] =
    include_bytes!("../../../../../prebuilt/third_party/fonts/robotomono/RobotoMono-Regular.ttf");

fn make_color(term_color: &term_model::term::color::Rgb) -> Color {
    Color { r: term_color.r, g: term_color.g, b: term_color.b, a: 0xFF }
}

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()
}

pub struct GridView {
    font: FontFace,
    background_color: Color,
    pub frame: Rect,
    pub cell_size: Size,
}

impl Default for GridView {
    fn default() -> Self {
        GridView::new(&Color::new())
    }
}

impl GridView {
    pub fn new(background_color: &Color) -> GridView {
        GridView {
            frame: Rect::zero(),
            background_color: *background_color,
            font: FontFace::new(FONT_DATA).expect("unable to load font data"),
            cell_size: Size::zero(),
        }
    }

    pub fn render<'a, C>(
        &self,
        render_context: &mut RenderContext,
        cells: RenderableCellsIter<'a, C>,
    ) -> Vec<Layer> {
        let size = self.cell_size;

        let font = &self.font;

        let font_size = size.height * 0.9;
        let baseline = font_size * 0.9;
        let background_color = self.background_color;
        let (mut layers, maybe_bg_layers): (Vec<_>, Vec<_>) = cells
            .filter_map(|cell| {
                if let Some(character) = maybe_char_for_renderable_cell_content(cell.inner) {
                    let cell_position = Point::new(
                        size.width * cell.column.0 as f32,
                        size.height * cell.line.0 as f32,
                    );
                    let char_position = cell_position + Vector2D::new(0.0, baseline);
                    let glyph_index = font.face.glyph_index(character);
                    let glyph = Glyph::new(render_context, &self.font, font_size, glyph_index);
                    let cell_bounds = Rect::new(cell_position, size);
                    let fg_raster = if glyph_index.is_none() {
                        raster_for_rectangle(&cell_bounds, render_context)
                    } else {
                        let pos_vec = char_position.to_vector().to_i32();
                        glyph.raster.translate(pos_vec)
                    };
                    let cell_background_color = make_color(&cell.bg);
                    let bg_layer = if cell_background_color != background_color {
                        let bg_raster = raster_for_rectangle(&cell_bounds, render_context);
                        Some(Layer {
                            raster: bg_raster,
                            style: Style {
                                fill_rule: FillRule::NonZero,
                                fill: Fill::Solid(cell_background_color),
                                blend_mode: BlendMode::Over,
                            },
                        })
                    } else {
                        None
                    };

                    Some((
                        Layer {
                            raster: fg_raster,
                            style: Style {
                                fill_rule: FillRule::NonZero,
                                fill: Fill::Solid(make_color(&cell.fg)),
                                blend_mode: BlendMode::Over,
                            },
                        },
                        bg_layer,
                    ))
                } else {
                    None
                }
            })
            .unzip();
        let bg_layers: Vec<Layer> = maybe_bg_layers.into_iter().filter_map(|a| a).collect();
        layers.extend(bg_layers);
        layers
    }
}

// The term-model library gives us zero-width characters in our array of chars. However,
// we do not support this at thsi point so we just pull out the first char for rendering.
fn maybe_char_for_renderable_cell_content(content: RenderableCellContent) -> Option<char> {
    match content {
        RenderableCellContent::Cursor(cursor_key) => chars_for_cursor(cursor_key),
        RenderableCellContent::Chars(chars) => Some(chars[0]),
    }
}

fn chars_for_cursor(cursor: CursorKey) -> Option<char> {
    match cursor.style {
        CursorStyle::Block => Some(BOX_CURSOR_CHAR),
        CursorStyle::Underline => Some(UNDERLINE_CURSOR_CHAR),
        CursorStyle::Beam => Some(BEAM_CURSOR_CHAR),
        //TODO add support for HollowBlock style
        CursorStyle::HollowBlock => Some(UNDERLINE_CURSOR_CHAR),
        CursorStyle::Hidden => None,
    }
}

pub struct ScrollBar {
    pub frame: Rect,

    /// The content size of the scrollable area.
    pub content_height: Coord,

    /// The vertical distance that the content is offset from the bottom
    pub content_offset: Coord,

    /// The frame to draw the scroll bar thumb
    thumb_frame: Option<Rect>,

    /// Indicates whether we are tracking a scroll or not. This will
    /// eventually need to track the device_id when we handle multiple
    /// input events.
    last_pointer_tracking_location: Option<Point>,
}

impl Default for ScrollBar {
    fn default() -> Self {
        ScrollBar {
            frame: Rect::zero(),
            content_height: 0.0,
            content_offset: 0.0,
            thumb_frame: None,
            last_pointer_tracking_location: None,
        }
    }
}

impl ScrollBar {
    pub fn render(&self, render_context: &mut RenderContext) -> Option<Layer> {
        ftrace::duration!("terminal", "Views:ScrollBar:render2");
        self.thumb_frame
            .and_then(|thumb_frame| Some(Self::render_thumb_pattern(render_context, &thumb_frame)))
    }

    /// This method must be called after the client has updated
    /// the frame, content_height or content_offset. We leave this
    /// up to the caller to allow for the optimization of batching
    /// these updates without needing to recalculate the frame.
    pub fn invalidate_thumb_frame(&mut self) {
        self.update_thumb_frame();
    }

    pub fn begin_tracking_pointer_event(&mut self, point: Point) {
        if let Some(frame) = &self.thumb_frame {
            if !frame.contains(point) {
                // jump the middle of the thumb to the middle of the point
                let thumb_height = frame.size.height;
                let conversion_factor = self.pixel_space_to_content_space_conversion_factor();

                let proposed_offset = conversion_factor
                    * (self.frame.size.height
                        - (point.y - self.frame.origin.y)
                        - (thumb_height / 2.0));

                self.propose_offset(proposed_offset, conversion_factor, thumb_height);
            }
            self.last_pointer_tracking_location = Some(point);
        }
    }

    pub fn handle_pointer_move(&mut self, point: Point) {
        if let (Some(last_point), Some(thumb_frame)) =
            (self.last_pointer_tracking_location, self.thumb_frame)
        {
            let dy = last_point.y - point.y;
            // We do not want to respond to every micro pixel change. Only
            // move if we are above the threshold
            if dy.abs() < SCROLL_BAR_MOVEMENT_THRESHOLD {
                return;
            }

            let conversion_factor = self.pixel_space_to_content_space_conversion_factor();
            let proposed_offset = self.content_offset + (conversion_factor * dy);
            self.propose_offset(proposed_offset, conversion_factor, thumb_frame.size.height);

            self.last_pointer_tracking_location = Some(point);
        }
    }

    pub fn cancel_pointer_event(&mut self) {
        self.last_pointer_tracking_location = None;
    }

    fn propose_offset(
        &mut self,
        proposed_offset: Coord,
        conversion_factor: f32,
        thumb_height: f32,
    ) {
        // we have some rounding errors which make us loose 2 pixels. We round our inputs
        // to get those pixels back when calculating the max_offset.
        let max_offset =
            f32::ceil((self.frame.size.height - f32::floor(thumb_height)) * conversion_factor);
        self.content_offset = Coord::min(Coord::max(proposed_offset, 0.0), max_offset);
        self.invalidate_thumb_frame();
    }

    #[inline]
    pub fn is_tracking(&self) -> bool {
        self.last_pointer_tracking_location.is_some()
    }

    fn update_thumb_frame(&mut self) {
        if let Some(thumb_info) = self.calculate_thumb_render_info() {
            let thumb_frame = thumb_info.calculate_frame_in_rect(&self.frame);

            self.thumb_frame = Some(thumb_frame);
        } else {
            self.thumb_frame = None;
        }
    }

    fn render_thumb_pattern(render_context: &mut RenderContext, frame: &Rect) -> Layer {
        let white = Color::white();
        let raster = raster_for_rectangle(&frame, render_context);
        Layer {
            raster: raster,
            style: Style {
                fill_rule: FillRule::NonZero,
                fill: Fill::Solid(white),
                blend_mode: BlendMode::Over,
            },
        }
    }

    fn calculate_thumb_render_info(&self) -> Option<ThumbRenderInfo> {
        if self.content_height <= self.frame.size.height {
            return None;
        }

        let height =
            Self::calculate_thumb_height_ratio(self.frame.size.height, self.content_height)
                * self.frame.size.height;

        let vertical_offset =
            Coord::floor(self.content_space_to_pixel_space_factor(&height) * self.content_offset);
        Some(ThumbRenderInfo { height, vertical_offset })
    }

    fn calculate_thumb_height_ratio(frame_height: Coord, content_height: Coord) -> Coord {
        let ratio = frame_height / content_height;
        Coord::min(Coord::max(MINIMUM_THUMB_RATIO, ratio), MAXIMUM_THUMB_RATIO)
    }

    #[inline]
    fn pixel_space_to_content_space_conversion_factor(&self) -> Coord {
        // this method is different from the thumb_height_ratio in that it will never round
        // so it can be used to calculate offsets from pixel positions.
        self.content_height / self.frame.size.height
    }

    #[inline]
    fn content_space_to_pixel_space_factor(&self, thumb_height: &Coord) -> Coord {
        (self.frame.size.height - thumb_height) / (self.content_height - self.frame.size.height)
    }
}

#[derive(PartialEq, Debug)]
struct ThumbRenderInfo {
    /// The height of the ScrollBarThumb
    height: Coord,

    /// The y position of the bottom of the ScrollBarThumb
    vertical_offset: Coord,
}

impl ThumbRenderInfo {
    fn calculate_frame_in_rect(&self, outer_rect: &Rect) -> Rect {
        let size = Size::new(outer_rect.size.width, self.height);
        let origin = Point::new(
            outer_rect.origin.x,
            outer_rect.origin.y + outer_rect.size.height - self.vertical_offset - self.height,
        );
        Rect::new(origin, size)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn rect_with_height(height: Coord) -> Rect {
        Rect::new(Point::zero(), Size::new(10.0, height))
    }

    #[test]
    fn sroll_bar_is_tracking_flag() {
        let mut scroll_bar = ScrollBar::default();

        assert_eq!(scroll_bar.is_tracking(), false);

        scroll_bar.last_pointer_tracking_location = Some(Point::new(0.0, 0.0));
        assert_eq!(scroll_bar.is_tracking(), true);
    }

    #[test]
    fn scroll_bar_does_not_change_content_offset_if_not_tracking() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;

        scroll_bar.handle_pointer_move(Point::new(50.0, 50.0));
        assert_eq!(scroll_bar.content_offset, 0.0);
    }

    #[test]
    fn scroll_bar_does_not_change_content_offset_if_less_than_threshold() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.last_pointer_tracking_location = Some(Point::new(10.0, 90.0));

        scroll_bar.handle_pointer_move(Point::new(10.0, 89.9));
        assert_eq!(scroll_bar.content_offset, 0.0);
    }

    #[test]
    fn scroll_bar_updates_content_offset_on_move_when_tracking() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.last_pointer_tracking_location = Some(Point::new(10.0, 90.0));

        // a movement of 1 pixel in view space should equate to a movement
        // of 4 points in content space
        scroll_bar.handle_pointer_move(Point::new(10.0, 89.0));
        assert_eq!(scroll_bar.content_offset, 4.0);
    }

    #[test]
    fn scroll_bar_updates_content_offset_on_move_when_tracking_nonzero_origin() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = Rect::new(Point::new(10.0, 10.0), Size::new(10.0, 100.0));
        scroll_bar.content_height = 400.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.last_pointer_tracking_location = Some(Point::new(10.0, 90.0));

        // a movement of 1 pixel in view space should equate to a movement
        // of 4 points in content space
        scroll_bar.handle_pointer_move(Point::new(10.0, 89.0));
        assert_eq!(scroll_bar.content_offset, 4.0);
    }

    #[test]
    fn scroll_bar_updates_content_offset_on_move_when_tracking_stays_above_zero() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.last_pointer_tracking_location = Some(Point::new(10.0, 90.0));

        scroll_bar.handle_pointer_move(Point::new(10.0, 91.0));
        assert_eq!(scroll_bar.content_offset, 0.0);
    }

    #[test]
    fn scroll_bar_updates_content_offset_on_move_when_tracking_does_not_exceed_maximum() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.last_pointer_tracking_location = Some(Point::new(10.0, 90.0));

        scroll_bar.handle_pointer_move(Point::new(10.0, 0.0));
        assert_eq!(scroll_bar.content_offset, 300.0);
    }

    #[test]
    fn scroll_bar_handle_pointer_move_updates_last_tracking_point() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.last_pointer_tracking_location = Some(Point::new(10.0, 10.0));
        scroll_bar.handle_pointer_move(Point::new(10.0, 11.0));
        assert_eq!(scroll_bar.last_pointer_tracking_location.unwrap(), Point::new(10.0, 11.0));
    }

    #[test]
    fn scroll_bar_begin_pointer_move_updates_last_tracking_point() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.begin_tracking_pointer_event(Point::new(5.0, 90.0));
        assert_eq!(scroll_bar.last_pointer_tracking_location.unwrap(), Point::new(5.0, 90.0));
    }

    #[test]
    fn scroll_bar_begin_pointer_move_jumps_if_initial_point_outside_thumb_min() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.begin_tracking_pointer_event(Point::new(5.0, 10.0));
        assert_eq!(scroll_bar.content_offset, 300.0);
    }

    #[test]
    fn scroll_bar_begin_pointer_move_jumps_if_initial_point_outside_thumb() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 500.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.begin_tracking_pointer_event(Point::new(5.0, 50.0));
        assert_eq!(scroll_bar.content_offset, 200.0);
    }

    #[test]
    fn scroll_bar_begin_pointer_move_jumps_if_initial_point_outside_thumb_nonzero_origin() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = Rect::new(Point::new(10.0, 10.0), Size::new(10.0, 100.0));
        scroll_bar.content_height = 500.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.begin_tracking_pointer_event(Point::new(5.0, 60.0));
        assert_eq!(scroll_bar.content_offset, 200.0);
    }

    #[test]
    fn scroll_bar_begin_pointer_move_jumps_if_initial_point_outside_thumb_max() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.content_offset = 300.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.begin_tracking_pointer_event(Point::new(5.0, 99.0));
        assert_eq!(scroll_bar.content_offset, 0.0);
    }

    #[test]
    fn scroll_bar_cancel_pointer_event_drops_last_tracking_point() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.invalidate_thumb_frame();

        scroll_bar.begin_tracking_pointer_event(Point::new(10.0, 10.0));
        scroll_bar.cancel_pointer_event();
        assert!(scroll_bar.last_pointer_tracking_location.is_none());
    }

    #[test]
    fn thumb_frame_updated_when_told_thumb_frame_is_invalidated() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.content_height = 10_000.0;
        scroll_bar.invalidate_thumb_frame();
        assert!(scroll_bar.thumb_frame.is_some());
    }

    #[test]
    fn thumb_render_info_none_same_content_size_and_frame() {
        let scroll_bar = ScrollBar::default();
        let thumb_info = scroll_bar.calculate_thumb_render_info();
        assert!(thumb_info.is_none());
    }

    #[test]
    fn thumb_render_info_none_not_scrollable() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(1000.0);
        scroll_bar.content_height = 900.0;

        let thumb_info = scroll_bar.calculate_thumb_render_info();
        assert!(thumb_info.is_none());
    }

    #[test]
    fn scroll_bar_thumb_render_info_returns_proper_height() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.content_height = 2_000.0;
        scroll_bar.frame.size.height = 1_000.0;

        let render_info = scroll_bar.calculate_thumb_render_info().unwrap();
        assert_eq!(render_info.height, 500.0,);
    }

    #[test]
    fn calculate_thumb_height_ratio_pins_to_min() {
        let ratio = ScrollBar::calculate_thumb_height_ratio(100.0, 10_100.0);
        assert_eq!(ratio, super::MINIMUM_THUMB_RATIO);
    }

    #[test]
    fn calculate_thumb_height_ratio_pins_to_max() {
        let ratio = ScrollBar::calculate_thumb_height_ratio(100.0, 101.0);
        assert_eq!(ratio, super::MAXIMUM_THUMB_RATIO);
    }

    #[test]
    fn calculate_thumb_height_ratio() {
        let ratio = ScrollBar::calculate_thumb_height_ratio(10.0, 40.0);
        assert_eq!(ratio, 0.25);
    }

    #[test]
    fn calculate_thumb_vertical_offset_top() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.content_offset = 300.0;

        let render_info = scroll_bar.calculate_thumb_render_info().unwrap();
        assert_eq!(render_info.vertical_offset, 75.0);
    }

    #[test]
    fn calculate_thumb_vertical_offset_mid() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 400.0;
        scroll_bar.content_offset = 100.0;

        let render_info = scroll_bar.calculate_thumb_render_info().unwrap();

        assert_eq!(render_info.vertical_offset, 25.0);
    }

    #[test]
    fn calculate_thumb_vertical_offset_with_round() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 300.0;
        scroll_bar.content_offset = 100.0;

        let render_info = scroll_bar.calculate_thumb_render_info().unwrap();

        assert_eq!(render_info.vertical_offset, 33.0);
    }

    #[test]
    fn calculate_thumb_vertical_offset_bottom() {
        let mut scroll_bar = ScrollBar::default();
        scroll_bar.frame = rect_with_height(100.0);
        scroll_bar.content_height = 302.0;
        scroll_bar.content_offset = 0.0;

        let render_info = scroll_bar.calculate_thumb_render_info().unwrap();

        assert_eq!(render_info.vertical_offset, 0.0);
    }

    #[test]
    fn scroll_context_thumb_render_info_equality() {
        let first = ThumbRenderInfo { height: 100.0, vertical_offset: 100.0 };
        let second = ThumbRenderInfo { height: 100.0, vertical_offset: 100.0 };
        assert_eq!(first, second);
    }

    #[test]
    fn scroll_context_thumb_render_info_not_equal_diff_offset() {
        let first = ThumbRenderInfo { height: 100.0, vertical_offset: 100.0 };
        let second = ThumbRenderInfo { height: 100.0, vertical_offset: 0.0 };
        assert_ne!(first, second);
    }

    #[test]
    fn scroll_context_thumb_render_info_equality_not_equal_diff_height() {
        let first = ThumbRenderInfo { height: 100.0, vertical_offset: 100.0 };
        let second = ThumbRenderInfo { height: 10.0, vertical_offset: 100.0 };
        assert_ne!(first, second);
    }

    #[test]
    fn thumb_render_info_calculate_frame_in_rect() {
        let thumb_info = ThumbRenderInfo { height: 10.0, vertical_offset: 10.0 };
        let outer = Rect::new(Point::new(10.0, 10.0), Size::new(10.0, 1000.0));
        let rect = thumb_info.calculate_frame_in_rect(&outer);

        assert_eq!(rect, Rect::new(Point::new(10.0, 990.0), Size::new(10.0, 10.0)));
    }
}
