#!/usr/bin/env php
<?php
PHP_SAPI == 'cli' or die("Please run this script using the cli sapi");

require_once __DIR__ . '/../src/autoload.php';

use phpweb\News\Entry;

$imageRestriction = [
	'width' => 400,
	'height' => 250
];

// Create an entry!
if (!file_exists(Entry::ARCHIVE_FILE_ABS)) {
	fwrite(STDERR, "Can't find " . Entry::ARCHIVE_FILE_REL . ", are you sure you are in phpweb/?\n");
	exit(1);
}

if ($_SERVER['argc'] > 1) {
	// getopt based non-interactive mode
	$entry = parseOptions();
} else {
	// Classic interactive prompts
	$entry = getEntry();
}

$entry->save()->updateArchiveXML();

fwrite(STDOUT, "File saved.\nPlease git diff " . Entry::ARCHIVE_FILE_REL . " and sanity-check the changes before committing\n");
fwrite(STDOUT, "NOTE: Remember to git add " . Entry::ARCHIVE_ENTRIES_REL . $entry->getId() . ".xml !!\n");

// Implementation functions

function getEntry(): Entry {
	$entry = new Entry;
	$entry->setTitle(getTitle());
	$entry->setCategories(selectCategories());
	if ($entry->isConference()) {
		$entry->setConfTime(getConfTime());
	}

	$image = getImage();
	$entry->setImage($image['path'] ?? '', $image['title'] ?? '', $image['link'] ?? '');

	$entry->setContent(getContent());

	return $entry;
}

function getTitle(): string {
	do {
		fwrite(STDOUT, "Please type in the title: ");
		$title = rtrim(fgets(STDIN));
	} while(strlen($title)<3);

	return $title;
}

function selectCategories(): array { for(;;) {
	$ids = array_keys(Entry::CATEGORIES);

	fwrite(STDOUT, "Categories:\n");
	foreach($ids as $n => $id) {
		fprintf(STDOUT, "\t%d: %-11s\t [%s]\n", $n, Entry::CATEGORIES[$id], $id);
	}
	fwrite(STDOUT, "Please select appropriate categories, seperated with space: ");

	// Filter to 0..n-1, then map to short names.
	$cat = array_map(
		function ($c) use ($ids) {
			return $ids[$c];
		},
		array_filter(
			explode(" ", rtrim(fgets(STDIN))),
			function ($c) {
				return is_numeric($c) && ($c >= 0) && ($c < count(Entry::CATEGORIES));
			})
	);

	// Special case, we don't allow items in both 'cfp' and 'conferences'.
	if (count(array_intersect($cat, ['cfp', 'conferences'])) >= 2) {
		fwrite(STDERR, "Pick either a CfP OR a conference\n");
		continue;
	}

	if (count($cat) == 0) {
		fwrite(STDERR, "You have to pick at least one category\n");
		continue;
	}

	return $cat;
}}

function getConfTime(): int { for(;;) {
	fwrite(STDOUT, "When does the conference start/cfp end? (strtotime() compatible syntax): ");

	$t = strtotime(fgets(STDIN));
	if (!$t) {
		fwrite(STDERR, "I told you I would run it through strtotime()!\n");
		continue;
	}

	return $t;
}}

function getImage(): ?array {
	global $imageRestriction;

	fwrite(STDOUT, "Will a picture be accompanying this entry?(y/N) ");
	$yn = fgets(STDIN);


	if (strtoupper($yn[0]) !== "Y") {
		return NULL;
	}

	for ($isValidImage = false; !$isValidImage;) {
		fwrite(STDOUT, "Enter the image name (note: the image has to exist in './images/news'): ");
		$path = basename(rtrim(fgets(STDIN)));

		if (true === file_exists(Entry::PHPWEB . "/images/news/$path")) {
			$isValidImage = true;

			if (extension_loaded('gd')) {
				break;
			}

			$imageSizes = getimagesize("./images/news/$path");

			if (($imageSizes[0] > $imageRestriction['width']) || ($imageSizes[1] > $imageRestriction['height'])) {
				fwrite(STDOUT, "Provided image has a higher size than recommended (" . implode(' by ', $imageRestriction) . "). Continue with this image?(y/N) ");
				$ynImg = fgets(STDIN);
				if (strtoupper($ynImg[0]) !== "Y") {
					$isValidImage = false;
				}
			}
		}
	}

	fwrite(STDOUT, "Image title: ");
	$title = rtrim(fgets(STDIN));

	fwrite(STDOUT, "Link (when clicked on the image): ");
	$via = rtrim(fgets(STDIN));

	return [
		'title' => $title,
		'link' => $via,
		'path' => $path,
	];
}

function getContent(): string {
	fwrite(STDOUT, "And at last; paste/write your news item here.\nTo end it, hit <enter>.<enter>\n");
	$news = "\n";
	while(($line = rtrim(fgets(STDIN))) != ".") {
		$news .= "     $line\n";
	}

	return $news;
}

function parseOptions(): Entry {
	$opts = getopt('h', [
		'help',
		'title:',
		'category:',
		'conf-time:',
		'image-path:',
		'image-title:',
		'image-link:',
		'content:',
		'content-file:',
	]);
	if (isset($opts['h']) || isset($opts['help'])) {
		echo "Usage: {$_SERVER['argv'][0]} --title 'Name of event' --category cfp ( --content 'text' | --content-file '-') [...options]\n\n";
		echo "  --title 'value'        The title of the entry (required)\n";
		echo "  --category 'value'     'frontpage', 'release', 'cfp', or 'conference' (required; may repeat)\n";
		echo "  --conf-time 'value'    When the event will be occurign (cfp and conference categories only)\n";
		echo "  --content 'value'      Text content for the entry, may include XHTML\n";
		echo "  --content-file 'value' Name of file to load content from, may not be specified with --content\n";
		echo "  --image-path 'value'   Basename of image file in " . Entry::IMAGE_PATH_REL . "\n";
		echo "  --image-title 'value'  Title for the image provided\n";
		echo "  --image-link 'value'   URI to direct to when clicking the image\n";
		exit(0);
	}

	$entry = new Entry;
	if (!isset($opts['title'])) {
		fwrite(STDERR, "--title required\n");
		exit(1);
	}
	$entry->setTitle($opts['title']);

	if (empty($opts['category'])) {
		fwrite(STDERR, "--category required\n");
		exit(1);
	}
	if (is_string($opts['category'])) {
		$opts['category'] = [ $opts['category'] ];
	}
	foreach ($opts['category'] as $cat) {
		$entry->addCategory($cat);
	}
	if ($entry->isConference()) {
		if (empty($opts['conf-time'])) {
			fwrite(STDERR, "--conf-time required for conferences\n");
			exit(1);
		}
		$t = strtotime($opts['conf-time']);
		if (!is_int($t)) {
			fwrite(STDERR, "Error parsing --conf-time\n");
			exit(1);
		}
		$entry->setConfTime($t);
	} elseif (!empty($opts['conf-time'])) {
		fwrite(STDERR, "--conf-time not allowed with non-conference events\n");
		exit(1);
	}

	$entry->setImage($opts['image-path'] ?? '', $opts['image-title'] ?? '', $opts['image-link'] ?? '');

	if (isset($opts['content'])) {
		if (isset($opts['content-file'])) {
			fwrite(STDERR, "--content and --content-file may not be specified together\n");
			exit(1);
		}
		$entry->setContent($opts['content']);
	} elseif (isset($opts['content-file'])) {
		if ($opts['content-file'] === '-') {
			$entry->setContent(stream_get_contents(STDIN));
		} else {
			$entry->setContent(file_get_contents($opts['content-file']));
		}
	} else {
		fwrite(STDERR, "--content or --content-file required\n");
		exit(1);
	}

	return $entry;
}
