<?php

namespace Planaday\Platform\WordpressConfig\ShortcodeLinks;

use Planaday\Html\Parsers\ParseFailedException;
use Planaday\Html\Parsers\StdDOMParser;
use Planaday\Html\Tags\Course\Button\CourseButton;
use Planaday\Html\Tags\Course\CourseBookingForm\CourseBookingForm;
use Planaday\Html\Tags\Course\CourseCalendarShortcode\CourseCalendarShortcode;
use Planaday\Html\Tags\Course\CourseListShortcode\CourseListShortcode;
use Planaday\Html\Tags\Course\CourseSearchShortcode\CourseSearchShortcode;
use Planaday\Html\Tags\Course\CourseShortcode\CourseShortcode;
use Planaday\Html\Tags\Course\Dates\CourseDates;
use Planaday\Html\Tags\Course\Id\CourseId;
use Planaday\Html\Tags\Course\Name\CourseName;
use Planaday\Html\Tags\Course\NotFoundRedirect\NotFoundRedirect;
use Planaday\Html\Tags\Course\Price\CoursePrice;
use Planaday\Html\Tags\Course\PriceRemark\CoursePriceRemark;
use Planaday\Html\Tags\Tag;
use Planaday\Utility\Debug\Log\Logging;
use Planaday\Utility\Debug\PluginFeatureTimer;
use Planaday\Utility\DependencyInjection\Container;
use Planaday\Utility\DependencyInjection\InjectionImpossibleException;
use Planaday\Utility\GeneralTermEnum;
use Planaday\Utility\PluginData;

class CourseShortcodes{
	use Logging;

	const LIST_TEMPLATE = 'courseList';
	const BLOCK_TEMPLATE = 'courseBlock';
	const BLOCK2_TEMPLATE = 'courseBlock2';
	const TABLE_TEMPLATE = 'courseTable';
	const COURSE_OVERVIEW_SHORTCODE = GeneralTermEnum::COURSE_DETAILS_SHORTCODE;
	const COURSE_SEARCH_SHORTCODE = '-courseSearch';

	public function __construct(
		protected PluginData $pluginData,
		protected Container $registry,
		protected PluginFeatureTimer $timer
	) {
	}

	public function addShortcodes() :void{
		add_shortcode($this->pluginData->getShortPrefix() . self::COURSE_OVERVIEW_SHORTCODE, [$this, 'course']); // [padc-course]
		add_shortcode($this->pluginData->getShortPrefix() . '-courseListList', [$this, 'courseList']); // [padc-courseListList start=now end=+2months]
		add_shortcode($this->pluginData->getShortPrefix() . '-courseListTable', [$this, 'courseTable']); // [padc-courseListTable start=now end=+2months]
		add_shortcode($this->pluginData->getShortPrefix() . '-courseListBlock', [$this, 'courseBlock']); // [padc-courseListBlock start=now end=+2months]
		add_shortcode($this->pluginData->getShortPrefix() . '-courseListBlock2', [$this, 'courseBlock2']); // [padc-courseListBlock2 start=now end=+2months]
		add_shortcode($this->pluginData->getShortPrefix() . self::COURSE_SEARCH_SHORTCODE, [$this, 'courseSearch']); // [padc-courseSearch]
		add_shortcode($this->pluginData->getShortPrefix() . '-courseCalendar', [$this, 'courseCalendar']); // [padc-courseCalendar start=now end=+2months]
		add_shortcode($this->pluginData->getShortPrefix() . GeneralTermEnum::BOOKING_FORM_SHORTCODE, [$this, 'bookingForm']); // [padc-booking-form]
		add_shortcode($this->pluginData->getShortPrefix() . '-name', [$this, 'courseName']); // [padc-name id=3]
		add_shortcode($this->pluginData->getShortPrefix() . '-dates', [$this, 'courseDates']); // [padc-dates id=3]
		add_shortcode($this->pluginData->getShortPrefix() . '-dates-locations', [$this, 'courseDatesWithLocation']); // [padc-dates-locations id=3]
		add_shortcode($this->pluginData->getShortPrefix() . '-price', [$this, 'coursePrice']); // [padc-price id=3]
		add_shortcode($this->pluginData->getShortPrefix() . '-price-remark', [$this, 'coursePriceRemark']); // [padc-price-remark id=3]
		add_shortcode($this->pluginData->getShortPrefix() . '-button', [$this, 'courseButton']); // [padc-button id=3]
		add_shortcode($this->pluginData->getShortPrefix() . '-courseId', [$this, 'courseId']); // [padc-courseId]
		add_shortcode($this->pluginData->getShortPrefix() . '-courselistlist', [$this, 'courseList']); // [padc-courseListList start=now end=+2months]
		add_shortcode($this->pluginData->getShortPrefix() . '-courselisttable', [$this, 'courseTable']); // [padc-courseListTable start=now end=+2months]
		add_shortcode($this->pluginData->getShortPrefix() . '-courselistblock', [$this, 'courseBlock']); // [padc-courseListBlock start=now end=+2months]
		add_shortcode($this->pluginData->getShortPrefix() . '-courselistblock2', [$this, 'courseBlock2']); // [padc-courseListBlock2 start=now end=+2months]
		add_shortcode($this->pluginData->getShortPrefix() . strtolower(self::COURSE_SEARCH_SHORTCODE), [$this, 'courseSearch']); // [padc-courseSearch]
		add_shortcode($this->pluginData->getShortPrefix() . '-coursecalendar', [$this, 'courseCalendar']); // [padc-courseCalendar start=now end=+2months]
		add_shortcode($this->pluginData->getShortPrefix() . strtolower(GeneralTermEnum::BOOKING_FORM_SHORTCODE), [$this, 'bookingForm']); // [padc-booking-form]
		add_shortcode($this->pluginData->getShortPrefix() . '-bookingform', [$this, 'bookingForm']); // [padc-bookingform]
		add_shortcode($this->pluginData->getShortPrefix() . '-courseid', [$this, 'courseId']); // [padc-courseId]
		add_shortcode($this->pluginData->getShortPrefix() . '-course-not-found-redirect', [$this, 'notFoundRedirect']);
		add_shortcode($this->pluginData->getShortPrefix() . '-test-new', [$this, 'testNew']); // [padc-test-new]
		add_shortcode($this->pluginData->getShortPrefix() . '-test-personal', [$this, 'testPersonal']); // [padc-test-personal]
	}

	public function testNew(): string {
		try{
			return $this->registry->getInstance(StdDOMParser::class)->parse(
				"<pad-testing-node_control_test pad-template='XMLFragmentTest'/>"
			);
		} catch (ParseFailedException|InjectionImpossibleException ) {
			return "";
		}
	}

	public function testPersonal(): string {
		try{
			return $this->registry->getInstance(StdDOMParser::class)->parse(
				"<pad-testing-personal_testing pad-template='test'/>"
			);
		} catch (ParseFailedException|InjectionImpossibleException ) {
			return "";
		}
	}

	public function course( $attributes ): string {
		return $this->loadShortcode('course', CourseShortcode::TAG, $attributes);
	}

	public function courseList( $attributes ): string {
		return $this->getCourseListType($attributes, self::LIST_TEMPLATE);
	}

	public function courseTable( $attributes ): string {
		return $this->getCourseListType($attributes, self::TABLE_TEMPLATE);
	}

	public function courseBlock( $attributes ): string {
		return $this->getCourseListType($attributes, self::BLOCK_TEMPLATE);
	}

	public function courseBlock2( $attributes ): string {
		return $this->getCourseListType($attributes, self::BLOCK2_TEMPLATE);
	}

	private function getCourseListType($attributes, $defaultTemplate): string {
		$attributes[ Tag::TEMPLATE_ATTRIBUTE] = $attributes[ Tag::TEMPLATE_ATTRIBUTE] ?? $defaultTemplate;
		return $this->loadShortcode('course list with ' . $attributes[ Tag::TEMPLATE_ATTRIBUTE] . ' as the template', CourseListShortcode::TAG, $attributes);
	}

	public function courseSearch( $attributes ): string {
		return $this->loadShortcode('course search', CourseSearchShortcode::TAG, $attributes);
	}

	public function courseCalendar( $attributes ):string {
		return $this->loadShortcode('course calendar', CourseCalendarShortcode::TAG, $attributes);
	}

	public function bookingForm( $attributes ):string {
		return $this->loadShortcode('booking form', CourseBookingForm::TAG, $attributes);
	}

	public function courseName( $attributes ):string {
		$attributes[CourseName::ID_ATTRIBUTE] = $attributes['id'];
		return $this->loadShortcode('course name', CourseName::TAG, $attributes);
	}

	public function courseDates( $attributes ):string {
		$attributes[CourseDates::SHOW_LOCATION_ATTRIBUTE] = false;
		$attributes[CourseDates::ID_ATTRIBUTE] = $attributes['id'];
		return $this->loadShortcode('course dates', CourseDates::TAG, $attributes);
	}

	public function courseDatesWithLocation( $attributes ):string {
		$attributes[CourseDates::SHOW_LOCATION_ATTRIBUTE] = true;
		$attributes[CourseDates::ID_ATTRIBUTE] = $attributes['id'];
		return $this->loadShortcode('course dates with location', CourseDates::TAG, $attributes);
	}

	public function coursePrice( $attributes ):string {
		$attributes[CoursePrice::ID_ATTRIBUTE] = $attributes['id'];
		return $this->loadShortcode('course price', CoursePrice::TAG, $attributes);
	}

	public function coursePriceRemark( $attributes ):string {
		$attributes[CoursePriceRemark::ID_ATTRIBUTE] = $attributes['id'];
		return $this->loadShortcode('course price remark', CoursePriceRemark::TAG, $attributes);
	}

	public function courseButton( $attributes ):string {
		$attributes[CourseButton::ID_ATTRIBUTE] = $attributes['id'];
		return $this->loadShortcode('course button', CourseButton::TAG, $attributes);
	}

	public function courseId( $attributes ):string {
		return $this->loadShortcode('course id', CourseId::TAG, $attributes);
	}

	public function notFoundRedirect( $attributes ):string {
		return $this->loadShortcode('course not found redirect', NotFoundRedirect::TAG, $attributes);
	}

	private function loadShortcode($shortcodeName, $shortcode, $attributes ): string {
		try {
			$stop = $this->timer->start("shortcode " . $shortcodeName);
			$render = $this->registry->getInstance(ShortcodeToTagConverter::class)->getShortcode($shortcodeName, $shortcode, $attributes);
			$stop();
			return $render;
		}
		catch (InjectionImpossibleException $e) {
			$this->logError( "failed to create ShortcodeToTagConverter, error: " . $e->getMessage() );
			return '<!-- dependency injection failed -->';
		}
	}
}