// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "repl.h"

#include <stdlib.h>
#include <zircon/syscalls.h>

#include <array>
#include <fstream>
#include <queue>
#include <string>

#include <gtest/gtest.h>

#include "li.h"
#include "src/developer/shell/josh/lib/runtime.h"
#include "src/lib/line_input/line_input.h"
#include "third_party/quickjs/quickjs-libc.h"
#include "third_party/quickjs/quickjs.h"

extern "C" const uint8_t qjsc_repl_init[];
extern "C" const uint32_t qjsc_repl_init_size;

namespace shell::repl {

class TestRepl : public Repl {
 public:
  TestRepl(JSContext* ctx, const std::string& prompt, bool ev)
      : Repl(ctx, prompt, [this](const std::string& s) { HandleLine(s); }), eval_(ev) {
    ChangeOutput(&shell_out_);
  }

  std::queue<std::string> GetListFullLines() {
    std::queue<std::string> res(full_lines_);
    std::queue<std::string>().swap(full_lines_);
    return res;
  }

  std::queue<std::string> GetListFullCmds() {
    std::queue res(full_cmds_);
    std::queue<std::string>().swap(full_cmds_);
    return res;
  }

  std::string PublicOpenSymbols(const std::string& cmd) { return OpenSymbols(cmd); }

  std::string GetOutput() { return shell_out_.str(); }

 protected:
  void HandleLine(const std::string& line) override {
    full_lines_.push(line);
    Repl::HandleLine(line);
  }

  void EvalCmd(const std::string& cmd) override {
    full_cmds_.push(cmd);
    if (eval_) {
      Repl::EvalCmd(cmd);
    } else {
      ShowPrompt();  // no evaluation, which makes this call
    }
  }

 private:
  std::queue<std::string> full_lines_;
  std::queue<std::string> full_cmds_;
  bool eval_ = false;
  std::ostringstream shell_out_;
};

TEST(Repl, Sanity) {
  std::ostringstream captured_output;

  // set up the repl
  shell::Runtime rt;
  ASSERT_NE(rt.Get(), nullptr);
  shell::Context ctx(&rt);
  ASSERT_NE(ctx.Get(), nullptr);
  ASSERT_NE(0, ctx.InitStd());
  ASSERT_NE(0, ctx.InitBuiltins("/pkg/data/fidling", "/pkg/data/lib"));
  JSContext* ctx_ptr = ctx.Get();
  js_std_add_helpers(ctx_ptr, 0, nullptr);
  ASSERT_NE(shell::li::LiModuleInit(ctx_ptr, "li_internal"), nullptr);
  js_std_eval_binary(ctx_ptr, qjsc_repl_init, qjsc_repl_init_size, 0);

  // uninstall repl read handler and get a pointer to the repl
  std::string script = "os.setReadHandler(std.in.fileno(), null); repl.repl;";
  JSValue res =
      JS_Eval(ctx_ptr, script.c_str(), script.length(), "<evalScript>", JS_EVAL_TYPE_GLOBAL);
  repl::Repl* repl = li::GetRepl(ctx_ptr, res);

  repl->ChangeOutput(&captured_output);

  std::string test_string = "print(4);\n";
  repl->FeedInput(reinterpret_cast<unsigned char*>(test_string.data()), test_string.size());

  std::string actual = captured_output.str();
  std::string expected("undefined\n");
  ASSERT_STREQ(expected.c_str(), actual.c_str());

  std::string test_string2 =
      "ccc = new Promise(function(resolve, reject){os.setTimeout(() => resolve('d'), 1);});\n";
  repl->FeedInput(reinterpret_cast<unsigned char*>(test_string2.data()), test_string2.size());
  js_std_loop(ctx_ptr);

  std::string actual2 = captured_output.str();
  std::string expected2("undefined\nd\n");
  ASSERT_STREQ(expected2.c_str(), actual2.c_str());
}

TEST(Repl, SpecialCharacters) {
  JSContext* ctx_ptr = nullptr;
  TestRepl repl(ctx_ptr, "li >", false);

  std::string test_string = "pr\x1b[Dint(3)\n";
  std::string expected = "pint(3)r";
  repl.FeedInput(reinterpret_cast<unsigned char*>(test_string.data()), test_string.size());
  std::queue<std::string> res_lines = repl.GetListFullLines();
  std::queue<std::string> res_cmds = repl.GetListFullCmds();
  EXPECT_EQ(res_lines.size(), 1u);
  EXPECT_EQ(res_cmds.size(), 1u);
  EXPECT_STREQ(res_lines.front().c_str(), expected.c_str());
  EXPECT_STREQ(res_cmds.front().c_str(), expected.c_str());
}

TEST(Repl, MultipleLines) {
  JSContext* ctx_ptr = nullptr;
  TestRepl repl(ctx_ptr, "li >", false);

  constexpr int kNumLines = 4;
  std::array<std::string, kNumLines> test_string1 = {"function (\n", "a){\n", "\tprint(a)\n",
                                                     "};\n"};
  std::string cur_cmd;
  std::string expected = "function (a){print(a)};";
  std::array<std::string, kNumLines> expected_open_symbols = {"(", "{", "{", ""};
  for (int i = 0; i < kNumLines; i++) {
    repl.FeedInput(reinterpret_cast<unsigned char*>(test_string1[i].data()),
                   test_string1[i].size());
    std::queue<std::string> res_lines = repl.GetListFullLines();
    ASSERT_EQ(res_lines.size(), 1u);
    cur_cmd += res_lines.front();
    EXPECT_STREQ(repl.PublicOpenSymbols(cur_cmd).c_str(), expected_open_symbols[i].c_str());
  }
  std::queue<std::string> res_cmds = repl.GetListFullCmds();
  EXPECT_EQ(res_cmds.size(), 1u);
  EXPECT_STREQ(res_cmds.front().c_str(), expected.c_str());

  constexpr int kNumLines2 = 5;
  std::array<std::string, kNumLines2> test_string2 = {"regex = /\n", "[abc\n", "/\n", "]\n",
                                                      "/;\n"};
  std::array<std::string, kNumLines2> expected_lines = {"regex = /", "[abc", "/", "]", "/;"};
  std::string expected2 = "regex = /[abc/]/;";
  std::array<std::string, kNumLines2> expected_open_symbols2 = {"/", "/[", "/[", "/", ""};
  cur_cmd = "";
  for (int i = 0; i < kNumLines2; i++) {
    repl.FeedInput(reinterpret_cast<unsigned char*>(test_string2[i].data()),
                   test_string2[i].size());
    std::queue<std::string> res_lines = repl.GetListFullLines();
    ASSERT_EQ(res_lines.size(), 1u);
    cur_cmd += res_lines.front();
    EXPECT_STREQ(repl.PublicOpenSymbols(cur_cmd).c_str(), expected_open_symbols2[i].c_str());
  }
  res_cmds = repl.GetListFullCmds();
  EXPECT_EQ(res_cmds.size(), 1u);
  EXPECT_STREQ(res_cmds.front().c_str(), expected2.c_str());
}

TEST(Repl, TabCompletionAndHistory) {
  std::ostringstream captured_output;

  // set up the repl
  shell::Runtime rt;
  ASSERT_NE(rt.Get(), nullptr);
  shell::Context ctx(&rt);
  ASSERT_NE(ctx.Get(), nullptr);
  ASSERT_NE(0, ctx.InitStd());
  ASSERT_NE(0, ctx.InitBuiltins("/pkg/data/fidling", "/pkg/data/lib"));
  JSContext* ctx_ptr = ctx.Get();
  js_std_add_helpers(ctx_ptr, 0, nullptr);
  ASSERT_NE(shell::li::LiModuleInit(ctx_ptr, "li_internal"), nullptr);
  js_std_eval_binary(ctx_ptr, qjsc_repl_init, qjsc_repl_init_size, 0);

  // uninstall repl read handler and get a pointer to the repl
  std::string script = "os.setReadHandler(std.in.fileno(), null); repl.repl;";
  JSValue res =
      JS_Eval(ctx_ptr, script.c_str(), script.length(), "<evalScript>", JS_EVAL_TYPE_GLOBAL);
  auto repl = reinterpret_cast<repl::Repl*>(li::GetRepl(ctx_ptr, res));

  repl->ChangeOutput(&captured_output);

  std::string test_string = "a = \"dddd\";\n";
  repl->FeedInput(reinterpret_cast<unsigned char*>(test_string.data()), test_string.size());
  std::string test_string2 = "b =a.le\t;\n";
  repl->FeedInput(reinterpret_cast<unsigned char*>(test_string2.data()), test_string2.size());

  std::string actual = captured_output.str();
  std::string expected("dddd\n4\n");
  ASSERT_STREQ(expected.c_str(), actual.c_str());

  // testing history, repeats the previous command
  std::string test_string3 = "\x1b[A\n";
  repl->FeedInput(reinterpret_cast<unsigned char*>(test_string3.data()), test_string3.size());

  std::string actual2 = captured_output.str();
  std::string expected2("dddd\n4\n4\n");
  ASSERT_STREQ(expected2.c_str(), actual2.c_str());
}

}  // namespace shell::repl
