use tower_lsp::lsp_types::*;


pub fn provide_keyword_completions(keywords: &[(&str, &str)]) -> Vec<CompletionItem> {
    let mut items: Vec<CompletionItem> = Vec::new();
    for key in keywords {
        let label_details = CompletionItemLabelDetails {
            description: Some("keyword".to_string()),
            ..Default::default()
        };
        if key.1.is_empty() {
            items.push(CompletionItem {
                label: key.0.to_string(),
                label_details: Some(label_details),
                kind: Some(CompletionItemKind::KEYWORD),
                ..CompletionItem::default()
            });
        } else {
            items.push(CompletionItem {
                label: key.0.to_string(),
                kind: Some(CompletionItemKind::KEYWORD),
                label_details: Some(label_details),
                insert_text: Some(key.1.to_string()),
                insert_text_format: Some(InsertTextFormat::SNIPPET),
                ..CompletionItem::default()
            })
        }
    }
    items
}

/// (&str, &str, &str): (label, snippet, description)
pub const VLOG_KEYWORDS: &[(&str, &str)] = &[
    ("accept_on", ""),
    ("alias", ""),
    ("always", "always @($1) begin\nend"),
    ("always_comb", "always_comb begin\n\t$1\nend"),
    ("always_ff", "always_ff @($1) begin\nend"),
    ("always_latch", "always_latch begin\n\t$1\nend"),
    ("and", ""),
    ("assert", ""),
    ("assign", ""),
    ("assume", ""),
    ("automatic", ""),
    ("before", ""),
    ("begin", "begin\n\t$1\nend"),
    ("bind", ""),
    ("bins", ""),
    ("binsof", ""),
    ("bit", ""),
    ("break", ""),
    ("buf", ""),
    ("bufif0", ""),
    ("bufif1", ""),
    ("byte", ""),
    ("case", "case $1;\nendcase"),
    ("casex", "casex $1;\nendcase"),
    ("casez", "casez $1;\nendcase"),
    ("cell", ""),
    ("chandle", ""),
    ("checker", "checker $1;\nendchecker"),
    ("class", "class $1;\nendclass"),
    ("clocking", "clocking $1;\nendclocking"),
    ("cmos", ""),
    ("config", "config $1;\nendconfig"),
    ("const", ""),
    ("constraint", ""),
    ("context", ""),
    ("continue", ""),
    ("cover", ""),
    ("covergroup", ""),
    ("coverpoint", ""),
    ("cross", ""),
    ("deassign", ""),
    ("default", ""),
    ("defparam", ""),
    ("design", ""),
    ("disable", ""),
    ("dist", ""),
    ("do", ""),
    ("edge", ""),
    ("else", ""),
    ("end", ""),
    ("endcase", ""),
    ("endchecker", ""),
    ("endclass", ""),
    ("endclocking", ""),
    ("endconfig", ""),
    ("endfunction", ""),
    ("endgenerate", ""),
    ("endgroup", ""),
    ("endinterface", ""),
    ("endmodule", ""),
    ("endpackage", ""),
    ("endprimitive", ""),
    ("endprogram", ""),
    ("endproperty", ""),
    ("endspecify", ""),
    ("endsequence", ""),
    ("endtable", ""),
    ("endtask", ""),
    ("enum", ""),
    ("event", ""),
    ("eventually", ""),
    ("expect", ""),
    ("export", ""),
    ("extends", ""),
    ("extern", ""),
    ("final", ""),
    ("first_match", ""),
    ("for", ""),
    ("force", ""),
    ("foreach", ""),
    ("forever", ""),
    ("fork", ""),
    ("forkjoin", ""),
    ("function", "function $1;\nendfunction"),
    ("generate", "generate\n\t$1\nendgenerate"),
    ("genvar", ""),
    ("global", ""),
    ("highz0", ""),
    ("highz1", ""),
    ("if", ""),
    ("iff", ""),
    ("ifnone", ""),
    ("ignore_bins", ""),
    ("illegal_bins", ""),
    ("implements", ""),
    ("implies", ""),
    ("import", ""),
    ("incdir", ""),
    ("include", "`include \"$1\""),
    ("initial", "initial begin\n\t$1\nend"),
    ("inout", "inout $1"),
    ("input", "input $1"),
    ("inside", ""),
    ("instance", ""),
    ("int", ""),
    ("integer", ""),
    ("interconnect", ""),
    ("interface", "interface $1;\nendinterface"),
    ("intersect", ""),
    ("join", ""),
    ("join_any", ""),
    ("join_none", ""),
    ("large", ""),
    ("let", ""),
    ("liblist", ""),
    ("library", ""),
    ("local", ""),
    ("localparam", ""),
    ("logic", ""),
    ("longint", ""),
    ("macromodule", ""),
    ("matches", ""),
    ("medium", ""),
    ("modport", ""),
    ("module", "module $1($2);\nendmodule"),
    ("nand", ""),
    ("negedge", ""),
    ("nettype", ""),
    ("new", ""),
    ("nexttime", ""),
    ("nmos", ""),
    ("nor", ""),
    ("noshowcancelled", ""),
    ("not", ""),
    ("notif0", ""),
    ("notif1", ""),
    ("null", ""),
    ("or", ""),
    ("output", "output $1"),
    ("package", "package $1;\nendpackage"),
    ("packed", ""),
    ("parameter", ""),
    ("pmos", ""),
    ("posedge", ""),
    ("primitive", "primitive $1;\nendprimitive"),
    ("priority", ""),
    ("program", "program $1;\nendprogram"),
    ("property", "property $1;\nendproperty"),
    ("protected", ""),
    ("pull0", ""),
    ("pull1", ""),
    ("pulldown", ""),
    ("pullup", ""),
    ("pulsestyle_ondetect", ""),
    ("pulsestyle_onevent", ""),
    ("pure", ""),
    ("rand", ""),
    ("randc", ""),
    ("randcase", ""),
    ("randsequence", ""),
    ("rcmos", ""),
    ("real", ""),
    ("realtime", ""),
    ("ref", ""),
    ("reg", ""),
    ("reject_on", ""),
    ("release", ""),
    ("repeat", ""),
    ("restrict", ""),
    ("return", ""),
    ("rnmos", ""),
    ("rpmos", ""),
    ("rtran", ""),
    ("rtranif0", ""),
    ("rtranif1", ""),
    ("s_always", ""),
    ("s_eventually", ""),
    ("s_nexttime", ""),
    ("s_until", ""),
    ("s_until_with", ""),
    ("scalared", ""),
    ("sequence", "sequence $1;\nendsequence"),
    ("shortint", ""),
    ("shortreal", ""),
    ("showcancelled", ""),
    ("signed", ""),
    ("small", ""),
    ("soft", ""),
    ("solve", ""),
    ("specify", "specify $1;\nendspecify"),
    ("specparam", ""),
    ("static", ""),
    ("string", ""),
    ("strong", ""),
    ("strong0", ""),
    ("strong1", ""),
    ("struct", ""),
    ("super", ""),
    ("supply0", ""),
    ("supply1", ""),
    ("sync_accept_on", ""),
    ("sync_reject_on", ""),
    ("table", "table $1;\nendtable"),
    ("tagged", ""),
    ("task", "task $1;\nendtask"),
    ("this", ""),
    ("throughout", ""),
    ("time", ""),
    ("timeprecision", ""),
    ("timeunit", ""),
    ("tran", ""),
    ("tranif0", ""),
    ("tranif1", ""),
    ("tri", ""),
    ("tri0", ""),
    ("tri1", ""),
    ("triand", ""),
    ("trior", ""),
    ("trireg", ""),
    ("type", ""),
    ("typedef", ""),
    ("union", ""),
    ("unique", ""),
    ("unique0", ""),
    ("unsigned", ""),
    ("until", ""),
    ("until_with", ""),
    ("untyped", ""),
    ("use", ""),
    ("uwire", ""),
    ("var", ""),
    ("vectored", ""),
    ("virtual", ""),
    ("void", ""),
    ("wait", ""),
    ("wait_order", ""),
    ("wand", ""),
    ("weak", ""),
    ("weak0", ""),
    ("weak1", ""),
    ("while", ""),
    ("wildcard", ""),
    ("wire", ""),
    ("with", ""),
    ("within", ""),
    ("wor", ""),
    ("xnor", ""),
    ("xor", ""),
];

pub const VHDL_KEYWORDS: &[(&str, &str)] = &[
    ("abs", ""),
    ("access", ""),
    ("after", ""),
    ("alias", "alias $1 is $2;"),
    ("all", ""),
    ("and", ""),
    ("architecture", "architecture $1 of $2 is\nbegin\n\t$3\nend $1;"),
    ("array", "array $1 is $2;"),
    ("assert", "assert $1 report $2 severity $3;"),
    ("attribute", "attribute $1 : $2;"),
    ("begin", "begin\n\t$1\nend;"),
    ("block", "block ($1) is\nbegin\n\t$2\nend block;"),
    ("body", "body $1 is\nbegin\n\t$2\nend $1;"),
    ("buffer", ""),
    ("bus", ""),
    ("case", "case $1 is\n\twhen $2 => $3;\nend case;"),
    ("component", "component $1 is\n\tport (\n\t\t$2\n\t);\nend component;"),
    ("configuration", "configuration $1 of $2 is\nfor $3\n\t$4\nend for;\nend $1;"),
    ("constant", "constant $1 : $2 := $3;"),
    ("disconnect", "disconnect $1 after $2;"),
    ("downto", ""),
    ("else", ""),
    ("elsif", ""),
    ("end", ""),
    ("entity", "entity $1 is\n\tport (\n\t\t$2\n\t);\nend $1;"),
    ("exit", "exit $1 when $2;"),
    ("file", "file $1 : $2;"),
    ("for", "for $1 in $2 loop\n\t$3\nend loop;"),
    ("function", "function $1 return $2 is\nbegin\n\t$3\nend $1;"),
    ("generate", "generate\n\t$1\nend generate;"),
    ("generic", "generic (\n\t$1\n);"),
    ("group", "group $1 : $2 ($3);"),
    ("guarded", ""),
    ("if", "if $1 then\n\t$2\nend if;"),
    ("impure", ""),
    ("in", ""),
    ("inertial", ""),
    ("inout", ""),
    ("is", ""),
    ("label", ""),
    ("library", "library $1;"),
    ("linkage", ""),
    ("literal", ""),
    ("loop", "loop\n\t$1\nend loop;"),
    ("map", "map ($1 => $2);"),
    ("mod", ""),
    ("nand", ""),
    ("new", ""),
    ("next", "next $1 when $2;"),
    ("nor", ""),
    ("not", ""),
    ("null", "null;"),
    ("of", ""),
    ("on", ""),
    ("open", ""),
    ("or", ""),
    ("others", ""),
    ("out", ""),
    ("package", "package $1 is\n\t$2\nend $1;"),
    ("port", "port (\n\t$1\n);"),
    ("postponed", ""),
    ("procedure", "procedure $1 is\nbegin\n\t$2\nend $1;"),
    ("process", "process ($1) is\nbegin\n\t$2\nend process;"),
    ("pure", ""),
    ("range", ""),
    ("record", "record\n\t$1\nend record;"),
    ("register", ""),
    ("reject", ""),
    ("rem", ""),
    ("report", "report $1 severity $2;"),
    ("return", "return $1;"),
    ("rol", ""),
    ("ror", ""),
    ("select", "select\n\t$1\nend select;"),
    ("severity", ""),
    ("signal", "signal $1 : $2 := $3;"),
    ("shared", ""),
    ("sla", ""),
    ("sll", ""),
    ("sra", ""),
    ("srl", ""),
    ("subtype", "subtype $1 is $2;"),
    ("then", ""),
    ("to", ""),
    ("transport", ""),
    ("type", "type $1 is $2;"),
    ("unaffected", ""),
    ("units", "units $1;\n\t$2\nend units;"),
    ("until", ""),
    ("use", "use $1;"),
    ("variable", "variable $1 : $2 := $3;"),
    ("wait", "wait on $1;"),
    ("when", ""),
    ("while", "while $1 loop\n\t$2\nend loop;"),
    ("with", "with $1 select\n\t$2\nend select;"),
    ("xnor", ""),
    ("xor", ""),
];