#!/usr/bin/python3

import json
import os
import pprint
import re
import subprocess
import time


path = os.path.dirname(os.path.realpath(__file__))

tests = [
    (
        {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "initialize",
            "params": {"rootUri": "file://" + path},
        },
        {
            "id": 1,
            "jsonrpc": "2.0",
            "result": {
                "capabilities": {
                    "codeActionProvider": {"codeActionKinds": ["quickfix"]},
                    "codeLensProvider": {"resolveProvider": False},
                    "completionProvider": {
                        "resolveProvider": False,
                        "triggerCharacters": [".", ":", ">", "#", "<", '"', "/"],
                    },
                    "declarationProvider": True,
                    "definitionProvider": True,
                    "documentFormattingProvider": True,
                    "documentHighlightProvider": True,
                    "documentLinkProvider": {"resolveProvider": True},
                    "documentOnTypeFormattingProvider": {
                        "firstTriggerCharacter": "}",
                        "moreTriggerCharacter": [],
                    },
                    "documentRangeFormattingProvider": True,
                    "documentSymbolProvider": True,
                    "executeCommandProvider": {"commands": ["ccls.xref"]},
                    "foldingRangeProvider": True,
                    "hoverProvider": True,
                    "implementationProvider": True,
                    "referencesProvider": True,
                    "renameProvider": True,
                    "signatureHelpProvider": {"triggerCharacters": ["(", ","]},
                    "textDocumentSync": {
                        "change": 2,
                        "openClose": True,
                        "save": {"includeText": False},
                        "willSave": False,
                        "willSaveWaitUntil": False,
                    },
                    "typeDefinitionProvider": True,
                    "workspace": {
                        "workspaceFolders": {
                            "changeNotifications": True,
                            "supported": True,
                        }
                    },
                    "workspaceSymbolProvider": True,
                }
            },
        },
    ),
    (
        {"jsonrpc": "2.0", "id": 1, "method": "$ccls/info"},
        {
            "id": 1,
            "jsonrpc": "2.0",
            "result": {
                "db": {"files": 1, "funcs": 0, "types": 1, "vars": 1},
                "pipeline": {"pendingIndexRequests": 0},
                "project": {"entries": 1},
            },
        },
    ),
    (
        {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "workspace/symbol",
            "params": {"query": "test"},
        },
        {
            "id": 1,
            "jsonrpc": "2.0",
            "result": [
                {
                    "kind": 13,
                    "location": {
                        "range": {
                            "end": {"character": 12, "line": 0},
                            "start": {"character": 4, "line": 0},
                        },
                        "uri": "file://" + path + "/sample.c",
                    },
                    "name": "int test_var",
                }
            ],
        },
    ),
]


def encode(msg):
    msg_str = json.dumps(msg)
    rpc_str = "Content-Length: %d\r\n\r\n%s" % (len(msg_str), msg_str)
    return rpc_str.encode()


def read(f):
    size = int(re.findall(r"Content-Length: (\d+)", f.readline().decode())[0])
    f.readline()
    return json.loads(f.read(size).decode())


with subprocess.Popen(
    [os.getenv("CCLS", "ccls"), "-v=-1"], stdin=subprocess.PIPE, stdout=subprocess.PIPE
) as proc:
    for tt in tests:
        method = tt[0]["method"]
        print("Testing", method)
        proc.stdin.write(encode(tt[0]))
        proc.stdin.flush()
        if method == "initialize":
            # wait ccls finishing index
            time.sleep(1)
        got = read(proc.stdout)
        if not tt[1] == got:
            print("Expect:")
            pprint.pprint(tt[1])
            print("Got:")
            pprint.pprint(got)
            raise AssertionError
    proc.stdin.close()
