// Copyright 2022 The Pigweed Authors
//
// 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
//
//     https://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 std::{
    io::Write,
    path::{Path, PathBuf},
};

use serde::{de::DeserializeOwned, Serialize};

use crate::{Error, Result};

/// A file storing data in some serialized format.
#[derive(Debug)]
pub struct File {
    path: PathBuf,
}

impl File {
    pub(super) fn new(path: impl AsRef<Path>) -> Self {
        Self {
            path: path.as_ref().to_path_buf(),
        }
    }

    /// Returns the full path to the file.
    #[must_use]
    pub fn path(&self) -> &Path {
        &self.path
    }

    /// Reads the contents of the file into a string.
    ///
    /// # Errors
    /// Returns an error if the file could not be read.
    pub fn read_text(&self) -> Result<String> {
        std::fs::read_to_string(&self.path).map_err(Error::from)
    }

    /// Writes a string to the file.
    ///
    /// Creates the file if it does not exist, or overwrites existing contents.
    ///
    /// # Errors
    /// Returns an error if the file could not be written.
    pub fn write_text(&self, contents: &str) -> Result<()> {
        std::fs::write(&self.path, contents).map_err(Error::from)
    }

    /// Writes a serializable struct to the file as TOML.
    ///
    /// Creates the file if it does not exist, or overwrites existing contents.
    ///
    /// # Errors
    /// Returns an error if the file could not be written, or the data is not
    /// serializable.
    pub fn serialize_toml<T: Serialize>(&self, value: &T) -> Result<()> {
        let mut f = std::fs::File::create(&self.path).map_err(Error::file(&self.path))?;
        let string = toml::to_string(value)?;
        f.write_all(string.as_bytes())
            .map_err(Error::file(&self.path))?;
        Ok(())
    }

    /// Reads TOML data from the file into a struct.
    ///
    /// # Errors
    /// Returns an error if the file could not be read, or the data is not
    /// valid TOML.
    pub fn deserialize_toml<T: DeserializeOwned>(&self) -> Result<T> {
        let string = std::fs::read_to_string(&self.path).map_err(Error::file(&self.path))?;
        let value = toml::from_str(&string)?;
        Ok(value)
    }

    /// Modifies TOML data stored in the file, writing the updated values back
    /// to disk.
    ///
    /// # Errors
    /// Returns an error if the file could not be accessed, or data could not be
    /// serialized.
    pub fn modify_toml<T: Serialize + DeserializeOwned>(
        &self,
        func: impl FnOnce(&mut T) -> Result<()>,
    ) -> Result<()> {
        let mut value = self.deserialize_toml()?;
        func(&mut value)?;
        self.serialize_toml(&value)
    }

    pub(crate) fn relative_file(&self, path: &Path) -> Self {
        Self::new(
            self.path
                .parent()
                .expect("file must have parent")
                .join(path),
        )
    }
}

#[cfg(test)]
mod tests {
    use serde::Deserialize;

    use super::*;

    #[derive(Debug, Deserialize, PartialEq, Serialize)]
    struct Foo {
        value: String,
        number: u8,
        bar: Option<Bar>,
    }

    #[derive(Debug, Deserialize, PartialEq, Serialize)]
    struct Bar {
        path: PathBuf,
    }

    const SERIALIZED_DATA: &str = r#"value = "encodeme"
number = 199

[bar]
path = "/usr/bin"
"#;

    #[test]
    fn serialize_success() {
        let tmpfile = tempfile::NamedTempFile::new().unwrap();
        let file = File::new(tmpfile.path());

        let foo = Foo {
            value: "encodeme".into(),
            number: 199,
            bar: Some(Bar {
                path: PathBuf::from("/usr/bin"),
            }),
        };

        file.serialize_toml(&foo).unwrap();
        let string = std::fs::read_to_string(file.path()).unwrap();
        assert_eq!(string, SERIALIZED_DATA);
    }

    #[test]
    fn deserialize_success() {
        let tmpfile = tempfile::NamedTempFile::new().unwrap();
        let file = File::new(tmpfile.path());

        std::fs::write(file.path(), SERIALIZED_DATA).unwrap();
        let foo = file.deserialize_toml::<Foo>().unwrap();
        assert_eq!(foo.value, "encodeme".to_string());
        assert_eq!(foo.number, 199);
        assert_eq!(
            foo.bar,
            Some(Bar {
                path: PathBuf::from("/usr/bin")
            })
        );
    }

    #[test]
    fn deserialize_nonexisting_file() {
        let file = File::new("./non-existing-file.xyz");
        let e = file.deserialize_toml::<Foo>().unwrap_err();
        assert!(matches!(e, Error::File(_, _)));
    }

    #[test]
    fn deserialize_invalid_data() {
        let tmpfile = tempfile::NamedTempFile::new().unwrap();
        let file = File::new(tmpfile.path());

        std::fs::write(file.path(), "invalid data").unwrap();
        let e = file.deserialize_toml::<Foo>().unwrap_err();
        assert!(matches!(e, Error::Serialization(_)));
    }

    #[test]
    fn modify_success() {
        let tmpfile = tempfile::NamedTempFile::new().unwrap();
        let file = File::new(tmpfile.path());

        let foo = Foo {
            value: "encodeme".into(),
            number: 199,
            bar: Some(Bar {
                path: PathBuf::from("/usr/bin"),
            }),
        };

        file.serialize_toml(&foo).unwrap();
        file.modify_toml::<Foo>(|value| {
            value.bar = None;
            value.number += 2;
            Ok(())
        })
        .unwrap();

        let result = file.deserialize_toml::<Foo>().unwrap();
        assert_eq!(result.value, foo.value);
        assert_eq!(result.number, 201);
        assert_eq!(result.bar, None);
    }
}
