// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

use teaclave_crypto::TeaclaveFile128Key;

use std::collections::HashMap;
#[cfg(not(feature = "mesalock_sgx"))]
use std::fs::File;
use std::io::{self, BufRead, BufReader, Read, Write};
use std::path::{Path, PathBuf};
use std::prelude::v1::*;
#[cfg(feature = "mesalock_sgx")]
use std::untrusted::fs::File;

use crate::FileAuthTag;
use anyhow::Context;
use protected_fs::ProtectedFile;

#[derive(Clone, Debug, Default)]
pub struct StagedFileInfo {
    pub path: PathBuf,
    pub crypto_info: TeaclaveFile128Key,
    pub cmac: FileAuthTag,
}

impl StagedFileInfo {
    pub fn new(
        path: impl AsRef<Path>,
        crypto_info: TeaclaveFile128Key,
        cmac: impl Into<FileAuthTag>,
    ) -> Self {
        StagedFileInfo {
            path: path.as_ref().into(),
            crypto_info,
            cmac: cmac.into(),
        }
    }

    pub fn create_readable_io(&self) -> anyhow::Result<Box<dyn io::Read>> {
        let f = ProtectedFile::open_ex(&self.path, &self.crypto_info.key)?;
        let tag = f
            .current_meta_gmac()
            .context("Failed to get gmac from protected file")?;
        anyhow::ensure!(self.cmac == tag, "Corrupted input file: {:?}", self.path);
        Ok(Box::new(f))
    }

    pub fn create_writable_io(&self) -> anyhow::Result<Box<dyn io::Write>> {
        let f = ProtectedFile::create_ex(&self.path, &self.crypto_info.key)?;
        Ok(Box::new(f))
    }

    pub fn convert_file(
        &self,
        dst: impl AsRef<Path>,
        crypto: TeaclaveFile128Key,
    ) -> anyhow::Result<StagedFileInfo> {
        let src_file = ProtectedFile::open_ex(&self.path, &self.crypto_info.key)
            .context("Convert: failed to open src file")?;
        let mut dest_file = ProtectedFile::create_ex(dst.as_ref(), &crypto.key)
            .context("Convert: failed to create dst file")?;

        let mut reader = BufReader::with_capacity(4096, src_file);
        loop {
            let buffer = reader.fill_buf()?;
            let rd_len = buffer.len();
            if rd_len == 0 {
                break;
            }
            let wt_len = dest_file.write(buffer)?;
            anyhow::ensure!(
                rd_len == wt_len,
                "Cannot fully write to dest file: Rd({:?}) != Wt({:?})",
                rd_len,
                wt_len
            );
            reader.consume(rd_len);
        }
        dest_file
            .flush()
            .context("Convert: dst_file flush failed")?;
        let tag = dest_file
            .current_meta_gmac()
            .context("Convert: cannot get dst_file gmac")?;
        Ok(StagedFileInfo::new(dst, crypto, tag))
    }

    #[cfg(test_mode)]
    pub fn create_with_plaintext_file(path: impl AsRef<Path>) -> anyhow::Result<StagedFileInfo> {
        let bytes = read_all_bytes(path.as_ref())?;
        let dst = path.as_ref().with_extension("test_enc");
        Self::create_with_bytes(dst, &bytes)
    }

    #[cfg(test_mode)]
    pub fn get_plaintext(&self) -> anyhow::Result<Vec<u8>> {
        let mut content = Vec::new();
        let mut f = ProtectedFile::open_ex(&self.path, &self.crypto_info.key)?;
        f.read_to_end(&mut content)?;
        Ok(content)
    }

    pub fn create_with_bytes(
        path: impl AsRef<Path>,
        bytes: &[u8],
    ) -> anyhow::Result<StagedFileInfo> {
        let crypto = TeaclaveFile128Key::random();
        let mut f = ProtectedFile::create_ex(&path, &crypto.key)?;
        f.write_all(bytes)?;
        f.flush()?;
        let tag = f.current_meta_gmac()?;
        Ok(Self::new(path.as_ref(), crypto, tag))
    }
}

pub fn read_all_bytes(path: impl AsRef<Path>) -> anyhow::Result<Vec<u8>> {
    let mut content = Vec::new();
    let mut file = File::open(path)?;
    file.read_to_end(&mut content)?;
    Ok(content)
}

#[derive(Debug, Default, Clone)]
pub struct StagedFiles {
    entries: HashMap<String, StagedFileInfo>,
}

impl StagedFiles {
    pub fn new(entries: HashMap<String, StagedFileInfo>) -> Self {
        StagedFiles { entries }
    }

    pub fn get(&self, key: &str) -> Option<&StagedFileInfo> {
        self.entries.get(key)
    }

    pub fn len(&self) -> usize {
        self.entries.len()
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

impl std::iter::FromIterator<(String, StagedFileInfo)> for StagedFiles {
    fn from_iter<T: IntoIterator<Item = (String, StagedFileInfo)>>(iter: T) -> Self {
        StagedFiles {
            entries: HashMap::from_iter(iter),
        }
    }
}
