use rustc_hash::FxHashMap;
use crate::colors::{Colorscheme, GeneralColorscheme};
use crate::logo::build_remote_logo_paragraph;
use crate::mode::{mode_color, Mode};
use crate::results::build_results_list;
use television_channels::entry::Entry;
use television_utils::input::Input;
use color_eyre::eyre::Result;
use ratatui::layout::{Alignment, Constraint, Direction, Layout, Rect};
use ratatui::prelude::Style;
use ratatui::style::{Color, Stylize};
use ratatui::text::{Line, Span};
use ratatui::widgets::{
Block, BorderType, Borders, ListDirection, ListState, Padding, Paragraph,
};
use ratatui::Frame;
#[allow(clippy::too_many_arguments)]
pub fn draw_remote_control(
f: &mut Frame,
rect: Rect,
entries: &[Entry],
use_nerd_font_icons: bool,
picker_state: &mut ListState,
input_state: &mut Input,
icon_color_cache: &mut FxHashMap<String, Color>,
mode: &Mode,
colorscheme: &Colorscheme,
) -> Result<()> {
let layout = Layout::default()
.direction(Direction::Vertical)
.constraints(
[
Constraint::Min(3),
Constraint::Length(3),
Constraint::Length(20),
]
.as_ref(),
)
.split(rect);
draw_rc_channels(
f,
layout[0],
entries,
use_nerd_font_icons,
picker_state,
icon_color_cache,
colorscheme,
);
draw_rc_input(f, layout[1], input_state, colorscheme)?;
draw_rc_logo(
f,
layout[2],
mode_color(*mode, &colorscheme.mode),
&colorscheme.general,
);
Ok(())
}
fn draw_rc_channels(
f: &mut Frame,
area: Rect,
entries: &[Entry],
use_nerd_font_icons: bool,
picker_state: &mut ListState,
icon_color_cache: &mut FxHashMap<String, Color>,
colorscheme: &Colorscheme,
) {
let rc_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.border_style(Style::default().fg(colorscheme.general.border_fg))
.style(
Style::default()
.bg(colorscheme.general.background.unwrap_or_default()),
)
.padding(Padding::right(1));
let channel_list = build_results_list(
rc_block,
entries,
None,
ListDirection::TopToBottom,
use_nerd_font_icons,
icon_color_cache,
&colorscheme.results,
);
f.render_stateful_widget(channel_list, area, picker_state);
}
fn draw_rc_input(
f: &mut Frame,
area: Rect,
input: &mut Input,
colorscheme: &Colorscheme,
) -> Result<()> {
let input_block = Block::default()
.title_top(Line::from("Remote Control").alignment(Alignment::Center))
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.border_style(Style::default().fg(colorscheme.general.border_fg))
.style(
Style::default()
.bg(colorscheme.general.background.unwrap_or_default()),
);
let input_block_inner = input_block.inner(area);
f.render_widget(input_block, area);
let inner_input_chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Length(2),
Constraint::Fill(1),
])
.split(input_block_inner);
let prompt_symbol_block = Block::default();
let arrow = Paragraph::new(Span::styled(
"> ",
Style::default().fg(colorscheme.input.input_fg).bold(),
))
.block(prompt_symbol_block);
f.render_widget(arrow, inner_input_chunks[0]);
let interactive_input_block = Block::default();
let width = inner_input_chunks[1].width.max(3) - 3;
let scroll = input.visual_scroll(width as usize);
let input_paragraph = Paragraph::new(input.value())
.scroll((0, u16::try_from(scroll)?))
.block(interactive_input_block)
.style(
Style::default()
.fg(colorscheme.input.input_fg)
.bold()
.italic(),
)
.alignment(Alignment::Left);
f.render_widget(input_paragraph, inner_input_chunks[1]);
f.set_cursor_position((
inner_input_chunks[1].x
+ u16::try_from(input.visual_cursor().max(scroll) - scroll)?,
inner_input_chunks[1].y,
));
Ok(())
}
fn draw_rc_logo(
f: &mut Frame,
area: Rect,
mode_color: Color,
colorscheme: &GeneralColorscheme,
) {
let logo_block = Block::default().style(
Style::default()
.fg(mode_color)
.bg(colorscheme.background.unwrap_or_default()),
);
let logo_paragraph = build_remote_logo_paragraph()
.alignment(Alignment::Center)
.block(logo_block);
f.render_widget(logo_paragraph, area);
}