#include <algorithm>
#include <iostream>
#include <typeinfo>

#include <absl/strings/str_cat.h>
#include <absl/types/span.h>
#include <gflags/gflags.h>
#include <prjxray/memory_mapped_file.h>
#include <prjxray/xilinx/architectures.h>
#include <prjxray/xilinx/bitstream_reader.h>

namespace xilinx = prjxray::xilinx;

struct Action {
	std::string name;
	std::function<int(int, char* [])> handler;
};

struct ConfigPacketsLister {
	ConfigPacketsLister(const absl::Span<uint8_t>& bytes) : bytes_(bytes) {}

	const absl::Span<uint8_t>& bytes_;

	template <typename T>
	int operator()(T& arg) {
		using ArchType = std::decay_t<decltype(arg)>;
		auto reader =
		    xilinx::BitstreamReader<ArchType>::InitWithBytes(bytes_);
		if (!reader) {
			std::cerr << "Input doesn't look like a bitstream"
			          << std::endl;
			return 1;
		}

		for (auto packet : *reader) {
			std::cout << packet;
		}

		return 0;
	}
};

int ListConfigPackets(int argc, char* argv[]) {
	std::string architecture("Series7");
	if (argc < 1) {
		std::cerr << "ERROR: no input specified" << std::endl;
		std::cerr << "Usage: " << argv[0]
		          << "list_config_packets <bit_file>" << std::endl;
		return 1;
	}
	if (argc == 2) {
		architecture = argv[1];
	}

	auto in_file_name = argv[0];
	auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
	if (!in_file) {
		std::cerr << "Unable to open bit file: " << in_file_name
		          << std::endl;
		return 1;
	}
	auto in_bytes = absl::Span<uint8_t>(
	    static_cast<uint8_t*>(in_file->data()), in_file->size());
	xilinx::Architecture::Container arch_container =
	    xilinx::ArchitectureFactory::create_architecture(architecture);
	return absl::visit(ConfigPacketsLister(in_bytes), arch_container);
}

struct DebugFrameAddressesDumper {
	DebugFrameAddressesDumper(const absl::Span<uint8_t>& bytes)
	    : bytes_(bytes) {}

	const absl::Span<uint8_t>& bytes_;

	template <typename T>
	int operator()(T& arg) {
		using ArchType = std::decay_t<decltype(arg)>;
		auto reader =
		    xilinx::BitstreamReader<ArchType>::InitWithBytes(bytes_);
		if (!reader) {
			std::cerr << "Input doesn't look like a bitstream"
			          << std::endl;
			return 1;
		}

		bool found_one_lout = false;
		for (auto packet : *reader) {
			if ((packet.opcode() !=
			     xilinx::ConfigurationPacket<
			         typename ArchType::ConfRegType>::Opcode::
			         Write) ||
			    (packet.address() != ArchType::ConfRegType::LOUT)) {
				continue;
			}

			if (packet.data().size() != 1) {
				std::cerr << "Write to FAR with word_count != 1"
				          << std::endl;
				continue;
			}

			found_one_lout = true;
			std::cout << std::dec << packet.data()[0] << std::endl;
		}

		if (!found_one_lout) {
			std::cerr
			    << "No LOUT writes found.  Was "
			    << "BITSTREAM.GENERAL.DEBUGBITSTREAM set to YES?"
			    << std::endl;
			return 1;
		}

		return 0;
	}
};

int DumpDebugbitstreamFrameAddresses(int argc, char* argv[]) {
	std::string architecture("Series7");
	if (argc < 1) {
		std::cerr << "ERROR: no input specified" << std::endl;
		std::cerr << "Usage: " << argv[0]
		          << "dump_debugbitstream_frame_addresses <bit_file>"
		          << std::endl;
		return 1;
	}
	if (argc == 2) {
		architecture = argv[1];
	}

	auto in_file_name = argv[0];
	auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
	if (!in_file) {
		std::cerr << "Unable to open bit file: " << in_file_name
		          << std::endl;
		return 1;
	}

	auto in_bytes = absl::Span<uint8_t>(
	    static_cast<uint8_t*>(in_file->data()), in_file->size());
	xilinx::Architecture::Container arch_container =
	    xilinx::ArchitectureFactory::create_architecture(architecture);
	return absl::visit(DebugFrameAddressesDumper(in_bytes), arch_container);
}

struct DeviceIdGetter {
	DeviceIdGetter(const absl::Span<uint8_t>& bytes) : bytes_(bytes) {}

	const absl::Span<uint8_t>& bytes_;

	template <typename T>
	int operator()(T& arg) {
		using ArchType = std::decay_t<decltype(arg)>;
		auto reader =
		    xilinx::BitstreamReader<ArchType>::InitWithBytes(bytes_);
		if (!reader) {
			std::cerr << "Input doesn't look like a bitstream"
			          << std::endl;
			return 1;
		}
		auto idcode_packet = std::find_if(
		    reader->begin(), reader->end(),
		    [](const xilinx::ConfigurationPacket<
		        typename ArchType::ConfRegType>& packet) {
			    return (packet.opcode() ==
			            xilinx::ConfigurationPacket<
			                typename ArchType::ConfRegType>::
			                Opcode::Write) &&
			           (packet.address() ==
			            ArchType::ConfRegType::IDCODE);
		    });
		if (idcode_packet != reader->end()) {
			if (std::is_same<ArchType, xilinx::Spartan6>::value) {
				if (idcode_packet->data().size() != 2) {
					std::cerr << "Write to IDCODE with "
					             "word_count != 2"
					          << std::endl;
					return 1;
				}
				std::cout << "0x" << std::hex
				          << ((idcode_packet->data()[0] << 16) |
				              idcode_packet->data()[1])
				          << std::endl;
			} else {
				if (idcode_packet->data().size() != 1) {
					std::cerr << "Write to IDCODE with "
					             "word_count != 1"
					          << std::endl;
					return 1;
				}
				std::cout << "0x" << std::hex
				          << idcode_packet->data()[0]
				          << std::endl;
			}
		}
		return 0;
	}
};

int GetDeviceId(int argc, char* argv[]) {
	std::string architecture("Series7");
	if (argc < 1) {
		std::cerr << "ERROR: no input specified" << std::endl;
		std::cerr << "Usage: " << argv[0]
		          << "get_device_id <bit_file> [<architecture>]"
		          << std::endl;
		return 1;
	}
	if (argc == 2) {
		architecture = argv[1];
	}

	auto in_file_name = argv[0];
	auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
	if (!in_file) {
		std::cerr << "Unable to open bit file: " << in_file_name
		          << std::endl;
		return 1;
	}
	auto in_bytes = absl::Span<uint8_t>(
	    static_cast<uint8_t*>(in_file->data()), in_file->size());

	xilinx::Architecture::Container arch_container =
	    xilinx::ArchitectureFactory::create_architecture(architecture);
	return absl::visit(DeviceIdGetter(in_bytes), arch_container);
}

int main(int argc, char* argv[]) {
	Action actions[] = {
	    {"list_config_packets", ListConfigPackets},
	    {"dump_debugbitstream_frame_addresses",
	     DumpDebugbitstreamFrameAddresses},
	    {"get_device_id", GetDeviceId},
	};

	gflags::SetUsageMessage(
	    absl::StrCat("Usage: ", argv[0], " [options] [bitfile]"));
	gflags::ParseCommandLineFlags(&argc, &argv, true);

	if (argc < 2) {
		std::cerr << "ERROR: no command specified" << std::endl;
		std::cerr << "Usage: " << argv[0]
		          << "<command> <command_options>" << std::endl;
		return 1;
	}

	auto requested_action_str = argv[1];
	auto requested_action = std::find_if(
	    std::begin(actions), std::end(actions),
	    [&](const Action& t) { return t.name == requested_action_str; });
	if (requested_action == std::end(actions)) {
		std::cerr << "Unknown action: " << requested_action_str
		          << std::endl;
		return 1;
	}

	return requested_action->handler(argc - 2, argv + 2);
}
