#include <prjxray/xilinx/configuration_packet.h>

#include <iomanip>
#include <iostream>
#include <ostream>

#include <prjxray/bit_ops.h>

namespace prjxray {
namespace xilinx {

template <>
std::pair<absl::Span<uint32_t>,
          absl::optional<ConfigurationPacket<Spartan6ConfigurationRegister>>>
ConfigurationPacket<Spartan6ConfigurationRegister>::InitWithWords(
    absl::Span<uint32_t> words,
    const ConfigurationPacket<Spartan6ConfigurationRegister>* previous_packet) {
	using ConfigurationRegister = Spartan6ConfigurationRegister;
	// Need at least one 32-bit word to have a valid packet header.
	if (words.size() < 1)
		return {words, {}};

	uint32_t header_type = bit_field_get(words[0], 15, 13);
	switch (header_type) {
		case NONE:
			// Type 0 is emitted at the end of a configuration row
			// when BITSTREAM.GENERAL.DEBUGBITSTREAM is set to YES.
			// These seem to be padding that are interepreted as
			// NOPs.  Since Type 0 packets don't exist according to
			// UG470 and they seem to be zero-filled, just consume
			// the bytes without generating a packet.
			return {words.subspan(1),
			        {{header_type,
			          Opcode::NOP,
			          ConfigurationRegister::CRC,
			          {}}}};
		case TYPE1: {
			Opcode opcode = static_cast<Opcode>(
			    bit_field_get(words[0], 12, 11));
			ConfigurationRegister address =
			    static_cast<ConfigurationRegister>(
			        bit_field_get(words[0], 10, 5));
			uint32_t data_word_count =
			    bit_field_get(words[0], 4, 0);

			// If the full packet has not been received, return as
			// though no valid packet was found.
			if (data_word_count > words.size() - 1) {
				return {words, {}};
			}

			return {words.subspan(data_word_count + 1),
			        {{header_type, opcode, address,
			          words.subspan(1, data_word_count)}}};
		}
		case TYPE2: {
			absl::optional<ConfigurationPacket> packet;
			Opcode opcode = static_cast<Opcode>(
			    bit_field_get(words[0], 12, 11));
			ConfigurationRegister address =
			    static_cast<ConfigurationRegister>(
			        bit_field_get(words[0], 10, 5));
			// Type 2 packets according to UG380 consist of
			// a header word followed by 2 WCD (Word Count Data)
			// words
			uint32_t data_word_count = (words[1] << 16) | words[2];

			// If the full packet has not been received, return as
			// though no valid packet was found.
			if (data_word_count > words.size() - 1) {
				return {words, {}};
			}

			// Create a packet that contains as many data words
			// as specified in the WCD packets, but omit them
			// in the configuration packet along with the header
			// FIXME Figure out why we need the extra 2 words
			packet = ConfigurationPacket(
			    header_type, opcode, address,
			    words.subspan(3, data_word_count + 2));

			return {words.subspan(data_word_count + 3), packet};
		}
		default:
			return {{}, {}};
	}
}

template <>
std::pair<absl::Span<uint32_t>,
          absl::optional<ConfigurationPacket<Series7ConfigurationRegister>>>
ConfigurationPacket<Series7ConfigurationRegister>::InitWithWords(
    absl::Span<uint32_t> words,
    const ConfigurationPacket<Series7ConfigurationRegister>* previous_packet) {
	using ConfigurationRegister = Series7ConfigurationRegister;
	// Need at least one 32-bit word to have a valid packet header.
	if (words.size() < 1)
		return {words, {}};

	uint32_t header_type = bit_field_get(words[0], 31, 29);
	switch (header_type) {
		case NONE:
			// Type 0 is emitted at the end of a configuration row
			// when BITSTREAM.GENERAL.DEBUGBITSTREAM is set to YES.
			// These seem to be padding that are interepreted as
			// NOPs.  Since Type 0 packets don't exist according to
			// UG470 and they seem to be zero-filled, just consume
			// the bytes without generating a packet.
			return {words.subspan(1),
			        {{header_type,
			          Opcode::NOP,
			          ConfigurationRegister::CRC,
			          {}}}};
		case TYPE1: {
			Opcode opcode = static_cast<Opcode>(
			    bit_field_get(words[0], 28, 27));
			ConfigurationRegister address =
			    static_cast<ConfigurationRegister>(
			        bit_field_get(words[0], 26, 13));
			uint32_t data_word_count =
			    bit_field_get(words[0], 10, 0);

			// If the full packet has not been received, return as
			// though no valid packet was found.
			if (data_word_count > words.size() - 1) {
				return {words, {}};
			}

			return {words.subspan(data_word_count + 1),
			        {{header_type, opcode, address,
			          words.subspan(1, data_word_count)}}};
		}
		case TYPE2: {
			absl::optional<ConfigurationPacket> packet;
			Opcode opcode = static_cast<Opcode>(
			    bit_field_get(words[0], 28, 27));
			uint32_t data_word_count =
			    bit_field_get(words[0], 26, 0);

			// If the full packet has not been received, return as
			// though no valid packet was found.
			if (data_word_count > words.size() - 1) {
				return {words, {}};
			}

			if (previous_packet) {
				packet = ConfigurationPacket(
				    header_type, opcode,
				    previous_packet->address(),
				    words.subspan(1, data_word_count));
			}

			return {words.subspan(data_word_count + 1), packet};
		}
		default:
			return {{}, {}};
	}
}

template <class ConfigRegType>
std::ostream& operator<<(std::ostream& o,
                         const ConfigurationPacket<ConfigRegType>& packet) {
	if (packet.header_type() == 0x0) {
		return o << "[Zero-pad]" << std::endl;
	}

	switch (packet.opcode()) {
		case ConfigurationPacket<ConfigRegType>::Opcode::NOP:
			o << "[NOP]" << std::endl;
			break;
		case ConfigurationPacket<ConfigRegType>::Opcode::Read:
			o << "[Read Type=";
			o << packet.header_type();
			o << " Address=";
			o << std::setw(2) << std::hex;
			o << static_cast<int>(packet.address());
			o << " Length=";
			o << std::setw(10) << std::dec << packet.data().size();
			o << " Reg=\"" << packet.address() << "\"";
			o << "]" << std::endl;
			break;
		case ConfigurationPacket<ConfigRegType>::Opcode::Write:
			o << "[Write Type=";
			o << packet.header_type();
			o << " Address=";
			o << std::setw(2) << std::hex;
			o << static_cast<int>(packet.address());
			o << " Length=";
			o << std::setw(10) << std::dec << packet.data().size();
			o << " Reg=\"" << packet.address() << "\"";
			o << "]" << std::endl;
			o << "Data in hex:" << std::endl;

			for (size_t ii = 0; ii < packet.data().size(); ++ii) {
				o << std::setw(8) << std::hex;
				o << packet.data()[ii] << " ";

				if ((ii + 1) % 4 == 0) {
					o << std::endl;
				}
			}
			if (packet.data().size() % 4 != 0) {
				o << std::endl;
			}
			break;
		default:
			o << "[Invalid Opcode]" << std::endl;
	}

	return o;
}

template std::ostream& operator<<(
    std::ostream&,
    const ConfigurationPacket<Spartan6ConfigurationRegister>&);
template std::ostream& operator<<(
    std::ostream&,
    const ConfigurationPacket<Series7ConfigurationRegister>&);
}  // namespace xilinx
}  // namespace prjxray
