// Copyright 2021 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// A utility similar to expect(1) but for json-rpc.

#include <fstream>
#include <iostream>
#include <streambuf>
#include <string>

#include "absl/status/status.h"
#include "absl/strings/match.h"
#include "common/lsp/message-stream-splitter.h"
#include "nlohmann/json.hpp"

#ifndef _WIN32
#include <unistd.h>
#else
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
// Windows doesn't have Posix read(), but something called _read
#define read(fd, buf, size) _read(fd, buf, size)
#endif

using nlohmann::json;
using verible::lsp::MessageStreamSplitter;

static int usage(const char *progname, const char *msg) {
  fprintf(stderr, "%s\n\nUsage: %s <expect-script-file>\n", msg, progname);
  fprintf(stderr, "%s", R"(
The program receives JSON-RPC header/body responses on stdin
and compares if the response is contained in the response array.
Right now, the responses are checked to arrive in the same sequence they
are mentioned in the array (this might change in the future if we consider
async responses).

The exit code will be 0 if all expected responses have been received or the
index (1-based) where they failed.

Matching done 'fuzzy' so that expect strings can only contain what is relevant.
 - json structures are only checked for the keys mentioned and ignores
   additional keys
 - arrays must match in length and contain the matching content (by these
   matching rules)
 - strings are substring matched
 - numeric literals are matched exactly.

A typical expect-script file would be a json array like this
[
 {
   "json_contains": { ... some json, but only interesting fields ... }
 },
]
)");
  return 1;
}

static bool ValuesMatch(const json &expected, const json &received);
static bool CheckNested(const json &expected, const json &received) {
  for (const auto &[key, value] : expected.items()) {
    auto received_value = received.find(key);
    if (received_value == received.end()) {
      std::cerr << "key '" << key << "' missing in " << received << std::endl;
      return false;
    }
    if (!ValuesMatch(value, *received_value)) {
      std::cerr << "^ Issue with value at key '" << key << "'" << std::endl;
      return false;
    }
  }
  return true;
}
static bool ValuesMatch(const json &expected, const json &received) {
  if (expected.type() != received.type()) {
    std::cerr << "type mismatch " << received << std::endl;
    return false;
  }
  if (expected.is_object()) {
    return CheckNested(expected, received);
  } else if (expected.is_array()) {
    if (expected.size() != received.size()) {
      std::cerr << "array size mismatch. Expected: " << expected.size()
                << "; got: " << received.size() << std::endl;
      return false;
    }
    for (size_t i = 0; i < expected.size(); ++i) {
      if (!ValuesMatch(expected[i], received[i])) return false;
    }
    return true;

  } else if (expected.is_string()) {
    return absl::StrContains(received.get<std::string>(),
                             expected.get<std::string>());
  }
  if (expected != received) {
    std::cerr << "expected: " << expected << "; got: " << received << std::endl;
    return false;
  }
  return true;
}

static bool CheckExpectedMatch(const json &expected, const json &received) {
  auto json_contains = expected.find("json_contains");
  if (json_contains == expected.end()) {
    std::cerr << "'json_contains' key missing " << expected << std::endl;
    return false;
  }
  const json &partial_data = *json_contains;
  return CheckNested(partial_data, received);
}

int main(int argc, char *argv[]) {
#ifdef _WIN32
  _setmode(_fileno(stdin), _O_BINARY);
#endif
  static constexpr int kInFiledescriptor = 0;  // STDIN_FILENO on Unix

  if (argc != 2) {
    return usage(argv[0], "Required filename");
  }
  std::ifstream file(argv[1]);
  if (!file.is_open()) return usage(argv[0], "Could not open file");
  const std::string expect_script((std::istreambuf_iterator<char>(file)),
                                  std::istreambuf_iterator<char>());
  const json expect_data = json::parse(expect_script);
  if (!expect_data.is_array()) {
    return usage(argv[0], "Input needs to be a json array");
  }

  // Let's be lenient in parsing.
  const bool kStrictCRLFrequirement = true;
  MessageStreamSplitter stream_splitter(4096, !kStrictCRLFrequirement);

  int first_error = -1;
  size_t expect_pos = 0;
  stream_splitter.SetMessageProcessor(
      [&expect_data, &expect_pos, &first_error](absl::string_view,
                                                absl::string_view body) {
        std::cerr << "Got: " << body << std::endl;
        const json received = json::parse(body);
        const json &expected = expect_data[expect_pos];
        if (!CheckExpectedMatch(expected, received)) {
          if (first_error < 0) first_error = expect_pos;
        }
        ++expect_pos;
      });

  absl::Status status = absl::OkStatus();
  while (status.ok()) {
    status = stream_splitter.PullFrom([](char *buf, int size) -> int {  //
      return read(kInFiledescriptor, buf, size);
    });
  }

  if (status.code() != absl::StatusCode::kUnavailable) {
    std::cerr << "Expected EOF, got " << status << std::endl;
    return expect_pos;
  }

  return expect_pos == expect_data.size() ? (first_error + 1) : expect_pos;
}
