#[allow(unused)]
use log::info;
use serde::{Deserialize, Serialize};
use crate::{server::LspServer, utils::command::is_command_valid};
use ropey::Rope;
use tower_lsp::lsp_types::{Diagnostic, Url};

use super::{AbstractLinterConfiguration, LinterStatus};

#[derive(Debug, Serialize, Deserialize)]
pub struct VivadoConfiguration {
    pub language_id: String,
    pub linter: VivadoLinter,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct VivadoLinter {
    pub name: String,
    pub exe_name: String,
    /// 目前是否启动
    pub enabled: bool,
    pub path: String,
    pub args: Vec<String>,
}

impl VivadoLinter {
    fn new(invoker: &str, args: Vec<String>) -> Self {
        Self {
            name: "vivado".to_string(),
            exe_name: invoker.to_string(),
            enabled: false,
            path: invoker.to_string(),
            args,
        }
    }
}

impl AbstractLinterConfiguration for VivadoConfiguration {
    fn new(language_id: &str, invoker: &str, args: Vec<String>) -> Self {
        VivadoConfiguration {
            language_id: language_id.to_string(),
            linter: VivadoLinter::new(invoker, args)
        }
    }

    fn provide_diagnostics(
        &self,
        uri: &Url,
        #[allow(unused)]
        rope: &Rope,
        server: &LspServer
    ) -> Option<Vec<Diagnostic>> {
        let mut diagnostics = Vec::<Diagnostic>::new();

        Some(diagnostics)
    }

    fn get_linter_path(&self) -> &str {
        &self.linter.path
    }

    fn get_windows_extension(&self) -> &str {
        "exe"
    }

    fn linter_status(&self) -> LinterStatus {
        match self.language_id.as_str() {
            "verilog" => {
                let invoke_name = self.get_invoke_name("xvlog");
                let available = is_command_valid(&invoke_name);
                LinterStatus {
                    tool_name: "xvlog".to_string(),
                    available,
                    invoke_name
                }
            }

            "systemverilog" => {
                let invoke_name = self.get_invoke_name("xvlog");
                let available = is_command_valid(&invoke_name);
                LinterStatus {
                    tool_name: "xvlog".to_string(),
                    available,
                    invoke_name
                }
            }

            "vhdl" => {
                let invoke_name = self.get_invoke_name("xvhdl");
                let available = is_command_valid(&invoke_name);
                LinterStatus {
                    tool_name: "xvhdl".to_string(),
                    available,
                    invoke_name
                }
            }

            _ => {
                LinterStatus::default()
            }
        }
    }
}