// 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 crate::ask_box::AskBox;
use failure::{Error, ResultExt};
use fidl::encoding::Decodable;
use fidl::encoding::OutOfLine;
use fidl::endpoints::{create_proxy, ClientEnd, ServerEnd};
use fidl_fuchsia_math::{InsetF, RectF, SizeF};
use fidl_fuchsia_modular::{
    AddMod, Intent, PuppetMasterMarker, PuppetMasterProxy, StoryCommand, StoryPuppetMasterProxy,
    SurfaceArrangement, SurfaceDependency, SurfaceRelation,
};
use fidl_fuchsia_ui_gfx::{self as gfx, ColorRgba};
use fidl_fuchsia_ui_input::KeyboardEvent;
use fidl_fuchsia_ui_scenic::{SessionListenerMarker, SessionListenerRequest};
use fidl_fuchsia_ui_viewsv1::{
    CustomFocusBehavior, ViewContainerListenerMarker, ViewContainerListenerRequest, ViewLayout,
    ViewListenerMarker, ViewListenerRequest, ViewProperties,
};
use fuchsia_app::client::connect_to_service;
use fuchsia_async as fasync;
use fuchsia_scenic::{EntityNode, ImportNode, Material, Rectangle, SessionPtr, ShapeNode};
use fuchsia_zircon as zx;
use futures::{future::ready as fready, TryFutureExt, TryStreamExt};
use itertools::Itertools;
use parking_lot::Mutex;
use std::collections::BTreeMap;
use std::sync::Arc;
use std::time::SystemTime;

fn random_story_name() -> String {
    let secs = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
        Ok(n) => n.as_secs(),
        Err(_) => panic!("SystemTime before UNIX EPOCH!"),
    };
    format!("ermine-story-{}", secs)
}

fn random_mod_name() -> String {
    let secs = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
        Ok(n) => n.as_secs(),
        Err(_) => panic!("SystemTime before UNIX EPOCH!"),
    };
    format!("ermine-mod-{}", secs)
}

fn inset(rect: &mut RectF, border: f32) {
    let inset = border.min(rect.width / 0.3).min(rect.height / 0.3);
    rect.x += inset;
    rect.y += inset;
    let inset_width = inset * 2.0;
    rect.width = rect.width - inset_width;
    rect.height = rect.height - inset_width;
}

struct ViewData {
    key: u32,
    url: String,
    story_id: String,
    allow_focus: bool,
    bounds: Option<RectF>,
    host_node: EntityNode,
}

impl ViewData {
    pub fn new(
        key: u32,
        url: String,
        story_id: String,
        allow_focus: bool,
        host_node: EntityNode,
    ) -> ViewData {
        ViewData {
            key: key,
            url: url,
            story_id: story_id,
            bounds: None,
            allow_focus: allow_focus,
            host_node: host_node,
        }
    }
}

pub struct ErmineView {
    // Must keep the view proxy alive or the view goes away.
    _view: fidl_fuchsia_ui_viewsv1::ViewProxy,
    puppet_master: PuppetMasterProxy,
    story_puppet_masters: BTreeMap<String, StoryPuppetMasterProxy>,
    view_container: fidl_fuchsia_ui_viewsv1::ViewContainerProxy,
    session: SessionPtr,
    import_node: ImportNode,
    background_node: ShapeNode,
    container_node: EntityNode,
    views: BTreeMap<u32, ViewData>,
    width: f32,
    height: f32,
    ask_box: Option<AskBox>,
}

pub type ErmineViewPtr = Arc<Mutex<ErmineView>>;

impl ErmineView {
    pub fn new(
        view_listener_request: ServerEnd<ViewListenerMarker>,
        view: fidl_fuchsia_ui_viewsv1::ViewProxy,
        mine: zx::EventPair,
        session: SessionPtr,
        session_listener_server: ServerEnd<SessionListenerMarker>,
    ) -> Result<ErmineViewPtr, Error> {
        let (view_container_proxy, view_container_request) = create_proxy()?;

        view.get_container(view_container_request)?;

        let puppet_master = connect_to_service::<PuppetMasterMarker>()?;

        let view_controller = ErmineView {
            _view: view,
            puppet_master,
            story_puppet_masters: BTreeMap::new(),
            view_container: view_container_proxy,
            session: session.clone(),
            import_node: ImportNode::new(session.clone(), mine),
            background_node: ShapeNode::new(session.clone()),
            container_node: EntityNode::new(session.clone()),
            views: BTreeMap::new(),
            width: 0.0,
            height: 0.0,
            ask_box: None,
        };

        let view_controller = Arc::new(Mutex::new(view_controller));

        Self::setup_session_listener(&view_controller, session_listener_server)?;
        Self::setup_view_listener(&view_controller, view_listener_request)?;
        Self::setup_view_container_listener(&view_controller)?;
        Self::finish_setup_scene(&view_controller);

        Ok(view_controller)
    }

    fn setup_session_listener(
        view_controller: &ErmineViewPtr,
        session_listener_server: ServerEnd<SessionListenerMarker>,
    ) -> Result<(), Error> {
        let view_controller = view_controller.clone();
        fasync::spawn(
            session_listener_server
                .into_stream()?
                .map_ok(move |request| match request {
                    SessionListenerRequest::OnScenicEvent { events, .. } => {
                        view_controller.lock().handle_session_events(events)
                    }
                    _ => (),
                })
                .try_collect::<()>()
                .unwrap_or_else(|e| eprintln!("session listener error: {:?}", e)),
        );
        Ok(())
    }

    fn setup_view_listener(
        view_controller: &ErmineViewPtr,
        view_listener_request: ServerEnd<ViewListenerMarker>,
    ) -> Result<(), Error> {
        let view_controller = view_controller.clone();
        fasync::spawn(
            view_listener_request
                .into_stream()?
                .try_for_each(
                    move |ViewListenerRequest::OnPropertiesChanged { properties, responder }| {
                        view_controller.lock().handle_properies_changed(&properties);
                        fready(responder.send())
                    },
                )
                .unwrap_or_else(|e| eprintln!("view listener error: {:?}", e)),
        );
        Ok(())
    }

    fn setup_view_container_listener(view_controller: &ErmineViewPtr) -> Result<(), Error> {
        let view_controller = view_controller.clone();
        let (view_container_listener_client, view_container_listener_server) =
            zx::Channel::create()?;
        let view_container_listener = ClientEnd::new(view_container_listener_client);
        let view_container_listener_request =
            ServerEnd::<ViewContainerListenerMarker>::new(view_container_listener_server);

        view_controller.lock().view_container.set_listener(Some(view_container_listener))?;

        fasync::spawn(
            view_container_listener_request
                .into_stream()?
                .try_for_each(move |event| match event {
                    ViewContainerListenerRequest::OnChildAttached { responder, .. } => {
                        view_controller.lock().update();
                        fready(responder.send())
                    }
                    ViewContainerListenerRequest::OnChildUnavailable { responder, child_key } => {
                        view_controller
                            .lock()
                            .remove_story(child_key)
                            .unwrap_or_else(|e| eprintln!("remove_story error: {:?}", e));
                        fready(responder.send())
                    }
                })
                .unwrap_or_else(|e| eprintln!("view listener error: {:?}", e)),
        );

        Ok(())
    }

    fn finish_setup_scene(view_controller: &ErmineViewPtr) {
        let vc = view_controller.lock();
        vc.setup_scene();
        vc.present();
    }

    fn setup_scene(&self) {
        self.import_node.resource().set_event_mask(gfx::METRICS_EVENT_MASK);
        self.import_node.add_child(&self.background_node);
        self.import_node.add_child(&self.container_node);
        let material = Material::new(self.session.clone());
        material.set_color(ColorRgba { red: 0xb3, green: 0x1b, blue: 0x1b, alpha: 0x80 });
        self.background_node.set_material(&material);
    }

    fn update(&mut self) {
        let center_x = self.width * 0.5;
        let center_y = self.height * 0.5;
        self.background_node.set_shape(&Rectangle::new(
            self.session.clone(),
            self.width,
            self.height,
        ));
        self.background_node.set_translation(center_x, center_y, 0.0);
        self.present();
    }

    fn present(&self) {
        fasync::spawn(
            self.session
                .lock()
                .present(0)
                .map_ok(|_| ())
                .unwrap_or_else(|e| eprintln!("present error: {:?}", e)),
        );
    }

    fn handle_session_events(&mut self, events: Vec<fidl_fuchsia_ui_scenic::Event>) {
        events.iter().for_each(|event| match event {
            fidl_fuchsia_ui_scenic::Event::Gfx(gfx::Event::Metrics(_event)) => {
                self.update();
            }
            _ => (),
        });
    }

    fn handle_properies_changed(&mut self, properties: &fidl_fuchsia_ui_viewsv1::ViewProperties) {
        if let Some(ref view_properties) = properties.view_layout {
            self.width = view_properties.size.width;
            self.height = view_properties.size.height;
            self.update();
        }
    }

    pub fn add_child_view_for_story_attach(
        &mut self,
        key: u32,
        story_id: String,
        view_holder_token: zx::EventPair,
    ) -> Result<(), Error> {
        let host_node = EntityNode::new(self.session.clone());
        let host_import_token = host_node.export_as_request();

        self.view_container.add_child2(key, view_holder_token, host_import_token)?;

        self.import_node.add_child(&host_node);
        let view_data = ViewData::new(key, "".to_string(), story_id, true, host_node);
        self.views.insert(key, view_data);
        self.update();
        self.layout()?;
        Ok(())
    }

    pub fn remove_view_for_story(&mut self, story_id: &String) -> Result<(), Error> {
        let result = self.views.iter().find(|(_key, view)| view.story_id == *story_id);

        if let Some((key, _view)) = result {
            self.remove_story(*key)?;
        }

        Ok(())
    }

    pub fn remove_story(&mut self, key: u32) -> Result<(), Error> {
        if self.views.remove(&key).is_some() {
            self.view_container.remove_child(key, None).unwrap_or_else(|e| {
                eprintln!("view_container.remove_child failed for key {} with {}", key, e);
            });
            self.layout()?;
            self.update();
        }
        Ok(())
    }

    pub fn list_stories(&self) -> (Vec<u32>, Vec<String>, Vec<SizeF>, Vec<bool>) {
        let mut keys = Vec::new();
        let mut urls = Vec::new();
        let mut sizes = Vec::new();
        let mut fs = Vec::new();
        for (key, view) in &self.views {
            let bounds =
                view.bounds.as_ref().unwrap_or(&RectF { x: 0.0, y: 0.0, width: 0.0, height: 0.0 });
            keys.push(*key);
            urls.push(view.url.clone());
            sizes.push(SizeF { width: bounds.width, height: bounds.height });
            fs.push(true);
        }
        (keys, urls, sizes, fs)
    }

    pub fn handle_hot_key(&mut self, event: &KeyboardEvent, key_to_use: u32) -> Result<(), Error> {
        if event.code_point == 0x20 {
            if let Some(ask_box) = self.ask_box.as_mut() {
                ask_box.focus(&self.view_container)?;
            } else {
                self.ask_box = Some(AskBox::new(
                    key_to_use,
                    &self.session,
                    &self.view_container,
                    &self.import_node,
                )?);
                self.update();
                self.layout()?;
            }
        }
        Ok(())
    }

    pub fn remove_ask_box(&mut self) {
        if let Some(mut ask_box) = self.ask_box.take() {
            ask_box
                .remove(&self.view_container)
                .unwrap_or_else(|e| eprintln!("ask_box.remove error: {:?}", e));
        }
    }

    pub fn handle_suggestion(&mut self, text: &str) -> Result<(), Error> {
        let story_name = random_story_name();
        let package = format!("fuchsia-pkg://fuchsia.com/{}#meta/{}.cmx", text, text);
        let (story_puppet_master, story_puppet_master_end) =
            create_proxy().context("handle_suggestion control_story")?;
        self.puppet_master.control_story(&story_name, story_puppet_master_end)?;
        let mut commands = [StoryCommand::AddMod(AddMod {
            mod_name_transitional: Some(random_mod_name()),
            intent: Intent { action: None, handler: Some(package), parameters: None },
            surface_parent_mod_name: None,
            surface_relation: SurfaceRelation {
                arrangement: SurfaceArrangement::None,
                dependency: SurfaceDependency::None,
                emphasis: 1.0,
            },
            ..AddMod::new_empty()
        })];
        story_puppet_master
            .enqueue(&mut commands.iter_mut())
            .context("handle_suggestion story_puppet_master.enqueue")?;
        let f = story_puppet_master.execute();
        fasync::spawn(
            f.map_ok(move |_| {}).unwrap_or_else(|e| eprintln!("puppetmaster error: {:?}", e)),
        );
        self.story_puppet_masters.insert(story_name, story_puppet_master);

        Ok(())
    }

    pub fn layout(&mut self) -> Result<(), Error> {
        if !self.views.is_empty() {
            let num_tiles = self.views.len();

            let columns = (num_tiles as f32).sqrt().ceil() as usize;
            let rows = (columns + num_tiles - 1) / columns;
            let tile_height = (self.height / rows as f32).floor();

            for (row_index, view_chunk) in
                self.views.iter_mut().chunks(columns).into_iter().enumerate()
            {
                let tiles_in_row = if row_index == rows - 1 && (num_tiles % columns) != 0 {
                    num_tiles % columns
                } else {
                    columns
                };
                let tile_width = (self.width / tiles_in_row as f32).floor();
                for (column_index, (_key, view)) in view_chunk.enumerate() {
                    let mut tile_bounds = RectF {
                        height: tile_height,
                        width: tile_width,
                        x: column_index as f32 * tile_width,
                        y: row_index as f32 * tile_height,
                    };
                    inset(&mut tile_bounds, 10.0);
                    let mut view_properties = ViewProperties {
                        custom_focus_behavior: Some(Box::new(CustomFocusBehavior {
                            allow_focus: view.allow_focus,
                        })),
                        view_layout: Some(Box::new(ViewLayout {
                            inset: InsetF { bottom: 0.0, left: 0.0, right: 0.0, top: 0.0 },
                            size: SizeF { width: tile_bounds.width, height: tile_bounds.height },
                        })),
                    };
                    self.view_container
                        .set_child_properties(view.key, Some(OutOfLine(&mut view_properties)))?;
                    view.host_node.set_translation(tile_bounds.x, tile_bounds.y, 0.0);
                    view.bounds = Some(tile_bounds);
                }
            }
        }

        if let Some(ask_box) = self.ask_box.as_ref() {
            ask_box.layout(&self.view_container, self.width, self.height)?;
        }

        Ok(())
    }
}
