/*
 * libgit2 "diff" example - shows how to use the diff API
 *
 * Written by the libgit2 contributors
 *
 * To the extent possible under law, the author(s) have dedicated all copyright
 * and related and neighboring rights to this software to the public domain
 * worldwide. This software is distributed without any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication along
 * with this software. If not, see
 * <http://creativecommons.org/publicdomain/zero/1.0/>.
 */

#![deny(warnings)]

use git2::{Blob, Diff, DiffOptions, Error, Object, ObjectType, Oid, Repository};
use git2::{DiffDelta, DiffFindOptions, DiffFormat, DiffHunk, DiffLine};
use std::str;
use structopt::StructOpt;

#[derive(StructOpt)]
#[allow(non_snake_case)]
struct Args {
    #[structopt(name = "from_oid")]
    arg_from_oid: Option<String>,
    #[structopt(name = "to_oid")]
    arg_to_oid: Option<String>,
    #[structopt(name = "blobs", long)]
    /// treat from_oid and to_oid as blob ids
    flag_blobs: bool,
    #[structopt(name = "patch", short, long)]
    /// show output in patch format
    flag_patch: bool,
    #[structopt(name = "cached", long)]
    /// use staged changes as diff
    flag_cached: bool,
    #[structopt(name = "nocached", long)]
    /// do not use staged changes
    flag_nocached: bool,
    #[structopt(name = "name-only", long)]
    /// show only names of changed files
    flag_name_only: bool,
    #[structopt(name = "name-status", long)]
    /// show only names and status changes
    flag_name_status: bool,
    #[structopt(name = "raw", long)]
    /// generate the raw format
    flag_raw: bool,
    #[structopt(name = "format", long)]
    /// specify format for stat summary
    flag_format: Option<String>,
    #[structopt(name = "color", long)]
    /// use color output
    flag_color: bool,
    #[structopt(name = "no-color", long)]
    /// never use color output
    flag_no_color: bool,
    #[structopt(short = "R")]
    /// swap two inputs
    flag_R: bool,
    #[structopt(name = "text", short = "a", long)]
    /// treat all files as text
    flag_text: bool,
    #[structopt(name = "ignore-space-at-eol", long)]
    /// ignore changes in whitespace at EOL
    flag_ignore_space_at_eol: bool,
    #[structopt(name = "ignore-space-change", short = "b", long)]
    /// ignore changes in amount of whitespace
    flag_ignore_space_change: bool,
    #[structopt(name = "ignore-all-space", short = "w", long)]
    /// ignore whitespace when comparing lines
    flag_ignore_all_space: bool,
    #[structopt(name = "ignored", long)]
    /// show untracked files
    flag_ignored: bool,
    #[structopt(name = "untracked", long)]
    /// generate diff using the patience algorithm
    flag_untracked: bool,
    #[structopt(name = "patience", long)]
    /// show ignored files as well
    flag_patience: bool,
    #[structopt(name = "minimal", long)]
    /// spend extra time to find smallest diff
    flag_minimal: bool,
    #[structopt(name = "stat", long)]
    /// generate a diffstat
    flag_stat: bool,
    #[structopt(name = "numstat", long)]
    /// similar to --stat, but more machine friendly
    flag_numstat: bool,
    #[structopt(name = "shortstat", long)]
    /// only output last line of --stat
    flag_shortstat: bool,
    #[structopt(name = "summary", long)]
    /// output condensed summary of header info
    flag_summary: bool,
    #[structopt(name = "find-renames", short = "M", long)]
    /// set threshold for findind renames (default 50)
    flag_find_renames: Option<u16>,
    #[structopt(name = "find-copies", short = "C", long)]
    /// set threshold for finding copies (default 50)
    flag_find_copies: Option<u16>,
    #[structopt(name = "find-copies-harder", long)]
    /// inspect unmodified files for sources of copies
    flag_find_copies_harder: bool,
    #[structopt(name = "break_rewrites", short = "B", long)]
    /// break complete rewrite changes into pairs
    flag_break_rewrites: bool,
    #[structopt(name = "unified", short = "U", long)]
    /// lints of context to show
    flag_unified: Option<u32>,
    #[structopt(name = "inter-hunk-context", long)]
    /// maximum lines of change between hunks
    flag_inter_hunk_context: Option<u32>,
    #[structopt(name = "abbrev", long)]
    /// length to abbreviate commits to
    flag_abbrev: Option<u16>,
    #[structopt(name = "src-prefix", long)]
    /// show given source prefix instead of 'a/'
    flag_src_prefix: Option<String>,
    #[structopt(name = "dst-prefix", long)]
    /// show given destinction prefix instead of 'b/'
    flag_dst_prefix: Option<String>,
    #[structopt(name = "path", long = "git-dir")]
    /// path to git repository to use
    flag_git_dir: Option<String>,
}

const RESET: &str = "\u{1b}[m";
const BOLD: &str = "\u{1b}[1m";
const RED: &str = "\u{1b}[31m";
const GREEN: &str = "\u{1b}[32m";
const CYAN: &str = "\u{1b}[36m";

#[derive(PartialEq, Eq, Copy, Clone)]
enum Cache {
    Normal,
    Only,
    None,
}

fn line_color(line: &DiffLine) -> Option<&'static str> {
    match line.origin() {
        '+' => Some(GREEN),
        '-' => Some(RED),
        '>' => Some(GREEN),
        '<' => Some(RED),
        'F' => Some(BOLD),
        'H' => Some(CYAN),
        _ => None,
    }
}

fn print_diff_line(
    _delta: DiffDelta,
    _hunk: Option<DiffHunk>,
    line: DiffLine,
    args: &Args,
) -> bool {
    if args.color() {
        print!("{}", RESET);
        if let Some(color) = line_color(&line) {
            print!("{}", color);
        }
    }
    match line.origin() {
        '+' | '-' | ' ' => print!("{}", line.origin()),
        _ => {}
    }
    print!("{}", str::from_utf8(line.content()).unwrap());
    true
}

fn run(args: &Args) -> Result<(), Error> {
    let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or(".");
    let repo = Repository::open(path)?;

    // Prepare our diff options based on the arguments given
    let mut opts = DiffOptions::new();
    opts.reverse(args.flag_R)
        .force_text(args.flag_text)
        .ignore_whitespace_eol(args.flag_ignore_space_at_eol)
        .ignore_whitespace_change(args.flag_ignore_space_change)
        .ignore_whitespace(args.flag_ignore_all_space)
        .include_ignored(args.flag_ignored)
        .include_untracked(args.flag_untracked)
        .patience(args.flag_patience)
        .minimal(args.flag_minimal);
    if let Some(amt) = args.flag_unified {
        opts.context_lines(amt);
    }
    if let Some(amt) = args.flag_inter_hunk_context {
        opts.interhunk_lines(amt);
    }
    if let Some(amt) = args.flag_abbrev {
        opts.id_abbrev(amt);
    }
    if let Some(ref s) = args.flag_src_prefix {
        opts.old_prefix(&s);
    }
    if let Some(ref s) = args.flag_dst_prefix {
        opts.new_prefix(&s);
    }
    if let Some("diff-index") = args.flag_format.as_ref().map(|s| &s[..]) {
        opts.id_abbrev(40);
    }

    if args.flag_blobs {
        let b1 = resolve_blob(&repo, args.arg_from_oid.as_ref())?;
        let b2 = resolve_blob(&repo, args.arg_to_oid.as_ref())?;
        repo.diff_blobs(
            b1.as_ref(),
            None,
            b2.as_ref(),
            None,
            Some(&mut opts),
            None,
            None,
            None,
            Some(&mut |d, h, l| print_diff_line(d, h, l, args)),
        )?;
        if args.color() {
            print!("{}", RESET);
        }
        return Ok(());
    }

    // Prepare the diff to inspect
    let t1 = tree_to_treeish(&repo, args.arg_from_oid.as_ref())?;
    let t2 = tree_to_treeish(&repo, args.arg_to_oid.as_ref())?;
    let head = tree_to_treeish(&repo, Some(&"HEAD".to_string()))?.unwrap();
    let mut diff = match (t1, t2, args.cache()) {
        (Some(t1), Some(t2), _) => {
            repo.diff_tree_to_tree(t1.as_tree(), t2.as_tree(), Some(&mut opts))?
        }
        (t1, None, Cache::None) => {
            let t1 = t1.unwrap_or(head);
            repo.diff_tree_to_workdir(t1.as_tree(), Some(&mut opts))?
        }
        (t1, None, Cache::Only) => {
            let t1 = t1.unwrap_or(head);
            repo.diff_tree_to_index(t1.as_tree(), None, Some(&mut opts))?
        }
        (Some(t1), None, _) => {
            repo.diff_tree_to_workdir_with_index(t1.as_tree(), Some(&mut opts))?
        }
        (None, None, _) => repo.diff_index_to_workdir(None, Some(&mut opts))?,
        (None, Some(_), _) => unreachable!(),
    };

    // Apply rename and copy detection if requested
    if args.flag_break_rewrites
        || args.flag_find_copies_harder
        || args.flag_find_renames.is_some()
        || args.flag_find_copies.is_some()
    {
        let mut opts = DiffFindOptions::new();
        if let Some(t) = args.flag_find_renames {
            opts.rename_threshold(t);
            opts.renames(true);
        }
        if let Some(t) = args.flag_find_copies {
            opts.copy_threshold(t);
            opts.copies(true);
        }
        opts.copies_from_unmodified(args.flag_find_copies_harder)
            .rewrites(args.flag_break_rewrites);
        diff.find_similar(Some(&mut opts))?;
    }

    // Generate simple output
    let stats = args.flag_stat | args.flag_numstat | args.flag_shortstat | args.flag_summary;
    if stats {
        print_stats(&diff, args)?;
    }
    if args.flag_patch || !stats {
        diff.print(args.diff_format(), |d, h, l| print_diff_line(d, h, l, args))?;
        if args.color() {
            print!("{}", RESET);
        }
    }

    Ok(())
}

fn print_stats(diff: &Diff, args: &Args) -> Result<(), Error> {
    let stats = diff.stats()?;
    let mut format = git2::DiffStatsFormat::NONE;
    if args.flag_stat {
        format |= git2::DiffStatsFormat::FULL;
    }
    if args.flag_shortstat {
        format |= git2::DiffStatsFormat::SHORT;
    }
    if args.flag_numstat {
        format |= git2::DiffStatsFormat::NUMBER;
    }
    if args.flag_summary {
        format |= git2::DiffStatsFormat::INCLUDE_SUMMARY;
    }
    let buf = stats.to_buf(format, 80)?;
    print!("{}", str::from_utf8(&*buf).unwrap());
    Ok(())
}

fn tree_to_treeish<'a>(
    repo: &'a Repository,
    arg: Option<&String>,
) -> Result<Option<Object<'a>>, Error> {
    let arg = match arg {
        Some(s) => s,
        None => return Ok(None),
    };
    let obj = repo.revparse_single(arg)?;
    let tree = obj.peel(ObjectType::Tree)?;
    Ok(Some(tree))
}

fn resolve_blob<'a>(repo: &'a Repository, arg: Option<&String>) -> Result<Option<Blob<'a>>, Error> {
    let arg = match arg {
        Some(s) => Oid::from_str(s)?,
        None => return Ok(None),
    };
    repo.find_blob(arg).map(|b| Some(b))
}

impl Args {
    fn cache(&self) -> Cache {
        if self.flag_cached {
            Cache::Only
        } else if self.flag_nocached {
            Cache::None
        } else {
            Cache::Normal
        }
    }
    fn color(&self) -> bool {
        self.flag_color && !self.flag_no_color
    }
    fn diff_format(&self) -> DiffFormat {
        if self.flag_patch {
            DiffFormat::Patch
        } else if self.flag_name_only {
            DiffFormat::NameOnly
        } else if self.flag_name_status {
            DiffFormat::NameStatus
        } else if self.flag_raw {
            DiffFormat::Raw
        } else {
            match self.flag_format.as_ref().map(|s| &s[..]) {
                Some("name") => DiffFormat::NameOnly,
                Some("name-status") => DiffFormat::NameStatus,
                Some("raw") => DiffFormat::Raw,
                Some("diff-index") => DiffFormat::Raw,
                _ => DiffFormat::Patch,
            }
        }
    }
}

fn main() {
    let args = Args::from_args();
    match run(&args) {
        Ok(()) => {}
        Err(e) => println!("error: {}", e),
    }
}
