use super::common;
use crate::{InstalledTab, Message, SoftwareApp};
use cosmic::iced::{Alignment, Length};
use cosmic::{theme, widget, Element};
use rakuos_packages::{FlatpakRuntime, NativeApp};

pub fn view(app: &SoftwareApp, _width: usize) -> Element<'_, Message> {
    if app.loading {
        return common::loading_page("Loading installed apps...");
    }

    let spacing = theme::active().cosmic().spacing;
    let mut column = widget::column::with_capacity(4)
        .padding([0, spacing.space_s, spacing.space_m, spacing.space_s])
        .spacing(spacing.space_xs)
        .width(Length::Fill);

    column = column.push(tab_bar(app));
    column = column.push(widget::divider::horizontal::default());

    column = column.push(match app.installed_tab {
        InstalledTab::Rpm => app_list(&app.installed_data.rpm_apps, "No overlay packages installed.", false),
        InstalledTab::Flatpak => flatpak_tab(app),
        InstalledTab::AppImages => app_list(&app.installed_data.app_images, "No AppImages installed.", false),
        InstalledTab::WebApps => app_list(&app.installed_data.web_apps, "No web apps installed.", false),
    });

    column.into()
}

fn tab_bar(app: &SoftwareApp) -> Element<'_, Message> {
    let tabs = [
        (InstalledTab::Rpm, format!("RPM ({})", app.installed_data.rpm_apps.len())),
        (
            InstalledTab::Flatpak,
            if app.installed_data.flatpak_runtimes.is_empty() {
                format!("Flatpak ({})", app.installed_data.flatpak_apps.len())
            } else {
                format!(
                    "Flatpak ({}) + {} runtimes",
                    app.installed_data.flatpak_apps.len(),
                    app.installed_data.flatpak_runtimes.len()
                )
            },
        ),
        (
            InstalledTab::AppImages,
            format!("AppImages ({})", app.installed_data.app_images.len()),
        ),
        (
            InstalledTab::WebApps,
            format!("Web Apps ({})", app.installed_data.web_apps.len()),
        ),
    ];

    let spacing = theme::active().cosmic().spacing;
    let mut row = widget::row().spacing(spacing.space_xs).align_y(Alignment::Center);
    for (tab, label) in tabs {
        let button: Element<_> = if app.installed_tab == tab {
            widget::button::suggested(label)
                .on_press(Message::SelectInstalledTab(tab))
                .into()
        } else {
            widget::button::standard(label)
                .on_press(Message::SelectInstalledTab(tab))
                .into()
        };
        row = row.push(button);
    }
    row.into()
}

fn flatpak_tab(app: &SoftwareApp) -> Element<'_, Message> {
    let spacing = theme::active().cosmic().spacing;
    if app.installed_data.flatpak_apps.is_empty() && app.installed_data.flatpak_runtimes.is_empty() {
        return common::message_page("Flatpak", "No Flatpaks installed.");
    }

    let mut column = widget::column().spacing(spacing.space_xxs).width(Length::Fill);

    if !app.installed_data.flatpak_apps.is_empty() {
        column = column
            .push(widget::text::caption("Applications"))
            .push(app_list(&app.installed_data.flatpak_apps, "", false));
    }

    if !app.installed_data.flatpak_runtimes.is_empty() {
        column = column.push(widget::text::caption("Runtimes / Add-ons"));
        for runtime in &app.installed_data.flatpak_runtimes {
            column = column.push(runtime_row(runtime));
        }
    }

    column.into()
}

fn app_list<'a>(apps: &'a [NativeApp], empty_text: &'static str, title_only: bool) -> Element<'a, Message> {
    if apps.is_empty() {
        return widget::container(widget::text::body(empty_text))
            .width(Length::Fill)
            .height(Length::Fill)
            .center_x(Length::Fill)
            .center_y(Length::Fill)
            .into();
    }

    let spacing = theme::active().cosmic().spacing;
    let mut column = widget::column().spacing(0).width(Length::Fill);
    for app in apps {
        column = column.push(app_row(app, title_only));
        column = column.push(widget::divider::horizontal::default());
    }
    column.spacing(spacing.space_xxxs).into()
}

fn app_row(app: &NativeApp, title_only: bool) -> Element<'_, Message> {
    let spacing = theme::active().cosmic().spacing;
    let app_for_click = app.clone();
    let mut text_column = widget::column::with_children(vec![
        widget::text::body(&app.name).into(),
    ])
    .spacing(2)
    .width(Length::Fill);

    if !title_only && !app.summary.is_empty() {
        text_column = text_column.push(widget::text::caption(&app.summary));
    }

    let mut row = widget::row::with_children(vec![
        common::app_icon(&app.icon_path, &app.icon_url, 32),
        text_column.into(),
    ])
    .spacing(spacing.space_s)
    .align_y(Alignment::Center)
    .width(Length::Fill);

    if !app.version.is_empty() {
        row = row.push(widget::text::caption(&app.version));
    }

    widget::mouse_area(
        widget::container(row)
            .width(Length::Fill)
            .height(Length::Fixed(if title_only { 48.0 } else { 52.0 }))
            .padding([0, spacing.space_s])
            .align_y(Alignment::Center),
    )
    .on_press(Message::SelectInstalledApp(app_for_click))
    .into()
}

fn runtime_row(runtime: &FlatpakRuntime) -> Element<'_, Message> {
    let spacing = theme::active().cosmic().spacing;
    widget::container(
        widget::row::with_children(vec![
            widget::icon::from_name("application-x-addon").size(32).into(),
            widget::column::with_children(vec![
                widget::text::body(&runtime.name).into(),
                widget::text::caption(format!(
                    "{}{}{}",
                    runtime.app_id,
                    if runtime.version.is_empty() { "" } else { " · " },
                    runtime.version
                ))
                .into(),
            ])
            .width(Length::Fill)
            .into(),
            widget::text::caption(&runtime.origin).into(),
        ])
        .spacing(spacing.space_s)
        .align_y(Alignment::Center),
    )
    .width(Length::Fill)
    .height(Length::Fixed(52.0))
    .padding([0, spacing.space_s])
    .align_y(Alignment::Center)
    .into()
}
