// Copyright 2022 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 {
    anyhow::{bail, Error},
    chrono::{TimeZone, Utc},
    fxfs::{
        crypt::Crypt,
        filesystem::OpenFxFilesystem,
        fsck,
        object_handle::{GetProperties, ObjectHandle, ReadObjectHandle, WriteObjectHandle},
        object_store::{
            directory::replace_child,
            transaction::{Options, TransactionHandler},
            volume::root_volume,
            Directory, HandleOptions, ObjectDescriptor, ObjectStore,
        },
    },
    std::{io::Write, path::Path, sync::Arc},
};

const DEFAULT_VOLUME: &str = "default";

pub async fn print_ls(dir: &Directory<ObjectStore>) -> Result<(), Error> {
    const DATE_FMT: &str = "%b %d %Y %T+00";
    let layer_set = dir.store().tree().layer_set();
    let mut merger = layer_set.merger();
    let mut iter = dir.iter(&mut merger).await?;
    while let Some((name, object_id, descriptor)) = iter.get() {
        match descriptor {
            ObjectDescriptor::File => {
                let handle = ObjectStore::open_object(
                    dir.owner(),
                    object_id,
                    HandleOptions::default(),
                    None,
                )
                .await?;
                let properties = handle.get_properties().await?;
                let size = properties.data_attribute_size;
                let mtime = Utc.timestamp(
                    properties.modification_time.secs as i64,
                    properties.modification_time.nanos,
                );
                println!(
                    "-rwx------    1 nobody   nogroup    {:>8} {:>12} {}",
                    size,
                    mtime.format(DATE_FMT),
                    name
                );
            }
            ObjectDescriptor::Directory => {
                let mtime = Utc.timestamp(0, 0);
                println!(
                    "d---------    1 nobody   nogroup           0 {:>12} {}",
                    mtime.format(DATE_FMT),
                    name
                );
            }
            ObjectDescriptor::Volume => unimplemented!(),
        }
        iter.advance().await?;
    }
    Ok(())
}

/// Opens a volume on a device and returns a Directory to it's root.
pub async fn open_volume(
    fs: &OpenFxFilesystem,
    crypt: Arc<dyn Crypt>,
) -> Result<Arc<ObjectStore>, Error> {
    let root_volume = root_volume(fs).await?;
    root_volume.volume(DEFAULT_VOLUME, Some(crypt)).await.map(|v| v.into())
}

/// Walks a directory path from a given root.
pub async fn walk_dir(
    vol: &Arc<ObjectStore>,
    path: &Path,
) -> Result<Directory<ObjectStore>, Error> {
    let mut dir: Directory<ObjectStore> =
        Directory::open(vol, vol.root_directory_object_id()).await?;
    for path in path.to_str().unwrap().split('/') {
        if path.len() == 0 {
            continue;
        }
        if let Some((object_id, descriptor)) = dir.lookup(&path).await? {
            if descriptor != ObjectDescriptor::Directory {
                bail!("Not a directory: {}", path);
            }
            dir = Directory::open(&dir.owner(), object_id).await?;
        } else {
            bail!("Not found: {}", path);
        }
    }
    Ok(dir)
}

pub async fn unlink(
    fs: &OpenFxFilesystem,
    vol: &Arc<ObjectStore>,
    path: &Path,
) -> Result<(), Error> {
    let dir = walk_dir(vol, path.parent().unwrap()).await?;
    let mut transaction = (*fs).clone().new_transaction(&[], Options::default()).await?;
    replace_child(&mut transaction, None, (&dir, path.file_name().unwrap().to_str().unwrap()))
        .await?;
    transaction.commit().await?;
    Ok(())
}

// Used to fsck after mutating operations.
pub async fn fsck(
    fs: &OpenFxFilesystem,
    crypt: Arc<dyn Crypt>,
    verbose: bool,
) -> Result<(), Error> {
    // Re-open the filesystem to ensure it's locked.
    let options = fsck::FsckOptions {
        fail_on_warning: false,
        halt_on_error: false,
        do_slow_passes: true,
        on_error: |err| eprintln!("{:?}", err.to_string()),
        verbose,
    };
    fsck::fsck_with_options(fs, Some(crypt), options).await
}

/// Read a file's contents into a Vec and return it.
pub async fn get(vol: &Arc<ObjectStore>, src: &Path) -> Result<Vec<u8>, Error> {
    let dir = walk_dir(vol, src.parent().unwrap()).await?;
    if let Some((object_id, descriptor)) =
        dir.lookup(&src.file_name().unwrap().to_str().unwrap()).await?
    {
        if descriptor != ObjectDescriptor::File {
            bail!("Expected File. Found {:?}", descriptor);
        }
        let handle =
            ObjectStore::open_object(dir.owner(), object_id, HandleOptions::default(), None)
                .await?;
        let mut out: Vec<u8> = Vec::new();
        let mut buf = handle.allocate_buffer(handle.block_size() as usize);
        let mut ofs = 0;
        loop {
            let bytes = handle.read(ofs, buf.as_mut()).await?;
            ofs += bytes as u64;
            out.write_all(&buf.as_ref().as_slice()[..bytes])?;
            if bytes as u64 != handle.block_size() {
                break;
            }
        }
        Ok(out)
    } else {
        bail!("File not found");
    }
}

/// Write the contents of a Vec to a file int he image.
pub async fn put(
    fs: &OpenFxFilesystem,
    vol: &Arc<ObjectStore>,
    dst: &Path,
    data: Vec<u8>,
) -> Result<(), Error> {
    let dir = walk_dir(vol, dst.parent().unwrap()).await?;
    let filename = dst.file_name().unwrap().to_str().unwrap();
    let mut transaction = (*fs).clone().new_transaction(&[], Options::default()).await?;
    if let Some(_) = dir.lookup(filename).await? {
        bail!("{} already exists", filename);
    }
    let handle = dir.create_child_file(&mut transaction, &filename).await?;
    transaction.commit().await?;
    let mut buf = handle.allocate_buffer(data.len());
    buf.as_mut_slice().copy_from_slice(&data);
    handle.write_or_append(Some(0), buf.as_ref()).await?;
    handle.flush().await
}

/// Create a directory.
pub async fn mkdir(
    fs: &OpenFxFilesystem,
    vol: &Arc<ObjectStore>,
    path: &Path,
) -> Result<(), Error> {
    let dir = walk_dir(vol, path.parent().unwrap()).await?;
    let filename = path.file_name().unwrap().to_str().unwrap();
    let mut transaction = (*fs).clone().new_transaction(&[], Options::default()).await?;
    if let Some(_) = dir.lookup(filename).await? {
        bail!("{} already exists", filename);
    }
    dir.create_child_dir(&mut transaction, &filename).await?;
    transaction.commit().await?;
    Ok(())
}
