// Bring in my package's API, which is what I'm testing
#include <socketcan_interface/filter.h>


#include <socketcan_interface/string.h>
#include <socketcan_interface/dummy.h>

// Bring in gtest
#include <gtest/gtest.h>


TEST(FilterTest, simpleMask)
{
  const std::string msg1("123#");
  const std::string msg2("124#");

  can::FrameFilterSharedPtr f1 = can::tofilter("123");

  EXPECT_TRUE(f1->pass(can::toframe(msg1)));
  EXPECT_FALSE(f1->pass(can::toframe(msg2)));
}

TEST(FilterTest, maskTests)
{
  const std::string msg1("123#");
  const std::string msg2("124#");
  const std::string msg3("122#");

  can::FrameFilterSharedPtr f1 = can::tofilter("123:123");
  can::FrameFilterSharedPtr f2 = can::tofilter("123:ffe");
  can::FrameFilterSharedPtr f3 = can::tofilter("123~123");

  EXPECT_TRUE(f1->pass(can::toframe(msg1)));
  EXPECT_FALSE(f1->pass(can::toframe(msg2)));
  EXPECT_FALSE(f1->pass(can::toframe(msg3)));


  EXPECT_TRUE(f2->pass(can::toframe(msg1)));
  EXPECT_FALSE(f2->pass(can::toframe(msg2)));
  EXPECT_TRUE(f2->pass(can::toframe(msg3)));

  EXPECT_FALSE(f3->pass(can::toframe(msg1)));
  EXPECT_TRUE(f3->pass(can::toframe(msg2)));
  EXPECT_TRUE(f3->pass(can::toframe(msg3)));

}

TEST(FilterTest, rangeTest)
{
  const std::string msg1("120#");
  const std::string msg2("125#");
  const std::string msg3("130#");

  can::FrameFilterSharedPtr f1 = can::tofilter("120-120");
  can::FrameFilterSharedPtr f2 = can::tofilter("120_120");
  can::FrameFilterSharedPtr f3 = can::tofilter("120-125");

  EXPECT_TRUE(f1->pass(can::toframe(msg1)));
  EXPECT_FALSE(f1->pass(can::toframe(msg2)));
  EXPECT_FALSE(f1->pass(can::toframe(msg3)));

  EXPECT_FALSE(f2->pass(can::toframe(msg1)));
  EXPECT_TRUE(f2->pass(can::toframe(msg2)));
  EXPECT_TRUE(f2->pass(can::toframe(msg3)));

  EXPECT_TRUE(f3->pass(can::toframe(msg1)));
  EXPECT_TRUE(f3->pass(can::toframe(msg2)));
  EXPECT_FALSE(f3->pass(can::toframe(msg3)));

}

class Counter {
public:
    size_t count_;
    Counter(): count_(0) {}
    void count(const can::Frame &frame) {
      ++count_;
    }
};

TEST(FilterTest, listenerTest)
{

  Counter counter;
  can::DummyBus bus("listenerTest");
  can::ThreadedDummyInterfaceSharedPtr dummy = std::make_shared<can::ThreadedDummyInterface>();
  dummy->init(bus.name, true, can::NoSettings::create());


  can::FilteredFrameListener::FilterVector filters;
  filters.push_back(can::tofilter("123:FFE"));

  can::FrameListenerConstSharedPtr  listener(new can::FilteredFrameListener(dummy,std::bind(&Counter::count, std::ref(counter), std::placeholders::_1), filters));

  can::Frame f1 = can::toframe("123#");
  can::Frame f2 = can::toframe("124#");
  can::Frame f3 = can::toframe("122#");

  dummy->send(f1);
  dummy->flush();
  EXPECT_EQ(1, counter.count_);
  dummy->send(f2);
  dummy->flush();
  EXPECT_EQ(1, counter.count_);
  dummy->send(f3);
  dummy->flush();
  EXPECT_EQ(2, counter.count_);

}

// Run all the tests that were declared with TEST()
int main(int argc, char **argv){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
