// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use anyhow::anyhow;
use fs_err::File;
use std::ffi::OsStr;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Write;
use std::path::Path;

const AUTOGEN_COMMENT: &str = "# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html";

pub fn check_autogen_comment(path: &Path, fix: bool) -> anyhow::Result<()> {
    if path.file_name() != Some(OsStr::new("Cargo.toml")) {
        return Ok(());
    }

    let f = BufReader::new(File::open(path)?);
    let mut found = false;
    for line in f.lines() {
        let line = line?;
        if line.trim() == AUTOGEN_COMMENT {
            found = true;
            break;
        }
    }

    if found && fix {
        let path_fix = &{
            let mut p = path.to_path_buf();
            let ok = p.set_extension("toml.fix");
            assert!(ok);
            p
        };

        let f = BufReader::new(File::open(path)?);
        let mut f_fixed = File::create(path_fix)?;

        let mut just_fixed = false;
        for line in f.lines() {
            let line = line?;

            if line.trim() == AUTOGEN_COMMENT {
                just_fixed = true;
                continue;
            }

            // also remove the extra newline that comes after the comment
            if just_fixed {
                if line.trim().is_empty() {
                    just_fixed = false;
                    continue;
                }
            }

            just_fixed = false;
            writeln!(f_fixed, "{}", line)?;
        }

        // swap the file with the newly fixed file
        fs_err::rename(path_fix, path)?;
    }

    if found {
        let msg = "autogenerated \"keys and their definitions\" comment";
        if fix {
            log::info!("fixed {} in {}", msg, path.display());
            Ok(())
        } else {
            Err(anyhow!("{} in {}", msg, path.display()))
        }
    } else {
        Ok(())
    }
}
