#[cfg(target_arch = "wasm32")]
use ratzilla::ratatui;

use ratatui::{
    layout::{Constraint, Direction, Layout},
    style::{Color, Style, Stylize},
    widgets::{Block, Borders, Paragraph, Tabs},
    Frame,
};
use tachyonfx::{fx, Effect, Interpolation, Shader};
use web_time::Instant;

use crate::app::password_locker::PasswordLocker;

mod password_locker;

pub struct App {
    transition_instant: Instant,
    selected_tab: usize,
    password_locker: PasswordLocker,
    current_effect: Effect,
}

const SPLASH: &str = r#"
!~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
!~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
!!~~~~~~!J5PPPPPPPPPPP?^^^^7PPPPPPPPPPPPPPPPY~^^^^
!!!!!!~~~!JB&@@@@@@@@@5^^^^Y@@@@@@@@@@@@@@@@#~^^^^
!!!!!5?!~~~!JG&@@@@@@@5^^^^Y@@@@@@@@@@@@@@@@#~^^^^
!!!!7#&GJ!~~~!?G&@@@@@5^^^^Y@@@@@@@@@@@@@@@@#~^^^^
7!!!7#@@&BJ!~~~!?G&@@@5^^^^Y@@@@@@@@@@@@@@@@#~^^^^
7!!!7#@@@@@BY!~~~~?P&@5~^^^Y@@@@@@@@@@@@@@@@#~^^^^
777!7#@@@@@@@BY!~~~~7PY~~~^Y@@@@@@@@@@@@@@@@#~^^^^
7777?#@@@@@@@@@#Y7~~~~!~~~~Y@@@@@@@@@@@@@@@@#~^^^^
7777?#@@@@@@@@@@@#57~~~~~~~Y@@@@@@@@@@@@@@@@#~^^^^
?777?#@@@@@@@@@@@@@#57~~~~~?#@@@@@@@@@@@@@@@#~^^^^
?777?#@@@@@@@@@@@@@@@#J~~~~~!Y#@@@@@@@@@@@@@#~^^^^
???7?#@@@@@@@@@@@@@@@@P!!~~~~~!YB@@@@@@@@@@@#~^^^^
?????#@@@@@@@@@@@@@@@@P!!!!!!~~~!YB@@@@@@@@@#~^^^^
????J&@@@@@@@@@@@@@@@@P!!!!YG?!~~~!JB&@@@@@@#~^^^^
????J&@@@@@@@@@@@@@@@@P!!!!5@&G?!~~~!JG&@@@@#~^^^^
J???J&@@@@@@@@@@@@@@@@P!!!!5@@@&GJ!~~~!?G&@@#!^^^^
J???J&@@@@@@@@@@@@@@@@P7!!!5@@@@@&BJ!~~~!?G&#!^^^~
JJJ?J&@@@@@@@@@@@@@@@@P777!5@@@@@@@@BY!~~~~?5!~~^~
JJJJJ&@@@@@@@@@@@@@@@@P77775@@@@@@@@@@BY!~~~~~~~~~
JJJJJGBBGGGGGGGGGGGGGGY7777JGGGGGGGPPPPPY!~~~~~~~~
YJJJJJJJJJ????????????77777777777!!!!!!!!!!!~~~~~~
YJJJJJJJJJJJ???????????77777777777!!!!!!!!!!!~~~~~
"#;

const TABS: [&'static str; 3] = ["Whatzahoozits", "Thingamajigs", "Doohickeys"];

impl App {
    pub fn new() -> Self {
        Self {
            transition_instant: Instant::now(),
            selected_tab: 0,
            password_locker: PasswordLocker::default(),
            current_effect: fx::fade_from_fg(Color::Black, (0, Interpolation::CircIn)),
        }
    }

    pub fn draw(&mut self, frame: &mut Frame) {
        if self.password_locker.unlocked() {
            self.draw_rest(frame);
        }
        self.draw_passcode(frame);
        let area = frame.area();

        self.current_effect.process(
            self.transition_instant.elapsed().into(),
            frame.buffer_mut(),
            area,
        );
    }

    pub fn draw_passcode(&mut self, frame: &mut Frame) {
        frame.render_widget(&mut self.password_locker, frame.area());
        if let Some(cursor_position) = self.password_locker.cursor_position() {
            if self.password_locker.current_effect_done() {
                frame.set_cursor_position(cursor_position);
            }
        }
    }

    pub fn draw_rest(&mut self, frame: &mut Frame) {
        let layout = Layout::new(
            Direction::Vertical,
            [Constraint::Length(3), Constraint::Min(0)],
        )
        .split(frame.area());
        frame.render_widget(
            Tabs::new(TABS)
                .select(self.selected_tab)
                .fg(Color::Rgb(226, 190, 89))
                .bg(Color::Black)
                .highlight_style(Style::new().bold())
                .block(Block::new().borders(Borders::all()).title("Coming soon")),
            layout[0],
        );
        frame.render_widget(
            Paragraph::new(SPLASH)
                .alignment(ratatui::layout::Alignment::Center)
                .fg(Color::Rgb(226, 190, 89))
                .bg(Color::Black)
                .block(Block::new().borders(Borders::all())),
            layout[1],
        );
    }

    pub fn add_char_to_number_guess(&mut self, c: char) {
        self.password_locker.add_char_to_number_guess(c);
    }

    pub fn next_tab(&mut self) {
        self.transition_instant = Instant::now();
        if self.selected_tab == TABS.len() - 1 {
            self.selected_tab = 0;
        } else {
            self.selected_tab += 1;
        }
    }

    pub fn prev_tab(&mut self) {
        self.transition_instant = Instant::now();
        if self.selected_tab == 0 {
            self.selected_tab = TABS.len() - 1;
        } else {
            self.selected_tab -= 1;
        }
    }
}
