#![recursion_limit = "256"]

use request::{
    test::CustomParamRequest,
    test::CustomRequest,
    fast::DoFastApi,
    fast::SyncFastApi,
    config::UpdateConfigurationApi,
    primitives::DoPrimitivesJudgeApi,
    linter::LinterStatusApi
};

use log::info;
use std::sync::Arc;
use structopt::StructOpt;
use tower_lsp::{LspService, Server};

mod core;
mod completion;
mod definition;
mod hover;
mod document_symbol;
mod document_highlight;
mod inlay_hint;
mod code_lens;
mod utils;
mod diagnostics;
mod format;
mod server;
mod sources;
mod request;
mod execute_command;

use server::Backend;

#[derive(StructOpt, Debug)]
#[structopt(name = "Digtal LSP", about = "LSP for Digital IDE")]
struct Opt {}

#[tokio::main]
async fn main() {
    let _ = Opt::from_args();
    let log_handle = flexi_logger::Logger::with(flexi_logger::LogSpecification::info())
        .start()
        .unwrap();
    
    info!("launch Digital LSP, version: 0.4.0");

    let stdin = tokio::io::stdin();
    let stdout = tokio::io::stdout();

    let (service, socket) = LspService::build(|client| {
        let backend = Arc::new(Backend::new(client, log_handle));
        backend
    })
        .custom_method("custom/request", CustomRequest)             // for test
        .custom_method("custom/paramRequest", CustomParamRequest)   // for test
        .custom_method("api/fast", DoFastApi)
        .custom_method("api/do-primitives-judge", DoPrimitivesJudgeApi)
        .custom_method("api/update-configuration", UpdateConfigurationApi)
        .custom_method("api/sync-fast", SyncFastApi)
        .custom_method("api/linter-status", LinterStatusApi)
        .finish();

    Server::new(stdin, stdout, socket)
        .serve(service)
        .await;
}
