#include <string>
#include "any.h"
#include "ctx.h"
#include "memory_Context.h"

std::string s(const char *str) {
  return std::string(str);
}

std::string test_ctx_Controller_executeFunctions_registerFunction_set() {
  auto c = memory_createContext();
  ctx_Controller<memory_Context> ctrl(c);
  // Disable automatic invocation of executeFunctions.
  ctrl.isProcessingQueue = true;
  ctrl.set("input", s("123"));

  auto processInput = [](memory_Context c) -> memory_Context {
    if (c.recentField == "input") {
      c.outputHelp = "Checked";
      c.recentField = "outputHelp";
      return c;
    }
    c.recentField = "none";
    return c;
  };

  ctrl.registerFunction(processInput);
  // Apply 'input'.
  ctrl.executeFunctions();
  // Apply 'outputHelp'.
  ctrl.executeFunctions();
  if (
    ctrl.context.input == "123" &&
    ctrl.context.outputHelp == "Checked"
  ) {
    return "OK: ctx_Controller_executeFunctions_set";
  }
  return "ERR: ctx_Controller_executeFunctions_set";
}

std::string test_ctx_Controller_processQueue() {
  auto c = memory_createContext();
  ctx_Controller<memory_Context> ctrl(c);

  auto processInput = [](memory_Context c) -> memory_Context {
    if (c.recentField == "input") {
      c.outputHelp = "Checked";
      c.recentField = "outputHelp";
      return c;
    }
    c.recentField = "none";
    return c;
  };

  ctrl.registerFunction(processInput);
  ctrl.set("input", s("abc"));
  if (
    ctrl.context.input == "abc" &&
    ctrl.context.outputHelp == "Checked"
  ) {
    return "OK: ctx_Controller_processQueue";
  }
  return "ERR: ctx_Controller_processQueue";
}

std::string test_ctx_Controller_registerFieldCallback_match() {
  auto c = memory_createContext();
  ctx_Controller<memory_Context> ctrl(c);

  c.input = "123";
  c.recentField = "input";
  std::string callbackInput = "";

  auto setCallbackInput = [&callbackInput](memory_Context c) {
    if (
      c.recentField == "input"
    ) {
      callbackInput = c.input;
    }
  };

  ctrl.registerFieldCallback("input", setCallbackInput);
  ctrl.reportContext();
  if (
    ctrl.context.input == callbackInput
  ) {
    return "OK: ctx_Controller_registerFieldCallback_match";
  }
  return "ERR: ctx_Controller_registerFieldCallback_match";
}

std::string test_ctx_Controller_registerFieldCallback_mismatch() {
  auto c = memory_createContext();
  ctx_Controller<memory_Context> ctrl(c);

  c.input = "123";
  c.outputHelp = "you";
  // A field other than 'input' is marked recent.
  c.recentField = "outputHelp";
  std::string callbackInput = "";

  auto setCallbackInput = [&callbackInput](memory_Context c) {
    if (
      c.recentField == "input"
    ) {
      callbackInput = c.input;
    }
  };

  ctrl.registerFieldCallback("input", setCallbackInput);
  ctrl.reportContext();
  if (
    callbackInput == ""
  ) {
    return "OK: ctx_Controller_registerFieldCallback_mismatch";
  }
  return "ERR: ctx_Controller_registerFieldCallback_mismatch";
}

std::string test_memory_Context_field() {
  auto c = memory_createContext();
  c.input = "abc";
  if (
    libany::any_cast<std::string>(c.field("input")) == "abc"
  ) {
    return "OK: memory_Context_field";
  }
  return "ERR: memory_Context_field";
}

std::string test_memory_Context_setField() {
  auto c = memory_createContext();
  c.input = "abc";
  c.setField("input", s("123"));
  if (
    c.input == "123"
  ) {
    return "OK: memory_Context_setField";
  }
  return "ERR: memory_Context_setField";
}