use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};

use crate::{Position, text_document::TextDocumentIdentifier};

#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct CompletionParams {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub context: Option<CompletionContext>,
    #[serde(rename = "textDocument")]
    pub text_document: TextDocumentIdentifier,
    pub position: Position,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct CompletionContext {
    #[serde(rename = "triggerKind")]
    pub trigger_kind: CompletionTriggerKind,
    #[serde(rename = "triggerCharacter", skip_serializing_if = "Option::is_none")]
    pub trigger_character: Option<String>,
}

#[repr(i32)]
#[derive(Clone, Debug, PartialEq, Serialize_repr, Deserialize_repr)]
pub enum CompletionTriggerKind {
    Invoked = 1,
    TriggerCharacter = 2,
    TriggerForIncompleteCompletions = 3,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct CompletionList {
    #[serde(rename = "isIncomplete")]
    pub is_incomplete: bool,
    pub items: Vec<CompletionItem>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct CompletionItem {
    pub label: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub kind: Option<CompletionItemKind>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub detail: Option<String>,
}

#[repr(i32)]
#[derive(Clone, Debug, PartialEq, Serialize_repr, Deserialize_repr)]
pub enum CompletionItemKind {
    Text = 1,
    Method = 2,
    Function = 3,
    Constructor = 4,
    Field = 5,
    Variable = 6,
    Class = 7,
    Interface = 8,
    Module = 9,
    Property = 10,
    Unit = 11,
    Value = 12,
    Enum = 13,
    Keyword = 14,
    Snippet = 15,
    Color = 16,
    File = 17,
    Reference = 18,
    Folder = 19,
    EnumMember = 20,
    Constant = 21,
    Struct = 22,
    Event = 23,
    Operator = 24,
    TypeParameter = 25,
}

#[cfg(test)]
mod test {
    const JSON: &str = r#"
{
  "context": {
    "triggerKind": 1
  },
  "position": {
    "character": 1,
    "line": 0
  },
  "textDocument": {
    "uri": "file:///home/work/Cargo.toml"
  }
}
        "#;
    use super::*;

    #[test]
    fn test() {
        serde_json::from_str::<CompletionParams>(JSON).unwrap();
    }
}
