#include "stdafx.h"

#include "ccl/lang/Literals.h"

#include "xtr/viewmodel/vmTextEdit.h"

#include "xtr/xtrDesign.h"
#include "resource.h"

#include "mockTextEdit.hpp"
#include "mockTermContext.hpp"
#include "mockMessageManager.hpp"

using ccl::lang::operator""_form;
using ccl::lang::operator""_ref;

class UTPyTextEdit : public ::testing::Test {
protected:
  using Reference = ccl::lang::Reference;
  using EntityRef = ccl::lang::EntityRef;
  using LexicalTerm = ccl::lang::LexicalTerm;
  using Morphology = ccl::lang::Morphology;

protected:
  MockTextEditCtrl control{};
  xtr::viewmodel::vmTextEdit model{ control };
  MockContext context{};
};

TEST_F(UTPyTextEdit, Unintialized) {
  EXPECT_TRUE(model.GetRefStr().IsEmpty());
  EXPECT_TRUE(model.GetRefSubstr(StrRange{ 0, 42 }).IsEmpty());
  ASSERT_NO_THROW(model.Invalidate());
  ASSERT_NO_THROW(model.OnEraseText(StrRange{ 0, 0 }, TRUE));
  EXPECT_EQ(model.RepresentativeOf(StrRange{ 0, 42 }), nullptr);
}

TEST_F(UTPyTextEdit, Initialize) {
  model.Initialize(context);
  EXPECT_EQ(&model.Context(), &context);

  MockContext context2{};
  model.Initialize(context2);
  EXPECT_EQ(&model.Context(), &context2);
}

TEST_F(UTPyTextEdit, SetRefStr) {
  using ccl::operator""_c17;
  static const EntityRef x1Ref{ "X1", Morphology{ "nomn,sing" } };

  model.Initialize(context);
  model.SetRefStr("");
  EXPECT_TRUE(control.text.IsEmpty());
  ASSERT_EQ(size(control.items), 0U);

  context.Insert("X1", LexicalTerm{ u8"\u212C42"_c17 });
  model.SetRefStr(xtr::mfc::ToMFC(x1Ref.ToString()));
  EXPECT_EQ(control.text, L"\u212C42");
  ASSERT_EQ(size(control.items), 1U);
  EXPECT_EQ(begin(control.items)->rng, StrRange(0, 3));

  model.SetRefStr("");
  EXPECT_EQ(xtr::mfc::ToSTL(control.text), "");
  ASSERT_EQ(size(control.items), 0U);

  context.Clear();
}

TEST_F(UTPyTextEdit, OnInsertRefErrors) {
  static const auto x1Ref = "@{X1|nomn,sing}"_ref;

  context.Insert("X1", LexicalTerm{ "42" });
  model.Initialize(context);
  model.SetRefStr(xtr::mfc::ToMFC(x1Ref.ToString()));

  auto insertMid = [&callModel = this->model] {
    callModel.OnInsertRef(StrRange{1, 2}, x1Ref);
  };
  ExpectMessage(Message{ .type = MB_ICONERROR, .msg = static_cast<uint32_t>(IXTRE_REF_CANNOT_ADD) }, insertMid);
  
  context.Clear();
}