// Copyright 2022, The Android Open Source Project
//
// 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.

//! Functions for creating and collecting atoms.

use crate::aidl::clone_file;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
    DeathReason::DeathReason, IVirtualMachine::IVirtualMachine,
    VirtualMachineAppConfig::VirtualMachineAppConfig, VirtualMachineConfig::VirtualMachineConfig,
};
use android_system_virtualizationservice::binder::{Status, Strong};
use anyhow::{anyhow, Result};
use binder::ThreadState;
use log::{trace, warn};
use microdroid_payload_config::VmPayloadConfig;
use statslog_virtualization_rust::{vm_booted, vm_creation_requested, vm_exited};
use zip::ZipArchive;

fn get_vm_payload_config(config: &VirtualMachineAppConfig) -> Result<VmPayloadConfig> {
    let apk = config.apk.as_ref().ok_or_else(|| anyhow!("APK is none"))?;
    let apk_file = clone_file(apk)?;
    let mut apk_zip = ZipArchive::new(&apk_file)?;
    let config_file = apk_zip.by_name(&config.configPath)?;
    let vm_payload_config: VmPayloadConfig = serde_json::from_reader(config_file)?;
    Ok(vm_payload_config)
}

/// Write the stats of VMCreation to statsd
pub fn write_vm_creation_stats(
    config: &VirtualMachineConfig,
    is_protected: bool,
    ret: &binder::Result<Strong<dyn IVirtualMachine>>,
) {
    let creation_succeeded;
    let binder_exception_code;
    match ret {
        Ok(_) => {
            creation_succeeded = true;
            binder_exception_code = Status::ok().exception_code() as i32;
        }
        Err(ref e) => {
            creation_succeeded = false;
            binder_exception_code = e.exception_code() as i32;
        }
    }

    let vm_identifier;
    let config_type;
    let num_cpus;
    let cpu_affinity;
    let memory_mib;
    let apexes;
    match config {
        VirtualMachineConfig::AppConfig(config) => {
            vm_identifier = &config.name;
            config_type = vm_creation_requested::ConfigType::VirtualMachineAppConfig;
            num_cpus = config.numCpus;
            cpu_affinity = config.cpuAffinity.clone().unwrap_or_default();
            memory_mib = config.memoryMib;

            let vm_payload_config = get_vm_payload_config(config);
            if let Ok(vm_payload_config) = vm_payload_config {
                apexes = vm_payload_config
                    .apexes
                    .iter()
                    .map(|x| x.name.clone())
                    .collect::<Vec<String>>()
                    .join(":");
            } else {
                apexes = "INFO: Can't get VmPayloadConfig".into();
            }
        }
        VirtualMachineConfig::RawConfig(config) => {
            vm_identifier = &config.name;
            config_type = vm_creation_requested::ConfigType::VirtualMachineRawConfig;
            num_cpus = config.numCpus;
            cpu_affinity = config.cpuAffinity.clone().unwrap_or_default();
            memory_mib = config.memoryMib;
            apexes = String::new();
        }
    }

    let vm_creation_requested = vm_creation_requested::VmCreationRequested {
        uid: ThreadState::get_calling_uid() as i32,
        vm_identifier,
        hypervisor: vm_creation_requested::Hypervisor::Pkvm,
        is_protected,
        creation_succeeded,
        binder_exception_code,
        config_type,
        num_cpus,
        cpu_affinity: &cpu_affinity,
        memory_mib,
        apexes: &apexes,
        // TODO(seungjaeyoo) Fill information about task_profile
        // TODO(seungjaeyoo) Fill information about disk_image for raw config
    };

    match vm_creation_requested.stats_write() {
        Err(e) => {
            warn!("statslog_rust failed with error: {}", e);
        }
        Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
    }
}

/// Write the stats of VM boot to statsd
pub fn write_vm_booted_stats(uid: i32, vm_identifier: &String) {
    let vm_booted = vm_booted::VmBooted { uid, vm_identifier };
    match vm_booted.stats_write() {
        Err(e) => {
            warn!("statslog_rust failed with error: {}", e);
        }
        Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
    }
}

/// Write the stats of VM exit to statsd
pub fn write_vm_exited_stats(uid: i32, vm_identifier: &String, reason: DeathReason) {
    let vm_exited = vm_exited::VmExited {
        uid,
        vm_identifier,
        death_reason: match reason {
            DeathReason::INFRASTRUCTURE_ERROR => vm_exited::DeathReason::InfrastructureError,
            DeathReason::KILLED => vm_exited::DeathReason::Killed,
            DeathReason::UNKNOWN => vm_exited::DeathReason::Unknown,
            DeathReason::SHUTDOWN => vm_exited::DeathReason::Shutdown,
            DeathReason::ERROR => vm_exited::DeathReason::Error,
            DeathReason::REBOOT => vm_exited::DeathReason::Reboot,
            DeathReason::CRASH => vm_exited::DeathReason::Crash,
            DeathReason::PVM_FIRMWARE_PUBLIC_KEY_MISMATCH => {
                vm_exited::DeathReason::PvmFirmwarePublicKeyMismatch
            }
            DeathReason::PVM_FIRMWARE_INSTANCE_IMAGE_CHANGED => {
                vm_exited::DeathReason::PvmFirmwareInstanceImageChanged
            }
            DeathReason::BOOTLOADER_PUBLIC_KEY_MISMATCH => {
                vm_exited::DeathReason::BootloaderPublicKeyMismatch
            }
            DeathReason::BOOTLOADER_INSTANCE_IMAGE_CHANGED => {
                vm_exited::DeathReason::BootloaderInstanceImageChanged
            }
            DeathReason::MICRODROID_FAILED_TO_CONNECT_TO_VIRTUALIZATION_SERVICE => {
                vm_exited::DeathReason::MicrodroidFailedToConnectToVirtualizationService
            }
            DeathReason::MICRODROID_PAYLOAD_HAS_CHANGED => {
                vm_exited::DeathReason::MicrodroidPayloadHasChanged
            }
            DeathReason::MICRODROID_PAYLOAD_VERIFICATION_FAILED => {
                vm_exited::DeathReason::MicrodroidPayloadVerificationFailed
            }
            DeathReason::MICRODROID_INVALID_PAYLOAD_CONFIG => {
                vm_exited::DeathReason::MicrodroidInvalidPayloadConfig
            }
            DeathReason::MICRODROID_UNKNOWN_RUNTIME_ERROR => {
                vm_exited::DeathReason::MicrodroidUnknownRuntimeError
            }
            DeathReason::HANGUP => vm_exited::DeathReason::Hangup,
            _ => vm_exited::DeathReason::Unknown,
        },
    };
    match vm_exited.stats_write() {
        Err(e) => {
            warn!("statslog_rust failed with error: {}", e);
        }
        Ok(_) => trace!("statslog_rust succeeded for virtualization service"),
    }
}
