// Fragments - file_page.rs
// Copyright (C) 2023  Felix Häcker <haeckerfelix@gnome.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

use std::cell::OnceCell;

use adw::prelude::*;
use adw::subclass::prelude::*;
use glib::{subclass, Properties};
use gtk::{gio, glib, CompositeTemplate};
use transmission_gobject::TrFile;

use crate::actions;
use crate::ui::FrgStatusHeader;

mod imp {
    use super::*;

    #[derive(Debug, Default, Properties, CompositeTemplate)]
    #[template(resource = "/de/haeckerfelix/Fragments/gtk/file_page.ui")]
    #[properties(wrapper_type = super::FrgFilePage)]
    pub struct FrgFilePage {
        #[property(get, set, construct_only)]
        file: OnceCell<TrFile>,

        #[template_child]
        status_header: TemplateChild<FrgStatusHeader>,
        #[template_child]
        checkbutton: TemplateChild<gtk::CheckButton>,
    }

    #[glib::object_subclass]
    impl ObjectSubclass for FrgFilePage {
        const NAME: &'static str = "FrgFilePage";
        type ParentType = adw::NavigationPage;
        type Type = super::FrgFilePage;

        fn class_init(klass: &mut Self::Class) {
            klass.bind_template();
        }

        fn instance_init(obj: &subclass::InitializingObject<Self>) {
            obj.init_template();
        }
    }

    #[glib::derived_properties]
    impl ObjectImpl for FrgFilePage {
        fn constructed(&self) {
            self.parent_constructed();
            let file = self.obj().file();

            self.obj().set_title(&file.title());

            self.status_header.set_title(file.title());

            let mimetype = gio::content_type_guess(Some(&file.name()), &[])
                .0
                .to_string();
            self.status_header.set_mimetype(mimetype);

            file.bind_property("length", &self.status_header.get(), "total-bytes")
                .sync_create()
                .build();

            file.bind_property(
                "bytes-completed",
                &self.status_header.get(),
                "downloaded-bytes",
            )
            .sync_create()
            .build();

            file.bind_property("wanted", &self.checkbutton.get(), "active")
                .sync_create()
                .bidirectional()
                .build();

            file.bind_property("bytes-completed", &self.checkbutton.get(), "sensitive")
                .transform_to(|b, bytes: i64| {
                    Some(bytes != b.source().unwrap().downcast::<TrFile>().unwrap().length())
                })
                .sync_create()
                .build();

            actions::install_file_actions(&self.obj().file(), self.obj().clone().upcast());
        }
    }

    impl WidgetImpl for FrgFilePage {}

    impl NavigationPageImpl for FrgFilePage {}
}

glib::wrapper! {
    pub struct FrgFilePage(ObjectSubclass<imp::FrgFilePage>)
        @extends gtk::Widget, adw::NavigationPage;
}

impl FrgFilePage {
    pub fn new(file: &TrFile) -> Self {
        glib::Object::builder().property("file", file).build()
    }
}
