#include <array>

#include <gtest/gtest.h>
#include <prjxray/xilinx/architectures.h>
#include <prjxray/xilinx/bitstream_reader.h>
#include <prjxray/xilinx/bitstream_writer.h>

#include <prjxray/bit_ops.h>

using namespace prjxray::xilinx;

constexpr uint32_t kType1NOP = prjxray::bit_field_set<uint32_t>(0, 15, 13, 0x1);

extern const uint32_t MakeType1(const int opcode,
                                const int address,
                                const int word_count);

extern const std::vector<uint32_t> MakeType2(const int opcode,
                                             const int address,
                                             const int word_count);

void dump_packets(BitstreamWriter<Spartan6> writer, bool nl = true) {
	int i = 0;
	// for (uint32_t x : itr) {
	for (auto itr = writer.begin(); itr != writer.end(); ++itr) {
		if (nl) {
			printf("% 3d: 0x0%08X\n", i, *itr);
		} else {
			printf("0x0%08X, ", *itr);
		}
		fflush(stdout);
		++i;
	}
	if (!nl) {
		printf("\n");
	}
}

// Special all 0's
void AddType0(
    std::vector<std::unique_ptr<ConfigurationPacket<Spartan6::ConfRegType>>>&
        packets) {
	// InitWithWords doesn't like type 0
	/*
	static std::vector<uint32_t> words{0x00000000};
	absl::Span<uint32_t> word_span(words);
	auto packet =
	ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords(word_span);
	packets.push_back(*(packet.second));
	*/
	static std::vector<uint32_t> words{};
	absl::Span<uint32_t> word_span(words);
	// CRC is config value 0
	packets.emplace_back(new ConfigurationPacket<Spartan6::ConfRegType>(
	    0, ConfigurationPacket<Spartan6::ConfRegType>::NOP,
	    Spartan6::ConfRegType::CRC, word_span));
}

void AddType1(
    std::vector<std::unique_ptr<ConfigurationPacket<Spartan6::ConfRegType>>>&
        packets) {
	static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 2), 0xAA, 0xBB};
	absl::Span<uint32_t> word_span(words);
	auto packet = ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords(
	    word_span);
	packets.emplace_back(
	    new ConfigurationPacket<Spartan6::ConfRegType>(*(packet.second)));
}

// Empty
void AddType1E(
    std::vector<std::unique_ptr<ConfigurationPacket<Spartan6::ConfRegType>>>&
        packets) {
	static std::vector<uint32_t> words{MakeType1(0x2, 0x3, 0)};
	absl::Span<uint32_t> word_span(words);
	auto packet = ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords(
	    word_span);
	packets.emplace_back(
	    new ConfigurationPacket<Spartan6::ConfRegType>(*(packet.second)));
}

void AddType2(Spartan6::ConfigurationPackage& packets) {
	// Type 2 packet with data
	{
		static std::vector<uint32_t> words;
		words = MakeType2(0x02, 0x3, 12);
		std::vector<uint32_t> payload{1, 2, 3, 4,  5,  6,
		                              7, 8, 9, 10, 11, 12};
		words.insert(words.end(), payload.begin(), payload.end());
		std::cout << words.size();
		absl::Span<uint32_t> word_span(words);
		auto packet =
		    ConfigurationPacket<Spartan6::ConfRegType>::InitWithWords(
		        word_span);
		packets.emplace_back(
		    new ConfigurationPacket<Spartan6::ConfRegType>(
		        *(packet.second)));
	}
}

// Empty packets should produce just the header
TEST(BitstreamWriterTest, WriteHeader) {
	std::vector<std::unique_ptr<ConfigurationPacket<Spartan6::ConfRegType>>>
	    packets;

	BitstreamWriter<Spartan6> writer(packets);
	std::vector<uint32_t> words(writer.begin(), writer.end());

	// Per UG380 pg 78: Bus Width Auto Detection
	std::vector<uint32_t> ref_header{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
	                                 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
	                                 0xAA99, 0x5566};
	EXPECT_EQ(words, ref_header);

	// dump_packets(writer);
}

TEST(BitstreamWriterTest, WriteType0) {
	std::vector<std::unique_ptr<ConfigurationPacket<Spartan6::ConfRegType>>>
	    packets;
	AddType0(packets);
	BitstreamWriter<Spartan6> writer(packets);
	// dump_packets(writer, false);
	std::vector<uint32_t> words(writer.begin(), writer.end());
	std::vector<uint32_t> ref{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
	                          0xFFFF, 0xFFFF, 0xFFFF, 0xAA99, 0x5566,
	                          // Type 0
	                          0x0000};
	EXPECT_EQ(words, ref);
}

TEST(BitstreamWriterTest, WriteType1) {
	Spartan6::ConfigurationPackage packets;
	AddType1(packets);
	BitstreamWriter<Spartan6> writer(packets);
	// dump_packets(writer, false);
	std::vector<uint32_t> words(writer.begin(), writer.end());
	std::vector<uint32_t> ref{// Bus width + sync
	                          0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
	                          0xFFFF, 0xFFFF, 0xFFFF, 0xAA99, 0x5566,
	                          // Type 1
	                          0x3062, 0x00AA, 0x00BB};
	EXPECT_EQ(words, ref);
}

TEST(BitstreamWriterTest, WriteType2) {
	Spartan6::ConfigurationPackage packets;
	AddType2(packets);
	BitstreamWriter<Spartan6> writer(packets);
	// dump_packets(writer, false);
	std::vector<uint32_t> words(writer.begin(), writer.end());
	std::vector<uint32_t> ref{
	    // Bus width + sync
	    0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
	    0xAA99, 0x5566, 0x5060, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005,
	    0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C};
	EXPECT_EQ(words, ref);
}

TEST(BitstreamWriterTest, WriteMulti) {
	Spartan6::ConfigurationPackage packets;
	AddType1(packets);
	AddType1E(packets);
	AddType2(packets);
	AddType1E(packets);
	BitstreamWriter<Spartan6> writer(packets);
	// dump_packets(writer, false);
	std::vector<uint32_t> words(writer.begin(), writer.end());
	std::vector<uint32_t> ref{// Bus width + sync
	                          0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
	                          0xFFFF, 0xFFFF, 0xFFFF, 0xAA99, 0x5566,
	                          // Type1
	                          0x3062, 0x00AA, 0x00BB,
	                          // Type1
	                          0x3060,
	                          // Type 1 + type 2 header
	                          0x5060, 0x0001, 0x0002, 0x0003, 0x0004,
	                          0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
	                          0x000A, 0x000B, 0x000C,
	                          // Type 1
	                          0x3060};
	EXPECT_EQ(words, ref);
}
