use std::{borrow::Cow, sync::Arc};
use std::future;
#[allow(unused)]
use log::info;
use serde::{Deserialize, Serialize};
use tower_lsp::jsonrpc::Result;

use crate::diagnostics::{AbstractLinterConfiguration, LinterStatus};
use crate::server::Backend;

#[derive(Clone)]
pub struct LinterStatusApi;

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct LinterStatusParams {
    language_id: String,
    linter_name: String,
    linter_path: String
}


impl <'a>tower_lsp::jsonrpc::Method<&'a Arc<Backend>, (LinterStatusParams, ), Result<LinterStatus>> for LinterStatusApi {
    type Future = future::Ready<Result<LinterStatus>>;

    fn invoke(&self, _server: &'a Arc<Backend>, _params: (LinterStatusParams, )) -> Self::Future {        
        let request_param = _params.0;
        
        let language_id = request_param.language_id;
        let linter_name = request_param.linter_name;
        let linter_path = request_param.linter_path;
        let linter_status = get_linter_status(
            &_server,
            &language_id,
            &linter_name,
            &linter_path
        );
        future::ready(linter_status)
    }
}

fn get_linter_status(
    backend: &Arc<Backend>,
    language_id: &str,
    linter_name: &str,
    #[allow(unused)]
    linter_path: &str
) -> Result<LinterStatus> {
    let configuration = backend.server.configuration.read().unwrap();
    // 获取对应语言的配置项目
    let configuration = match language_id {
        "verilog" => &configuration.vlog_linter_configuration,
        "systemverilog" => &configuration.svlog_linter_configuration,
        "vhdl" => &configuration.vhdl_linter_configuration,
        _ => {
            return Err(tower_lsp::jsonrpc::Error {
                code: tower_lsp::jsonrpc::ErrorCode::InvalidRequest,
                message: Cow::Owned(format!("无效的语言 ID {}", language_id)),
                data: None
            });
        }
    };

    // 再根据 linter name 进行分类讨论
    match linter_name {
        "iverilog" => {
            Ok(configuration.iverilog.linter_status(&backend.server))
        }

        "vivado" => {
            Ok(configuration.vivado.linter_status(&backend.server))
        }

        "modelsim" => {
            Ok(configuration.modelsim.linter_status(&backend.server))
        }

        "verible" => {
            Ok(configuration.verible.linter_status(&backend.server))
        }

        "verilator" => {
            Ok(configuration.verilator.linter_status(&backend.server))
        }

        _ => {
            return Err(tower_lsp::jsonrpc::Error {
                code: tower_lsp::jsonrpc::ErrorCode::InvalidRequest,
                message: Cow::Owned(format!("无效的诊断器 {}", linter_name)),
                data: None
            });
        }
    }
}

