//! Serializable types for the merge domain.

use serde::{Deserialize, Serialize};

use crate::commit::types::CommitOid;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MergeAnalysisResult {
    pub is_none: bool,
    pub is_normal: bool,
    pub is_up_to_date: bool,
    pub is_fast_forward: bool,
    pub is_unborn: bool,
}

impl MergeAnalysisResult {
    pub fn from_git2(analysis: git2::MergeAnalysis) -> Self {
        Self {
            is_none: analysis.is_none(),
            is_normal: analysis.is_normal(),
            is_up_to_date: analysis.is_up_to_date(),
            is_fast_forward: analysis.is_fast_forward(),
            is_unborn: analysis.is_unborn(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MergePreferenceResult {
    pub is_none: bool,
    pub is_no_fast_forward: bool,
    pub is_fastforward_only: bool,
}

impl MergePreferenceResult {
    pub fn from_git2(pref: git2::MergePreference) -> Self {
        Self {
            is_none: pref.is_none(),
            is_no_fast_forward: pref.is_no_fast_forward(),
            is_fastforward_only: pref.is_fastforward_only(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MergeheadInfo {
    pub oid: CommitOid,
}

#[derive(Debug, Clone, Default)]
pub struct MergeOptions {
    find_renames: bool,
    fail_on_conflict: bool,
    skip_reuc: bool,
    no_recursive: bool,
    rename_threshold: u32,
    target_limit: u32,
    recursion_limit: u32,
}

impl MergeOptions {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn find_renames(mut self, find: bool) -> Self {
        self.find_renames = find;
        self
    }

    pub fn fail_on_conflict(mut self, fail: bool) -> Self {
        self.fail_on_conflict = fail;
        self
    }

    pub fn skip_reuc(mut self, skip: bool) -> Self {
        self.skip_reuc = skip;
        self
    }

    pub fn no_recursive(mut self, disable: bool) -> Self {
        self.no_recursive = disable;
        self
    }

    pub fn rename_threshold(mut self, thresh: u32) -> Self {
        self.rename_threshold = thresh;
        self
    }

    pub fn target_limit(mut self, limit: u32) -> Self {
        self.target_limit = limit;
        self
    }

    pub fn recursion_limit(mut self, limit: u32) -> Self {
        self.recursion_limit = limit;
        self
    }

    pub fn to_git2(&self) -> git2::MergeOptions {
        let mut opts = git2::MergeOptions::new();
        opts.find_renames(self.find_renames);
        opts.fail_on_conflict(self.fail_on_conflict);
        opts.skip_reuc(self.skip_reuc);
        opts.no_recursive(self.no_recursive);
        opts.rename_threshold(self.rename_threshold);
        opts.target_limit(self.target_limit);
        opts.recursion_limit(self.recursion_limit);
        opts
    }
}
