use std::time::{Duration, Instant};

use ratatui::{
    buffer::Buffer,
    layout::Rect,
    style::{Color, Style},
};

/// 20×12 pixel grid of the rooster facing left.
const ROOSTER_NORMAL: [[Option<Color>; 20]; 12] = [
    [
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        Some(Color::White),
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        Some(Color::White),
        Some(Color::White),
        Some(Color::White),
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
];

/// 20×12 pixel grid of the rooster pecking (head tilted down toward the ground).
const ROOSTER_PECK: [[Option<Color>; 20]; 12] = [
    [None; 20],
    [
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        Some(Color::White),
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        Some(Color::White),
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        Some(Color::White),
        Some(Color::White),
        None,
        None,
        Some(Color::White),
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
    [
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        Some(Color::White),
        None,
        Some(Color::White),
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
    ],
];

fn rooster_pixels(pecking: bool) -> &'static [[Option<Color>; 20]; 12] {
    if pecking {
        &ROOSTER_PECK
    } else {
        &ROOSTER_NORMAL
    }
}

/// Render the braille-dot rooster into a 3-row area.
pub fn render_rooster_braille(buf: &mut Buffer, area: Rect, pecking: bool) {
    let pixels = rooster_pixels(pecking);
    let braille_cols = area.width.min(10);
    let braille_rows = area.height.min(3);

    for by in 0..braille_rows {
        for bx in 0..braille_cols {
            let mut bits: u8 = 0;

            for py in 0..4 {
                for px in 0..2 {
                    let pixel_x = (bx * 2 + px) as usize;
                    let pixel_y = (by * 4 + py) as usize;
                    if pixel_x >= 20 || pixel_y >= 12 {
                        continue;
                    }
                    if pixels[pixel_y][pixel_x].is_some() {
                        let bit = match (px, py) {
                            (0, 0) => 0x01,
                            (0, 1) => 0x02,
                            (0, 2) => 0x04,
                            (0, 3) => 0x40,
                            (1, 0) => 0x08,
                            (1, 1) => 0x10,
                            (1, 2) => 0x20,
                            (1, 3) => 0x80,
                            _ => 0,
                        };
                        bits |= bit;
                    }
                }
            }

            if bits != 0 {
                let ch = char::from_u32(0x2800 + bits as u32).unwrap_or(' ');
                buf.set_string(
                    area.x + bx,
                    area.y + by,
                    ch.encode_utf8(&mut [0u8; 4]),
                    Style::default().fg(Color::White),
                );
            }
        }
    }
}

/// Animation state for the rooster pecking.
pub struct RoosterState {
    pub is_pecking: bool,
    last_tick: Instant,
    interval: Duration,
}

impl RoosterState {
    pub fn new() -> Self {
        Self {
            is_pecking: false,
            last_tick: Instant::now(),
            interval: Duration::from_secs(4),
        }
    }

    /// Advance the animation by one tick. Should be called before each render.
    pub fn tick(&mut self) {
        let now = Instant::now();
        if now.duration_since(self.last_tick) >= self.interval {
            self.is_pecking = !self.is_pecking;
            self.last_tick = now;
            self.interval = if self.is_pecking {
                Duration::from_millis(500)
            } else {
                Duration::from_secs(4)
            };
        }
    }
}
