//! Parse the command-line arguments for the generate-tests tool.
/*
 * Copyright (c) 2022  Peter Pentchev <roam@ringlet.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

use std::path::Path;

use anyhow::{Context, Result};
use clap::Parser;

use crate::defs::Config;

/// The command-line interface arguments definition.
#[derive(Debug, Parser)]
#[clap(author, version, about)]
struct Cli {
    /// The path to the shell program to generate.
    #[clap(short, long)]
    output_file: String,

    /// Verbose operation: display diagnostic messages.
    #[clap(short)]
    verbose: bool,
}

/// Parse the command-line arguments.
pub fn parse_args() -> Result<Config> {
    let args = Cli::parse();

    let output_file = {
        let opath = Path::new(&args.output_file);
        let oparent = opath.parent().with_context(|| {
            format!(
                "Could not determine the parent directory for the output file {}",
                args.output_file
            )
        })?;
        let oparent_canon = if oparent.as_os_str().is_empty() {
            Path::new(".")
                .canonicalize()
                .context("Could not canonicalize the current working directory")?
        } else {
            oparent.canonicalize().with_context(|| {
                format!(
                    "Could not canonicalize the parent directory {} for the output file {}",
                    oparent.display(),
                    args.output_file,
                )
            })?
        };
        oparent_canon.join(opath.file_name().with_context(|| {
            format!(
                "No filename portion in the output file path {}",
                args.output_file
            )
        })?)
    };

    Ok(Config {
        output_file,
        verbose: args.verbose,
    })
}
