use embedded_graphics::{
    pixelcolor::Gray8,
    prelude::{DrawTarget, OriginDimensions},
};

use crate::input::InputEvent;

use super::{frame::Frame, screens::demo::DemoScreen, RefreshHint};

pub struct App {
    screen: DemoScreen,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AppUpdate {
    pub dirty: bool,
    pub refresh: RefreshHint,
    pub command: Option<AppCommand>,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum AppCommand {
    SetFrontLight { on: bool },
}

impl App {
    pub fn new() -> Self {
        Self {
            screen: DemoScreen::new(),
        }
    }

    pub fn update(&mut self, event: InputEvent) -> AppUpdate {
        let update = self.screen.update(event);
        AppUpdate::new(update.dirty, update.refresh, update.command)
    }

    pub fn render<D>(&self, target: &mut D) -> Result<(), D::Error>
    where
        D: DrawTarget<Color = Gray8> + OriginDimensions,
    {
        let mut frame = Frame::new(target);
        frame.clear()?;
        self.screen.render(&mut frame)
    }
}

impl AppUpdate {
    pub const fn new(dirty: bool, refresh: RefreshHint, command: Option<AppCommand>) -> Self {
        Self {
            dirty,
            refresh,
            command,
        }
    }
}

impl Default for App {
    fn default() -> Self {
        Self::new()
    }
}
