// Copyright 2020 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 carnelian::{
    color::Color,
    drawing::{load_font, FontFace},
    facet::*,
    input::{self},
    render::Context as RenderContext,
    App, AppAssistant, AppAssistantPtr, AppContext, AssistantCreatorFunc, Coord, LocalBoxFuture,
    Size, ViewAssistant, ViewAssistantContext, ViewAssistantPtr, ViewKey,
};
use euclid::point2;
use fuchsia_zircon::Event;
use lipsum::lipsum_words;
use std::path::PathBuf;

const LINE_THICKNESS: Coord = 2.0;
const BASELINE_INDENT: Coord = 0.15;
const PADDING: Coord = 0.005;

struct FontAppAssistant {
    app_context: AppContext,
}

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

    fn create_view_assistant(&mut self, view_key: ViewKey) -> Result<ViewAssistantPtr, Error> {
        Ok(FontMetricsViewAssistant::new(&self.app_context, view_key)?)
    }
}

struct SceneDetails {
    scene: Scene,
    sample_title: FacetId,
    sample_paragraph: FacetId,
    lines: Vec<FacetId>,
}

struct FontMetricsViewAssistant {
    app_context: AppContext,
    view_key: ViewKey,
    sample_title: String,
    sample_paragraph: String,
    sample_faces: Vec<FontFace>,
    sample_index: usize,
    sample_size_divisor: f32,
    label_face: FontFace,
    scene_details: Option<SceneDetails>,
    line_color: Color,
    round_scene_corners: bool,
}

impl FontMetricsViewAssistant {
    fn new(app_context: &AppContext, view_key: ViewKey) -> Result<ViewAssistantPtr, Error> {
        let ss = load_font(PathBuf::from("/pkg/data/fonts/ShortStack-Regular.ttf"))?;
        let ds = load_font(PathBuf::from("/pkg/data/fonts/DroidSerif-Regular.ttf"))?;
        let qr = load_font(PathBuf::from("/pkg/data/fonts/Quintessential-Regular.ttf"))?;
        let sample_faces = vec![ss, ds, qr];
        let label_face = load_font(PathBuf::from("/pkg/data/fonts/Roboto-Regular.ttf"))?;
        let (title, para) = Self::new_sample_pair();
        Ok(Box::new(Self {
            app_context: app_context.clone(),
            view_key,
            sample_title: title,
            sample_paragraph: para,
            sample_faces,
            sample_index: 0,
            sample_size_divisor: 6.0,
            label_face,
            scene_details: None,
            line_color: Color::new(),
            round_scene_corners: true,
        }))
    }

    fn new_sample_pair() -> (String, String) {
        (lipsum_words(2), lipsum_words(25))
    }

    fn update(&mut self) {
        self.scene_details = None;
        self.app_context.request_render(self.view_key);
    }

    fn new_sample_text(&mut self) {
        let (title, para) = Self::new_sample_pair();
        self.sample_title = title;
        self.sample_paragraph = para;
        if let Some(scene_details) = self.scene_details.as_mut() {
            scene_details.scene.send_message(
                &scene_details.sample_title.clone(),
                Box::new(SetTextMessage { text: self.sample_title.clone() }),
            );
            scene_details.scene.send_message(
                &scene_details.sample_paragraph.clone(),
                Box::new(SetTextMessage { text: self.sample_paragraph.clone() }),
            );
        }
        self.app_context.request_render(self.view_key);
    }

    fn show_next_face(&mut self) {
        self.sample_index = (self.sample_index + 1) % self.sample_faces.len();
        self.update();
    }

    fn increase_sample_size(&mut self) {
        self.sample_size_divisor = (self.sample_size_divisor - 0.5).max(1.0);
        self.update();
    }

    fn decrease_sample_size(&mut self) {
        self.sample_size_divisor = (self.sample_size_divisor + 0.5).min(10.0);
        self.update();
    }

    fn toggle_line_color(&mut self) {
        let black = Color::new();
        if self.line_color == black {
            self.line_color = Color::white();
        } else {
            self.line_color = black;
        }
        if let Some(scene_details) = self.scene_details.as_mut() {
            let targets: Vec<FacetId> = scene_details.lines.iter().cloned().collect();
            for target in targets {
                scene_details
                    .scene
                    .send_message(&target, Box::new(SetColorMessage { color: self.line_color }));
            }
        }
        self.app_context.request_render(self.view_key);
    }

    fn toggle_round_scene_corners(&mut self) {
        self.round_scene_corners = !self.round_scene_corners;
        if let Some(scene_details) = self.scene_details.as_mut() {
            scene_details.scene.round_scene_corners(self.round_scene_corners);
        }
        self.app_context.request_render(self.view_key);
    }
}

impl ViewAssistant for FontMetricsViewAssistant {
    fn resize(&mut self, _new_size: &Size) -> Result<(), Error> {
        self.scene_details = None;
        Ok(())
    }

    fn render(
        &mut self,
        render_context: &mut RenderContext,
        ready_event: Event,
        context: &ViewAssistantContext,
    ) -> Result<(), Error> {
        let mut scene_details = self.scene_details.take().unwrap_or_else(|| {
            let mut builder = SceneBuilder::new(Color::white());
            builder.round_scene_corners(self.round_scene_corners);
            let size = context.size;
            let text_size = size.height.min(size.width) / self.sample_size_divisor;
            let ascent = self.sample_faces[self.sample_index].ascent(text_size);
            let descent = self.sample_faces[self.sample_index].descent(text_size);
            let sample_text_size = text_size / 3.0;
            let baseline_location = size.height / 3.0;
            let baseline_left = size.width * BASELINE_INDENT;
            let baseline_width = size.width * (1.0 - BASELINE_INDENT * 2.0);
            let baseline_right = baseline_left + baseline_width;

            let sample_title = builder.text(
                self.sample_faces[self.sample_index].clone(),
                &self.sample_title,
                text_size,
                point2(size.width / 2.0, baseline_location),
                TextFacetOptions {
                    horizontal_alignment: TextHorizontalAlignment::Center,
                    ..TextFacetOptions::default()
                },
            );

            let paragraph_baseline_location = size.height / 2.0;

            let sample_paragraph = builder.text(
                self.sample_faces[self.sample_index].clone(),
                &self.sample_paragraph,
                sample_text_size,
                point2(baseline_left, paragraph_baseline_location),
                TextFacetOptions {
                    horizontal_alignment: TextHorizontalAlignment::Left,
                    max_width: Some(baseline_width),
                    ..TextFacetOptions::default()
                },
            );

            let mut lines = Vec::new();

            lines.push(builder.h_line(
                baseline_location,
                baseline_left,
                baseline_right,
                LINE_THICKNESS,
                self.line_color,
            ));

            let ascent_x = baseline_left + size.width * BASELINE_INDENT / 5.0;
            lines.push(builder.v_line(
                ascent_x,
                baseline_location - ascent,
                baseline_location,
                LINE_THICKNESS,
                self.line_color,
            ));

            lines.push(builder.v_line(
                ascent_x,
                baseline_location,
                baseline_location - descent,
                LINE_THICKNESS,
                self.line_color,
            ));

            let label_size = size.height.min(size.width) / 30.0;

            builder.text(
                self.label_face.clone(),
                "baseline",
                label_size,
                point2(baseline_right + PADDING * size.width, baseline_location),
                TextFacetOptions {
                    vertical_alignment: TextVerticalAlignment::Center,
                    ..TextFacetOptions::default()
                },
            );

            builder.text(
                self.label_face.clone(),
                "ascent",
                label_size,
                point2(ascent_x - PADDING * size.width, baseline_location - ascent / 2.0),
                TextFacetOptions {
                    vertical_alignment: TextVerticalAlignment::Center,
                    horizontal_alignment: TextHorizontalAlignment::Right,
                    ..TextFacetOptions::default()
                },
            );

            builder.text(
                self.label_face.clone(),
                "descent",
                label_size,
                point2(ascent_x - PADDING * size.width, baseline_location - descent / 2.0),
                TextFacetOptions {
                    vertical_alignment: TextVerticalAlignment::Center,
                    horizontal_alignment: TextHorizontalAlignment::Right,
                    ..TextFacetOptions::default()
                },
            );

            let scene = builder.build();
            SceneDetails { scene, sample_paragraph, sample_title, lines }
        });

        scene_details.scene.render(render_context, ready_event, context)?;
        self.scene_details = Some(scene_details);
        Ok(())
    }

    fn handle_keyboard_event(
        &mut self,
        _context: &mut ViewAssistantContext,
        _event: &input::Event,
        keyboard_event: &input::keyboard::Event,
    ) -> Result<(), Error> {
        const C: u32 = 'c' as u32;
        const F: u32 = 'f' as u32;
        const K: u32 = 'k' as u32;
        const T: u32 = 't' as u32;
        const PLUS: u32 = '+' as u32;
        const EQUALS: u32 = '=' as u32;
        const MINUS: u32 = '-' as u32;
        if let Some(code_point) = keyboard_event.code_point {
            if keyboard_event.phase == input::keyboard::Phase::Pressed {
                match code_point {
                    T => self.new_sample_text(),
                    F => self.show_next_face(),
                    PLUS | EQUALS => self.increase_sample_size(),
                    MINUS => self.decrease_sample_size(),
                    C => self.toggle_line_color(),
                    K => self.toggle_round_scene_corners(),
                    _ => println!("code_point = {}", code_point),
                }
            }
        }
        Ok(())
    }
}

fn make_app_assistant_fut(
    app_context: &AppContext,
) -> LocalBoxFuture<'_, Result<AppAssistantPtr, Error>> {
    let f = async move {
        let assistant = Box::new(FontAppAssistant { app_context: app_context.clone() });
        Ok::<AppAssistantPtr, Error>(assistant)
    };
    Box::pin(f)
}

pub fn make_app_assistant() -> AssistantCreatorFunc {
    Box::new(make_app_assistant_fut)
}

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