#include <memory>
#include <getopt.h>
#include <iostream>
#include <sstream>

#include "QR.hpp"

#define UNUSED(var) (void) var;

constexpr const char* VERSION = "1.0.0";

void printHelp() {
	std::string helpText = R"EOF(
(C) 2023, MikO <miko@massivedynamic.eu>
– a tool for generating QR codes –
Released under MIT license.

Usage:
    -f --format    output file format. can be one of "cli, png, svg"
    -h --help      show this help
    -i --input     take data from this argument instead of stdin
    -o --output    output file name
    -s --size      desired output file size in pixels
    -t --type      output QR code type. can be one of "small, medium, large"
	)EOF";
	std::cout << "qr " << VERSION;
	std::cout << helpText << std::endl;
}

int main(int argc, char* argv[]) {
	if (argc < 1) {
		printHelp();
		exit(1);
	}
	const option options[] = {
		{"help", no_argument, nullptr, 'h'},
		{"input", required_argument, nullptr, 'i'},
		{"output", required_argument, nullptr, 'o'},
		{"size", required_argument, nullptr, 's'},
		{"type", required_argument, nullptr, 't'},
		{"format", required_argument, nullptr, 'f'},
		{nullptr}
	};

	std::string outputFile;
	size_t segmentSize            = 0;
	massivedynamic::Type type     = massivedynamic::Type::MEDIUM;
	massivedynamic::Format format = massivedynamic::Format::CONSOLE;
	bool fromStdin                = true;
	std::string paramData         = "";

	for(;;) {
		int index  = -1;
		int result = getopt_long(argc, argv, "ho:s:t:f:i:", options, &index);
		
		if (result == -1)
			break;
		const option* opt = &options[index];
		UNUSED(opt);
		switch(result) {
			case 'o': {
				if (strlen(optarg) > 0)
					outputFile = optarg;
				break;
			}
			case 's': {
				segmentSize = std::atoi(optarg);
				break;
			}
			case 't': {
				std::string value = optarg;
				if (value == "small")
					type = massivedynamic::Type::SMALL;
				else if (value == "medium")
					type = massivedynamic::Type::MEDIUM;
				else if (value == "large")
					type = massivedynamic::Type::LARGE;
				else {
					printHelp();
					return 1;
				}
				break;
			}
			case 'f': {
				std::string value = optarg;
				if (value == "cli")
					format = massivedynamic::Format::CONSOLE;
				else if (value == "svg")
					format = massivedynamic::Format::SVG;
				else if (value == "png")
					format = massivedynamic::Format::PNG;
				else {
					printHelp();
					return 1;
				}
				break;
			}
			case 'i': {
				fromStdin = false;
				paramData = optarg;
				break;
			}
			case 'h':
			default:
				printHelp();
				return 0;
		}
	}

 	std::string line;
	std::stringstream data;
 
	if (fromStdin) {
		if (!isatty(fileno(stdin))) {
			while (std::getline(std::cin, line)) {
				if (std::cin.eof() || line.empty()) {
					std::cin.clear();
					break;
				}
				data << line;
			}
		}

		if (isatty(fileno(stdin)) || data.str().empty()) {
			std::cerr << "ERROR: no data from stdinput." << std::endl;
			exit(1);
		}
	} else
		data << paramData;

	if (data.str().empty()) {
		std::cerr << "ERROR: input data is empty" << std::endl;
		exit(1);
	}

	if ((format == massivedynamic::Format::PNG || format == massivedynamic::Format::SVG) && outputFile.empty()) {
		std::cerr << "ERROR: output file name (-o, --output) can not be empty" << std::endl;
		return 1;
	}

	std::unique_ptr<massivedynamic::QR> qr = std::make_unique<massivedynamic::QR>(data.str(), outputFile, segmentSize, type, format);

	return 0;
}