#[macro_use]
extern crate log;
#[macro_use]
extern crate anyhow;

mod gui;

use std::path::PathBuf;
use std::process;
use std::str::FromStr;

use anyhow::Result;
use structopt::StructOpt;

use crate::gui::Gui;

fn main() -> Result<()> {
    let opt = Options::from_args();

    stderrlog::new()
        .module(module_path!())
        .verbosity(opt.verbose)
        .init()
        .unwrap();

    let gui = Gui::new()?;
    let capture = gui.capture_entire_screen()?;

    match opt.region {
        Region::Fullscreen => {
            capture.save_to(&opt.outfile)?;
        }
        Region::Selection => {
            if let Some(rectangle) = gui.interactive_select(&capture)? {
                capture.save_cropped_to(&opt.outfile, Some(rectangle))?;
            } else {
                info!("Cancelled by user.");
                process::exit(1);
            }
        }
    }

    Ok(())
}

/// Options for screenshot
#[derive(StructOpt)]
pub struct Options {
    /// The region to select (fullscreen | select)
    #[structopt(parse(try_from_str = Region::from_str))]
    pub region: Region,

    /// The file to save the screenshot to
    #[structopt(short = "o", long = "out", parse(from_os_str))]
    pub outfile: PathBuf,

    /// Verbose mode (-v, -vv, -vvv, etc)
    #[structopt(short = "v", long = "verbose", parse(from_occurrences))]
    verbose: usize,
}

/// A region option
#[allow(missing_docs)]
pub enum Region {
    Fullscreen,
    Selection,
}

impl FromStr for Region {
    type Err = anyhow::Error;
    fn from_str(x: &str) -> Result<Self> {
        match x {
            "fullscreen" => Ok(Region::Fullscreen),
            "select" | "selection" => Ok(Region::Selection),
            _ => bail!("expected {fullscreen|selection}"),
        }
    }
}
