// Copyright (C) 2023 Huawei Device Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Notification bar service module for download task notifications.
//! 
//! This module provides components for managing, configuring, and displaying
//! notifications for download tasks, including database management, configuration
//! handling, notification publishing, and interaction with the system notification
//! infrastructure.

mod database;
mod notification_config;
mod notify_flow;
mod progress_percentage;
mod progress_size;
mod publish;
mod task_handle;
mod typology;

// Re-export for internal use within the service
pub(crate) use notification_config::NotificationConfig;

/// Notification dispatcher for managing and publishing download task notifications.
/// 
/// Provides functionality for displaying, updating, and removing notifications for
/// download tasks and groups of tasks.
pub use publish::NotificationDispatcher;

/// Interval in milliseconds for updating notification progress.
/// 
/// Controls how frequently progress updates are published to the notification bar.
pub(crate) use publish::NOTIFY_PROGRESS_INTERVAL;

// Subscribe function for notification bar events (internal use)
pub(crate) use task_handle::subscribe_notification_bar;
use task_handle::TaskManagerWrapper;

// CXX bridge for FFI between Rust and C++ components
#[cxx::bridge(namespace = "OHOS::Request")]
mod ffi {
    /// Content structure for publishing notifications to the system.
    /// 
    /// Contains all necessary information to display a download task notification,
    /// including title, text, progress, and interaction options.
    #[derive(Eq, PartialEq, Debug)]
    pub(crate) struct NotifyContent {
        title: String,
        text: String,
        want_agent: String,
        request_id: u32,
        uid: u32,
        live_view: bool,
        progress_circle: ProgressCircle,
        x_mark: bool,
    }

    /// Progress circle information for notifications.
    /// 
    /// Represents the progress visualization in notification items, showing
    /// current progress and total size information.
    #[derive(Eq, PartialEq, Debug)]
    struct ProgressCircle {
        open: bool,
        current: u64,
        total: u64,
    }

    // Rust functions exposed to C++
    extern "Rust" {
        /// Wrapper around task management functionality for notification callbacks.
        type TaskManagerWrapper;
        
        /// Attempts to pause the specified download task.
        /// 
        /// # Arguments
        /// 
        /// * `task_id` - The ID of the task to pause
        /// 
        /// # Returns
        /// 
        /// * `true` - If the task was successfully paused
        /// * `false` - If the task pause failed
        fn pause_task(self: &TaskManagerWrapper, task_id: u32) -> bool;
        
        /// Attempts to resume the specified download task.
        /// 
        /// # Arguments
        /// 
        /// * `task_id` - The ID of the task to resume
        /// 
        /// # Returns
        /// 
        /// * `true` - If the task was successfully resumed
        /// * `false` - If the task resume failed
        fn resume_task(self: &TaskManagerWrapper, task_id: u32) -> bool;
        
        /// Attempts to stop the specified download task.
        /// 
        /// # Arguments
        /// 
        /// * `task_id` - The ID of the task to stop
        /// 
        /// # Returns
        /// 
        /// * `true` - If the task was successfully stopped
        /// * `false` - If the task stop failed
        fn stop_task(self: &TaskManagerWrapper, task_id: u32) -> bool;
    }

    // C++ functions exposed to Rust
    unsafe extern "C++" {
        include!("notification_bar.h");

        /// Cancels a system notification with the specified ID.
        /// 
        /// # Arguments
        /// 
        /// * `notificationId` - The ID of the notification to cancel
        /// 
        /// # Returns
        /// 
        /// * `0` - If the notification was successfully cancelled
        /// * Error code - If the cancellation failed
        fn CancelNotification(notificationId: u32) -> i32;
        
        /// Retrieves a string from system resources by name.
        /// 
        /// # Arguments
        /// 
        /// * `name` - The name of the resource string to retrieve
        /// 
        /// # Returns
        /// 
        /// The requested system resource string
        fn GetSystemResourceString(name: &str) -> String;
        
        /// Gets the current system language setting.
        /// 
        /// # Returns
        /// 
        /// The system language code
        fn GetSystemLanguage() -> String;
        
        /// Publishes a notification to the system notification bar.
        /// 
        /// # Arguments
        /// 
        /// * `content` - The notification content to publish
        /// 
        /// # Returns
        /// 
        /// * `0` - If the notification was successfully published
        /// * Error code - If the publication failed
        fn PublishNotification(content: &NotifyContent) -> i32;

        /// Extracts the target bundleName from a serialized want_agent string.
        fn GetWantAgentBundle(want_agent: &str) -> String;
        
        /// Subscribes to notification bar events with the provided task manager.
        /// 
        /// # Arguments
        /// 
        /// * `task_manager` - The task manager wrapper to handle notification interactions
        fn SubscribeNotification(task_manager: Box<TaskManagerWrapper>);
    }
}

/// Validates that a want_agent's target Ability bundle belongs to the caller.
///
/// System API callers (`is_system_api`) are allowed to set any want_agent
/// (they are trusted). Non-system callers must own the target bundle: the
/// Want's bundleName (extracted via `GetWantAgentBundle`) must match the
/// caller's own bundle (`caller_bundle`, already resolved by the caller via
/// `query_calling_bundle` or `TaskConfig.bundle`). This blocks a malicious app
/// from proxying a want_agent that targets another app's Ability through the
/// request service's SA identity at notification-trigger time.
///
/// # Returns
///
/// `true` if the caller may set this want_agent, `false` to reject.
#[cfg(feature = "oh")]
pub(crate) fn validate_want_agent_ownership(
    want_agent: &str,
    caller_bundle: &str,
    is_system_api: bool,
) -> bool {
    if is_system_api {
        debug!("want_agent allowed: system api caller");
        return true;
    }
    if want_agent.is_empty() {
        debug!("want_agent allowed: empty want_agent");
        return true;
    }
    let target_bundle = ffi::GetWantAgentBundle(want_agent);
    debug!(
        "want_agent target: {}, caller: {}",
        target_bundle, caller_bundle
    );
    check_bundle_ownership(&target_bundle, caller_bundle)
}

/// Pure-Rust bundle ownership check (no FFI), extracted for unit testing.
///
/// `target_bundle` empty → allow (no explicit target, implicit start).
/// Otherwise `target_bundle == caller_bundle` → allow, else reject.
#[cfg(feature = "oh")]
fn check_bundle_ownership(target_bundle: &str, caller_bundle: &str) -> bool {
    if target_bundle.is_empty() {
        return true;
    }
    target_bundle == caller_bundle
}

#[cfg(test)]
mod tests {
    include!("../../../tests/ut/service/notification_bar/ut_validate_want_agent.rs");
}