// Copyright 2020 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.

use {
    crate::{PkgFs, TestEnv},
    anyhow::Error,
    fidl::endpoints::ClientEnd,
    fidl_fuchsia_io::{DirectoryMarker, DirectoryProxy},
    fidl_fuchsia_paver as paver,
    fidl_fuchsia_space::{ErrorCode, ManagerMarker},
    fuchsia_async::{self as fasync, OnSignals},
    fuchsia_merkle::Hash,
    fuchsia_pkg::{MetaContents, PackagePath},
    fuchsia_zircon as zx,
    maplit::{btreemap, hashmap},
    matches::assert_matches,
    mock_paver::{hooks as mphooks, MockPaverServiceBuilder, PaverEvent},
    std::{
        fs::{create_dir, create_dir_all, File},
        io::Write as _,
        path::PathBuf,
    },
    system_image::StaticPackages,
    tempfile::TempDir,
};

struct TempDirPkgFs {
    root: TempDir,
}

impl TempDirPkgFs {
    fn new() -> Self {
        let system_image_hash: Hash =
            "0000000000000000000000000000000000000000000000000000000000000000".parse().unwrap();
        let fake_package_hash: Hash =
            "1111111111111111111111111111111111111111111111111111111111111111".parse().unwrap();
        let static_packages = StaticPackages::from_entries(vec![(
            PackagePath::from_name_and_variant("fake-package", "0").unwrap(),
            fake_package_hash,
        )]);
        let versions_contents = hashmap! {
            system_image_hash.clone() => MetaContents::from_map(
                btreemap! {
                    "some-blob".to_string() =>
                        "2222222222222222222222222222222222222222222222222222222222222222".parse().unwrap()
                }
            ).unwrap(),
            fake_package_hash.clone() => MetaContents::from_map(
                btreemap! {
                    "other-blob".to_string() =>
                        "3333333333333333333333333333333333333333333333333333333333333333".parse().unwrap()
                }
            ).unwrap()
        };
        let root = tempfile::tempdir().unwrap();

        create_dir(root.path().join("ctl")).unwrap();

        create_dir(root.path().join("system")).unwrap();
        File::create(root.path().join("system/meta"))
            .unwrap()
            .write_all(system_image_hash.to_string().as_bytes())
            .unwrap();
        create_dir(root.path().join("system/data")).unwrap();
        static_packages
            .serialize(File::create(root.path().join("system/data/static_packages")).unwrap())
            .unwrap();

        create_dir(root.path().join("versions")).unwrap();
        for (hash, contents) in versions_contents.iter() {
            let meta_path = root.path().join(format!("versions/{}/meta", hash));
            create_dir_all(&meta_path).unwrap();
            contents.serialize(&mut File::create(meta_path.join("contents")).unwrap()).unwrap();
        }

        create_dir(root.path().join("blobfs")).unwrap();

        Self { root }
    }

    fn garbage_path(&self) -> PathBuf {
        self.root.path().join("ctl/garbage")
    }

    fn create_garbage(&self) {
        File::create(self.garbage_path()).unwrap();
    }

    fn garbage_exists(&self) -> bool {
        self.garbage_path().exists()
    }
}

impl PkgFs for TempDirPkgFs {
    fn root_dir_handle(&self) -> Result<ClientEnd<DirectoryMarker>, Error> {
        Ok(fdio::transfer_fd(File::open(self.root.path()).unwrap()).unwrap().into())
    }

    fn blobfs_root_proxy(&self) -> Result<DirectoryProxy, Error> {
        let dir_handle: ClientEnd<DirectoryMarker> =
            fdio::transfer_fd(File::open(self.root.path().join("blobfs")).unwrap()).unwrap().into();
        Ok(dir_handle.into_proxy().unwrap())
    }
}

#[fasync::run_singlethreaded(test)]
async fn gc_garbage_file_deleted() {
    let env = TestEnv::builder().pkgfs(TempDirPkgFs::new()).build().await;
    env.pkgfs.create_garbage();

    let res = env.proxies.space_manager.gc().await;

    assert_matches!(res, Ok(Ok(())));
    assert!(!env.pkgfs.garbage_exists());
}

#[fasync::run_singlethreaded(test)]
async fn gc_twice_same_client() {
    let env = TestEnv::builder().pkgfs(TempDirPkgFs::new()).build().await;
    env.pkgfs.create_garbage();

    let res = env.proxies.space_manager.gc().await;

    assert_matches!(res, Ok(Ok(())));
    assert!(!env.pkgfs.garbage_exists());

    env.pkgfs.create_garbage();

    let res = env.proxies.space_manager.gc().await;

    assert_matches!(res, Ok(Ok(())));
    assert!(!env.pkgfs.garbage_exists());
}

#[fasync::run_singlethreaded(test)]
async fn gc_twice_different_clients() {
    let env = TestEnv::builder().pkgfs(TempDirPkgFs::new()).build().await;
    env.pkgfs.create_garbage();

    let res = env.proxies.space_manager.gc().await;

    assert_matches!(res, Ok(Ok(())));
    assert!(!env.pkgfs.garbage_exists());

    env.pkgfs.create_garbage();
    let second_connection = env
        .apps
        .realm_instance
        .root
        .connect_to_protocol_at_exposed_dir::<ManagerMarker>()
        .expect("connect to space manager");
    let res = second_connection.gc().await;

    assert_matches!(res, Ok(Ok(())));
    assert!(!env.pkgfs.garbage_exists());
}

#[fasync::run_singlethreaded(test)]
async fn gc_error_missing_garbage_file() {
    let env = TestEnv::builder().pkgfs(TempDirPkgFs::new()).build().await;

    let res = env.proxies.space_manager.gc().await;

    assert_matches!(res, Ok(Err(ErrorCode::Internal)));
}

#[fasync::run_singlethreaded(test)]
async fn gc_error_pending_commit() {
    let (throttle_hook, throttler) = mphooks::throttle();

    let env = TestEnv::builder()
        .pkgfs(TempDirPkgFs::new())
        .paver_service_builder(
            MockPaverServiceBuilder::new()
                .insert_hook(throttle_hook)
                .insert_hook(mphooks::config_status(|_| Ok(paver::ConfigurationStatus::Pending))),
        )
        .build()
        .await;
    env.pkgfs.create_garbage();

    // Allow the paver to emit enough events to unblock the CommitStatusProvider FIDL server, but
    // few enough to guarantee the commit is still pending.
    let () = throttler.emit_next_paver_events(&[
        PaverEvent::QueryCurrentConfiguration,
        PaverEvent::QueryConfigurationStatus { configuration: paver::Configuration::A },
    ]);
    assert_matches!(env.proxies.space_manager.gc().await, Ok(Err(ErrorCode::PendingCommit)));

    // When the commit completes, GC should unblock as well.
    let () = throttler.emit_next_paver_events(&[
        PaverEvent::SetConfigurationHealthy { configuration: paver::Configuration::A },
        PaverEvent::SetConfigurationUnbootable { configuration: paver::Configuration::B },
        PaverEvent::BootManagerFlush,
    ]);
    let event_pair =
        env.proxies.commit_status_provider.is_current_system_committed().await.unwrap();
    assert_eq!(OnSignals::new(&event_pair, zx::Signals::USER_0).await, Ok(zx::Signals::USER_0));
    assert_matches!(env.proxies.space_manager.gc().await, Ok(Ok(())));
}
