Documentation
/*
==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--

Dia-Args

Copyright (C) 2018-2019, 2021-2025  Anonymous

There are several releases over multiple years,
they are listed as ranges, such as: "2018-2019".

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--
*/

//! # GNU General Public License
//!
//! This module provides some kit for the GNU General Public License.

use {
    std::io::{Error, ErrorKind},
    crate::Result,
};

/// # Finds 'Copyright' text from source (file) and makes short terminal notice
///
/// `command` will be added to the notice.
pub fn make_short_terminal_notice<S0, S1, S2>(src: S0, program_name: S1, command: S2) -> Result<String>
where S0: AsRef<str>, S1: AsRef<str>, S2: AsRef<str> {
    Ok(format!(
        concat!(
            "{program_name}\n\n{copyright_text}\n\n",
            "This program comes with ABSOLUTELY NO WARRANTY.\n",
            "This is free software, and you are welcome to redistribute it\n",
            "under certain conditions; type `{command}` for details.",
        ),
        program_name=program_name.as_ref(),
        copyright_text=find_copyright_text(src.as_ref())?,
        command=command.as_ref(),
    ))
}

/// # Finds 'Copyright' text from source (file)
fn find_copyright_text(src: &str) -> Result<String> {
    const S_COPYRIGHT: &str = "Copyright";

    // For multiple lines:
    //
    // - Find the comment mark at the start of any line.
    // - Parse next lines until one empty line is found.

    let err = || Error::new(ErrorKind::NotFound, __!("Not found"));

    let mut result = None;
    let mut comment_mark = None;
    for line in src.lines().map(|l| l.trim()) {
        match result.as_mut() {
            None => if let Some(index) = line.find(S_COPYRIGHT) {
                let text = &line[index..];
                if text[S_COPYRIGHT.len()..].contains("(C)") {
                    result = Some(text.to_string());
                    comment_mark = (index > 0).then_some(line[..index].trim());
                } else {
                    return Err(err());
                }
            },
            Some(result) => {
                let line = match comment_mark.as_ref() {
                    None => if line.is_empty() { break; } else { line },
                    Some(comment_mark) => if *comment_mark == line {
                        break;
                    } else if line.split_whitespace().next() != Some(comment_mark) {
                        return Err(Error::new(ErrorKind::InvalidData, "Invalid license notices"));
                    } else {
                        line[comment_mark.len()..].trim()
                    },
                };
                result.push('\n');
                result.push_str(line);
            },
        };
    }

    result.ok_or_else(|| err())
}

#[test]
fn tests() -> Result<()> {
    assert_eq!(find_copyright_text(include_str!("../licenses.rs"))?.lines().count(), 1);
    Ok(())
}