// 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.
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
    }

    /// 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)
    }
}

#[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);
    }
}
