// 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::{Point, Rect, Size};
use fidl_fuchsia_ui_gfx::{BoundingBox, Vec3, ViewProperties};
use fuchsia_scenic::{EntityNode, SessionPtr, ViewHolder};

use crate::{toggle::Toggle, REPLICA_Z};

const CONTROLLER_VIEW_HEIGHT: f32 = 25.0;

/// Container for data related to a single child view displaying an emulated session.
pub struct ChildViewData {
    bounds: Option<Rect>,
    host_node: EntityNode,
    host_view_holder: ViewHolder,
    pub toggle: Toggle,
}

impl ChildViewData {
    pub fn new(
        host_node: EntityNode,
        host_view_holder: ViewHolder,
        toggle: Toggle,
    ) -> ChildViewData {
        ChildViewData {
            bounds: None,
            host_node: host_node,
            host_view_holder: host_view_holder,
            toggle: toggle,
        }
    }

    pub fn id(&self) -> u32 {
        self.host_view_holder.id()
    }
}

/// Lays out the given child views using the given container.
///
/// Voila uses a column layout to display 2 or more emulated sessions side by side.
pub fn layout(
    child_views: &mut [&mut ChildViewData],
    size: &Size,
    session: &SessionPtr,
) -> Result<(), failure::Error> {
    if child_views.is_empty() {
        return Ok(());
    }
    let num_views = child_views.len();

    let tile_width = (size.width / num_views as f32).floor();
    let tile_height = size.height;
    for (column_index, view) in child_views.iter_mut().enumerate() {
        let tile_bounds = Rect::new(
            Point::new(column_index as f32 * tile_width, 0.0),
            Size::new(tile_width, tile_height),
        );
        layout_replica(view, &tile_bounds, session)?;
    }
    Ok(())
}

fn layout_replica(
    view: &mut ChildViewData,
    bounds: &Rect,
    session: &SessionPtr,
) -> Result<(), failure::Error> {
    let (replica_bounds, controller_bounds) = split_bounds(&bounds, CONTROLLER_VIEW_HEIGHT);

    // Update the session view.
    let replica_bounds = inset(&replica_bounds, 5.0);
    let view_properties = ViewProperties {
        bounding_box: BoundingBox {
            min: Vec3 { x: 0.0, y: 0.0, z: 0.0 },
            max: Vec3 { x: replica_bounds.size.width, y: replica_bounds.size.height, z: 0.0 },
        },
        inset_from_min: Vec3 { x: 0.0, y: 0.0, z: 0.0 },
        inset_from_max: Vec3 { x: 0.0, y: 0.0, z: 0.0 },
        focus_change: true,
        downward_input: false,
    };
    view.host_view_holder.set_view_properties(view_properties);
    view.host_node.set_translation(replica_bounds.origin.x, replica_bounds.origin.y, REPLICA_Z);
    view.bounds = Some(replica_bounds);

    // Update the controller view.
    match controller_bounds {
        None => {
            // TODO(ppi): hide the controller when it doesn't fit on the screen.
        }
        Some(rect) => view.toggle.update(&inset(&rect, 5.0), session)?,
    }

    Ok(())
}

/// Splits the screen area available for one replica into a replica view and a controller view.
fn split_bounds(bounds: &Rect, controller_view_height: f32) -> (Rect, Option<Rect>) {
    if bounds.size.height < controller_view_height * 2.0 {
        return ((*bounds).clone(), None);
    }
    let replica_bounds = Rect::new(
        bounds.origin.clone(),
        Size::new(bounds.size.width, bounds.size.height - controller_view_height),
    );
    let controller_bounds = Rect::new(
        Point::new(bounds.origin.x, bounds.origin.y + bounds.size.height - controller_view_height),
        Size::new(bounds.size.width, controller_view_height),
    );
    (replica_bounds, Some(controller_bounds))
}

/// Reduces the given bounds to leave the given amount of padding around it.
///
/// The added padding is no bigger than a third of the smaller dimension of the
/// bounds.
fn inset(rect: &Rect, padding: f32) -> Rect {
    let inset = padding.min(rect.size.width / 3.0).min(rect.size.height / 3.0);
    let double_inset = inset * 2.0;
    Rect::new(
        Point::new(rect.origin.x + inset, rect.origin.y + inset),
        Size::new(rect.size.width - double_inset, rect.size.height - double_inset),
    )
}

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

    #[test]
    fn split_bounds_works_correctly() {
        let bounds = Rect::new(Point::new(10.0, 20.0), Size::new(75.0, 80.0));

        let (replica_bounds, maybe_controller_bounds) = split_bounds(&bounds, 10.0);

        assert_eq!(replica_bounds.origin.x, 10.0);
        assert_eq!(replica_bounds.origin.y, 20.0);
        assert_eq!(replica_bounds.size.width, 75.0);
        assert_eq!(replica_bounds.size.height, 70.0);

        assert_eq!(maybe_controller_bounds.is_some(), true);
        let controller_bounds = maybe_controller_bounds.expect("expected bounds to be present");
        assert_eq!(controller_bounds.origin.x, 10.0);
        assert_eq!(controller_bounds.origin.y, 90.0);
        assert_eq!(controller_bounds.size.width, 75.0);
        assert_eq!(controller_bounds.size.height, 10.0);
    }

    #[test]
    fn split_bounds_with_no_space_for_controller_hides_controller() {
        let bounds = Rect::new(Point::new(0.0, 0.0), Size::new(10.0, 10.0));

        let (_replica_bounds, maybe_controller_bounds) = split_bounds(&bounds, 6.0);
        assert_eq!(maybe_controller_bounds.is_none(), true);
    }

    #[test]
    fn inset_empty_returns_empty() {
        let empty = Rect::zero();

        let result = inset(&empty, 2.0);

        assert_eq!(result, Rect::zero());
    }

    #[test]
    fn inset_non_empty_works_correctly() {
        let bounds = Rect::new(Point::new(1.0, 3.0), Size::new(10.0, 8.0));

        let result = inset(&bounds, 2.0);

        assert_eq!(result.origin.x, 3.0);
        assert_eq!(result.origin.y, 5.0);
        assert_eq!(result.size.width, 6.0);
        assert_eq!(result.size.height, 4.0);
    }

    #[test]
    fn inset_padding_is_at_most_a_third_of_dimension() {
        let bounds = Rect::new(Point::new(0.0, 0.0), Size::new(9.0, 10.0));

        let result = inset(&bounds, 5.0);

        // Verify that the actual padding was 3.0, not 5.0.
        assert_eq!(result.origin.x, 3.0);
        assert_eq!(result.origin.y, 3.0);
        assert_eq!(result.size.width, 3.0);
        assert_eq!(result.size.height, 4.0);
    }
}
