use ratatui::layout::{ Rect, Flex };
use ratatui::prelude::*;

use super::{Pane, RenderBuffer, RenderTarget};

#[derive(Debug, Clone, clap::ValueEnum)]
pub enum RenderLayoutKind {
  #[value(name = "horizontal", aliases = ["h"])]
  CliHorizontal,
  #[value(name = "vertical", aliases = ["v"])]
  CliVertical,

  CliOutputSplit,
}

const CLI_INPUT_PREFIX: &str = "> ";

#[derive(Debug)]
pub struct RenderLayout {
  layout: Layout,
  pub panes: Vec<Pane>,
}

impl Widget for &mut RenderLayout {
  fn render(self, area: Rect, buffer: &mut Buffer) {
    let rects = self.rects(area);

    for (p, r) in self.panes.iter_mut().zip(rects.iter()) {
      p.render(*r, buffer);
    }
  }
}

pub fn center(area: Rect, horizontal: Constraint, vertical: Constraint) -> Rect {
    let [area] = Layout::horizontal([horizontal])
        .flex(Flex::Center)
        .areas(area);
    let [area] = Layout::vertical([vertical]).flex(Flex::Center).areas(area);
    area
}

impl RenderLayout {
  pub fn rects(&self, area: Rect) -> std::rc::Rc<[Rect]> {
    self.layout.split(area)
  }

  pub fn generate(kind: RenderLayoutKind) -> RenderLayout {
    match kind {
      RenderLayoutKind::CliVertical => RenderLayout {
        layout: Layout::default()
          .constraints([Constraint::Percentage(70), Constraint::Percentage(30)]),
        panes: vec![
          Pane::new(
            Some(" Input Pane ".to_string()),
            RenderTarget::CliInput,
            RenderBuffer::List {
              list: vec![String::new()],
              index: 0,
              prefix: CLI_INPUT_PREFIX,
            },
            true,
          ),
          Pane::new(
            Some(" Output Pane ".to_string()),
            RenderTarget::CliOutput,
            RenderBuffer::String(String::new()),
            false,
          ),
        ],
      },
      RenderLayoutKind::CliHorizontal => RenderLayout {
        layout: Layout::default()
          .constraints([Constraint::Percentage(70), Constraint::Percentage(30)]),
        panes: vec![
          Pane::new(
            Some(" Output Pane ".to_string()),
            RenderTarget::CliOutput,
            RenderBuffer::String(String::new()),
            false,
          ),
          Pane::new(
            Some(" Input Pane ".to_string()),
            RenderTarget::CliInput,
            RenderBuffer::List {
              list: vec![String::new()],
              index: 0,
              prefix: CLI_INPUT_PREFIX,
            },
            true,
          ),
        ],
      },
      RenderLayoutKind::CliOutputSplit => {
        let layout = Layout::default()
          .constraints([Constraint::Percentage(70), Constraint::Percentage(30)]);
        RenderLayout {
          layout,
          panes: vec![]
        }
      }
    }
  }
}
