// file: poc-qt/poc005/src/bridge.rs

use core::pin::Pin;
use gstreamer as gst;
use gstreamer::prelude::*;

#[derive(Default)]
pub struct GstControllerRust {
    started: bool,
}

#[cxx_qt::bridge]
pub mod qobject {
    extern "RustQt" {
        #[qobject]
        #[qml_element]
        #[qproperty(bool, started)]
        type GstController = super::GstControllerRust;

        #[qinvokable]
        #[cxx_name = "startPreview"]
        fn start_preview(self: Pin<&mut GstController>);

        #[qinvokable]
        #[cxx_name = "stopPreview"]
        fn stop_preview(self: Pin<&mut GstController>);
    }
}

impl qobject::GstController {
    pub fn start_preview(self: Pin<&mut Self>) {
        if *self.started() {
            println!("preview already started");
            return;
        }

        if let Err(err) = gst::init() {
            eprintln!("gst init failed: {err}");
            return;
        }

        let pipeline_str = "v4l2src ! videoconvert ! fakesink";

        let element = match gst::parse::launch(pipeline_str) {
            Ok(v) => v,
            Err(err) => {
                eprintln!("failed to parse pipeline: {err}");
                return;
            }
        };

        let pipeline: gst::Pipeline = match element.downcast::<gst::Pipeline>() {
            Ok(v) => v,
            Err(_) => {
                eprintln!("parsed element is not a gst::Pipeline");
                return;
            }
        };

        match pipeline.set_state(gst::State::Playing) {
            Ok(_) => {
                println!("pipeline started");
                self.set_started(true);
            }
            Err(err) => {
                eprintln!("failed to set pipeline to Playing: {err:?}");
            }
        }
    }

    pub fn stop_preview(self: Pin<&mut Self>) {
        if !*self.started() {
            println!("preview already stopped");
            return;
        }

        self.set_started(false);
        println!("pipeline stop requested");
    }
}
