//
// Copyright (C) 2021 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.
//

//! ProfCollect Binder service implementation.

use anyhow::{anyhow, Context, Error, Result};
use binder::Result as BinderResult;
use binder::Status;
use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProfCollectd::IProfCollectd;
use std::ffi::CString;
use std::fs::{read_dir, read_to_string, remove_file, write};
use std::str::FromStr;
use std::sync::{Mutex, MutexGuard};
use std::time::Duration;

use crate::config::{
    clear_data, Config, CONFIG_FILE, PROFILE_OUTPUT_DIR, REPORT_OUTPUT_DIR, REPORT_RETENTION_SECS,
};
use crate::report::{get_report_ts, pack_report};
use crate::scheduler::Scheduler;

fn err_to_binder_status(msg: Error) -> Status {
    let msg = format!("{:#?}", msg);
    let msg = CString::new(msg).expect("Failed to convert to CString");
    Status::new_service_specific_error(1, Some(&msg))
}

pub struct ProfcollectdBinderService {
    lock: Mutex<Lock>,
}

struct Lock {
    config: Config,
    scheduler: Scheduler,
}

impl binder::Interface for ProfcollectdBinderService {}

impl IProfCollectd for ProfcollectdBinderService {
    fn schedule(&self) -> BinderResult<()> {
        let lock = &mut *self.lock();
        lock.scheduler
            .schedule_periodic(&lock.config)
            .context("Failed to schedule collection.")
            .map_err(err_to_binder_status)
    }
    fn terminate(&self) -> BinderResult<()> {
        self.lock()
            .scheduler
            .terminate_periodic()
            .context("Failed to terminate collection.")
            .map_err(err_to_binder_status)
    }
    fn trace_once(&self, tag: &str) -> BinderResult<()> {
        let lock = &mut *self.lock();
        lock.scheduler
            .one_shot(&lock.config, tag)
            .context("Failed to initiate an one-off trace.")
            .map_err(err_to_binder_status)
    }
    fn process(&self) -> BinderResult<()> {
        let lock = &mut *self.lock();
        lock.scheduler
            .process(&lock.config)
            .context("Failed to process profiles.")
            .map_err(err_to_binder_status)
    }
    fn report(&self) -> BinderResult<String> {
        self.process()?;

        let lock = &mut *self.lock();
        pack_report(&PROFILE_OUTPUT_DIR, &REPORT_OUTPUT_DIR, &lock.config)
            .context("Failed to create profile report.")
            .map_err(err_to_binder_status)
    }
    fn get_supported_provider(&self) -> BinderResult<String> {
        Ok(self.lock().scheduler.get_trace_provider_name().to_string())
    }
}

impl ProfcollectdBinderService {
    pub fn new() -> Result<Self> {
        let new_scheduler = Scheduler::new()?;
        let new_config = Config::from_env()?;

        let config_changed = read_to_string(*CONFIG_FILE)
            .ok()
            .and_then(|s| Config::from_str(&s).ok())
            .filter(|c| new_config == *c)
            .is_none();

        if config_changed {
            log::info!("Config change detected, resetting profcollect.");
            clear_data()?;

            write(*CONFIG_FILE, &new_config.to_string())?;
        }

        // Clear profile reports out of rentention period.
        for report in read_dir(*REPORT_OUTPUT_DIR)? {
            let report = report?.path();
            let report_name = report
                .file_stem()
                .and_then(|f| f.to_str())
                .ok_or_else(|| anyhow!("Malformed path {}", report.display()))?;
            let report_ts = get_report_ts(report_name);
            if let Err(e) = report_ts {
                log::error!(
                    "Cannot decode creation timestamp for report {}, caused by {}, deleting",
                    report_name,
                    e
                );
                remove_file(report)?;
                continue;
            }
            let report_age = report_ts.unwrap().elapsed()?;
            if report_age > Duration::from_secs(REPORT_RETENTION_SECS) {
                log::info!("Report {} past rentention period, deleting", report_name);
                remove_file(report)?;
            }
        }

        Ok(ProfcollectdBinderService {
            lock: Mutex::new(Lock { scheduler: new_scheduler, config: new_config }),
        })
    }

    fn lock(&self) -> MutexGuard<Lock> {
        self.lock.lock().unwrap()
    }
}
