use std::rc::Rc;

use napi::bindgen_prelude::{External, FunctionCallContext};
use napi::threadsafe_function::ThreadsafeFunction;

use crate::vscode_sys;

pub struct Arguments {
    pub repository_uri_ref: vscode_sys::reference::UriRef,
    pub quick_diff_provider_ref: Rc<vscode_sys::reference::QuickDiffProviderRef>,
    pub pijul_label: String,
    pub changes_label: String,
    pub untracked_label: String,
}

pub type Return = (
    vscode_sys::reference::SourceControlRef,
    vscode_sys::reference::SourceControlResourceGroupRef,
    vscode_sys::reference::SourceControlResourceGroupRef,
);

pub type Prototype = ThreadsafeFunction<
    External<Arguments>,
    Return,
    External<Arguments>,
    napi::Status,
    false,
    false,
    0,
>;

pub fn build(env: &napi::Env) -> Result<Prototype, napi::Error> {
    env.create_function_from_closure("initialize_source_control", callback)?
        .build_threadsafe_function()
        .build()
}

fn callback(function_call_context: FunctionCallContext) -> Result<Return, napi::Error> {
    let (external,): (&External<Arguments>,) = function_call_context.args()?;
    let Arguments {
        repository_uri_ref,
        quick_diff_provider_ref,
        pijul_label,
        changes_label,
        untracked_label,
    } = &**external;

    let mut source_control = vscode_sys::scm::create_source_control(
        function_call_context.env,
        "pijul",
        pijul_label,
        &repository_uri_ref.get_inner(function_call_context.env)?,
    )?;

    let quick_diff_provider = quick_diff_provider_ref.get_inner(function_call_context.env)?;
    source_control.set_quick_diff_provider(quick_diff_provider)?;

    let unrecorded_changes = source_control.create_resource_group("changes", changes_label)?;
    let untracked_paths = source_control.create_resource_group("untracked", untracked_label)?;

    Ok((
        source_control.create_ref()?,
        unrecorded_changes.create_ref()?,
        untracked_paths.create_ref()?,
    ))
}