// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#![recursion_limit = "256"]

use fidl_fuchsia_hardware_usb_policy::DeviceState;
use starnix_core::task::dynamic_thread_spawner::SpawnRequestBuilder;
use starnix_core::task::{CurrentTask, Kernel};
use starnix_logging::log_error;
use starnix_sync::{Locked, Unlocked};
use starnix_uapi::errors::Errno;

use fidl_fuchsia_usb_policy::PolicyProviderMarker;
use fuchsia_component::client::connect_to_protocol;
use starnix_core::device::kobject::{Device, UEventAction};
use starnix_core::device::mem::DevNull;
use starnix_core::device::simple_device_ops;
use starnix_core::fs::sysfs::build_device_directory;
use starnix_core::vfs::pseudo::simple_file::{BytesFile, BytesFileOps};
use starnix_core::vfs::{FsStr, FsString};
use starnix_uapi::file_mode::mode;
use std::borrow::Cow;

use std::future::Future;
use std::sync::Arc;
use std::sync::atomic::{AtomicU8, Ordering};

#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum UsbGadgetState {
    Disconnected = 0,
    Configured = 1,
    Connected = 2,
    Unknown = 3,
}

impl From<u8> for UsbGadgetState {
    fn from(val: u8) -> Self {
        match val {
            0 => UsbGadgetState::Disconnected,
            1 => UsbGadgetState::Configured,
            2 => UsbGadgetState::Connected,
            _ => UsbGadgetState::Unknown,
        }
    }
}

impl UsbGadgetState {
    pub fn to_fs_str(&self) -> &'static FsStr {
        match self {
            UsbGadgetState::Disconnected => b"DISCONNECTED".into(),
            UsbGadgetState::Configured => b"CONFIGURED".into(),
            UsbGadgetState::Connected => b"CONNECTED".into(),
            UsbGadgetState::Unknown => b"UNKNOWN".into(),
        }
    }

    pub fn map_from_device_state(state: DeviceState, previous: Option<Self>) -> Option<Self> {
        match state {
            DeviceState::NotAttached => Some(UsbGadgetState::Disconnected),
            DeviceState::Attached => Some(UsbGadgetState::Connected),
            DeviceState::Powered => Some(UsbGadgetState::Connected),
            DeviceState::Default => Some(UsbGadgetState::Connected),
            DeviceState::Address => Some(UsbGadgetState::Connected),
            DeviceState::Configured => Some(UsbGadgetState::Configured),
            DeviceState::Suspended => previous, // No change when suspended
            _ => {
                log_error!("Unexpected DeviceState: {:?}", state);
                previous
            }
        }
    }
}

#[derive(Clone)]
struct UsbStateSysfsFile {
    state: Arc<AtomicU8>,
}

impl BytesFileOps for UsbStateSysfsFile {
    fn read(&self, _current_task: &CurrentTask) -> Result<Cow<'_, [u8]>, Errno> {
        let state_val = self.state.load(Ordering::Relaxed);
        let state = UsbGadgetState::from(state_val);
        let mut content = state.to_fs_str().to_vec();
        content.push(b'\n'); // standard sysfs newline
        Ok(Cow::Owned(content))
    }
}

pub fn usb_device_init(
    locked: &mut Locked<Unlocked>,
    current_task: &CurrentTask,
) -> Result<Device, Errno> {
    let kernel = current_task.kernel();
    let registry = &kernel.device_registry;

    let android_usb_class =
        registry.objects.get_or_create_class("android_usb".into(), registry.objects.virtual_bus());

    let shared_state = Arc::new(AtomicU8::new(UsbGadgetState::Disconnected as u8));
    let state_clone = shared_state.clone();

    let device = registry.register_dyn_device_with_dir(
        locked,
        current_task,
        "android0".into(),
        android_usb_class,
        |device, dir| {
            build_device_directory(device, dir);
            dir.entry(
                "state",
                BytesFile::new_node(UsbStateSysfsFile { state: state_clone }),
                mode!(IFREG, 0o444),
            );
        },
        simple_device_ops::<DevNull>,
    )?;

    let kernel_clone = Arc::clone(kernel);
    let device_clone = device.clone();
    kernel.kthreads.spawn_future(
        move || async move {
            monitor_usb_device_state(kernel_clone, device_clone, shared_state).await;
        },
        "usb_device_state_monitor",
    );

    Ok(device)
}

// Prepare a request to broadcast a USB state change and dispatch it on a kernel thread.
fn dispatch_usb_state_change(
    kernel: &Arc<Kernel>,
    device: &Device,
    usb_state: FsString,
) -> impl Future<Output = Result<(), Errno>> {
    let spawner = kernel.kthreads.spawner();
    let device_clone = device.clone();
    let closure = move |locked: &mut Locked<Unlocked>, current_task: &CurrentTask| {
        if let Some(metadata) = &device_clone.metadata {
            metadata.properties.insert("USB_STATE".into(), usb_state);
        }

        current_task.kernel.device_registry.dispatch_uevent(
            locked,
            UEventAction::Change,
            device_clone,
        );
    };
    let (result, request) =
        SpawnRequestBuilder::new().with_sync_closure(closure).build_with_async_result();
    spawner.spawn_from_request(request);
    result
}

/// Monitor the USB state via FIDL messages from the PolicyProvider and dispatch uevents when the
/// state changes.
async fn monitor_usb_device_state(
    kernel: Arc<Kernel>,
    device: Device,
    shared_state: Arc<AtomicU8>,
) {
    let provider = connect_to_protocol::<PolicyProviderMarker>()
        .expect("USB Failed to connect to PolicyProvider");
    let mut previous_mapped_state: Option<UsbGadgetState> = None;
    loop {
        match provider.watch_device_state().await {
            Ok(Ok(update)) => {
                let state = update.state.unwrap_or_else(DeviceState::unknown);

                // Map the incoming device state onto the new UsbGadgetState.
                let mapped = UsbGadgetState::map_from_device_state(state, previous_mapped_state);

                if previous_mapped_state != mapped {
                    if let Some(val) = mapped {
                        previous_mapped_state = Some(val);
                        shared_state.store(val as u8, Ordering::Relaxed);
                        if let Err(e) =
                            dispatch_usb_state_change(&kernel, &device, val.to_fs_str().to_owned())
                                .await
                        {
                            log_error!("Failed to dispatch USB state change: {:?}", e);
                        }
                    }
                }
            }
            Ok(Err(err)) => {
                log_error!("USB PolicyProvider returned error: {:?}", err);
                break;
            }
            Err(e) => {
                log_error!("USB PolicyProvider watch failed: {:?}", e);
                break;
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use starnix_core::testing::spawn_kernel_and_run;
    use starnix_rcu::RcuReadScope;

    #[::fuchsia::test]
    async fn test_usb_gadget_state_map_from_device_state() {
        assert_eq!(
            UsbGadgetState::map_from_device_state(DeviceState::NotAttached, None),
            Some(UsbGadgetState::Disconnected)
        );
        assert_eq!(
            UsbGadgetState::map_from_device_state(DeviceState::Configured, None),
            Some(UsbGadgetState::Configured)
        );
        assert_eq!(
            UsbGadgetState::map_from_device_state(DeviceState::Attached, None),
            Some(UsbGadgetState::Connected)
        );
        assert_eq!(
            UsbGadgetState::map_from_device_state(DeviceState::Powered, None),
            Some(UsbGadgetState::Connected)
        );
        assert_eq!(
            UsbGadgetState::map_from_device_state(DeviceState::Default, None),
            Some(UsbGadgetState::Connected)
        );
        assert_eq!(
            UsbGadgetState::map_from_device_state(DeviceState::Address, None),
            Some(UsbGadgetState::Connected)
        );
        assert_eq!(
            UsbGadgetState::map_from_device_state(
                DeviceState::Suspended,
                Some(UsbGadgetState::Configured)
            ),
            Some(UsbGadgetState::Configured)
        );
        assert_eq!(UsbGadgetState::map_from_device_state(DeviceState::Suspended, None), None);
        assert_eq!(UsbGadgetState::map_from_device_state(DeviceState::unknown(), None), None);
        assert_eq!(
            UsbGadgetState::map_from_device_state(
                DeviceState::unknown(),
                Some(UsbGadgetState::Configured)
            ),
            Some(UsbGadgetState::Configured)
        );
    }

    #[::fuchsia::test]
    async fn test_usb_sysfs_state_reads() {
        spawn_kernel_and_run(async |_locked, current_task| {
            let shared_state = Arc::new(AtomicU8::new(UsbGadgetState::Disconnected as u8));

            shared_state.store(UsbGadgetState::Configured as u8, Ordering::Relaxed);

            let sysfs_file = UsbStateSysfsFile { state: shared_state };
            let content = sysfs_file.read(current_task).expect("read failed");
            assert_eq!(content.as_ref(), b"CONFIGURED\n");
        })
        .await;
    }

    #[::fuchsia::test]
    async fn test_usb_device_state_to_fs_str() {
        assert_eq!(UsbGadgetState::Disconnected.to_fs_str(), b"DISCONNECTED");
        assert_eq!(UsbGadgetState::Configured.to_fs_str(), b"CONFIGURED");
        assert_eq!(UsbGadgetState::Connected.to_fs_str(), b"CONNECTED");
        assert_eq!(UsbGadgetState::Unknown.to_fs_str(), b"UNKNOWN");
    }

    #[::fuchsia::test]
    async fn test_usb_device_state_from_u8() {
        assert_eq!(UsbGadgetState::from(0), UsbGadgetState::Disconnected);
        assert_eq!(UsbGadgetState::from(1), UsbGadgetState::Configured);
        assert_eq!(UsbGadgetState::from(2), UsbGadgetState::Connected);
        assert_eq!(UsbGadgetState::from(255), UsbGadgetState::Unknown);
    }

    #[::fuchsia::test]
    async fn test_usb_device_init_sysfs() {
        spawn_kernel_and_run(async |locked, current_task| {
            let device = usb_device_init(locked, current_task).expect("usb_device_init failed");

            assert_eq!(device.name.as_slice(), b"android0");
            let metadata = device.metadata.as_ref().expect("metadata not found");
            assert_eq!(metadata.devname.as_slice(), b"android0");
        })
        .await;
    }

    #[::fuchsia::test]
    async fn test_usb_device_metadata_property_injection() {
        spawn_kernel_and_run(async |locked, current_task| {
            let device = usb_device_init(locked, current_task).expect("usb_device_init failed");

            let kernel = current_task.kernel();

            // Send the state change and wait for the background task to execute.
            dispatch_usb_state_change(
                kernel,
                &device,
                UsbGadgetState::Connected.to_fs_str().to_owned(),
            )
            .await
            .unwrap();

            let metadata = device.metadata.as_ref().expect("metadata not found");
            let scope = RcuReadScope::new();
            let value = metadata
                .properties
                .get(&scope, FsStr::new(b"USB_STATE"))
                .expect("property not found");
            assert_eq!(value.as_slice(), b"CONNECTED");
        })
        .await;
    }
}
