<?php declare(strict_types=1);
/**
 * JTL Plugin
 * Copyright (C) 2011 - 2020 Andreas Petermann
 *
 * PHP version 7.2+
 *
 * @copyright css-umsetzung
 * @author Andreas Petermann <info@css-umsetzung.de>
 * @package css_vatSelect
 * @license GNU
 * @version 1.00
 *
 */

namespace Plugin\css_vatSelect;

use JTL\Backend\Notification;
use JTL\Backend\NotificationEntry;
use JTL\Events\Dispatcher;
use JTL\Plugin\Bootstrapper;
use JTL\Shop;
use JTL\Router\Route;
use JTL\Minify\MinifyService;
use \JTL\Helpers\Tax;
use Plugin\css_vatSelect\src\cssPlugin\VatSelectCronJob;

class Bootstrap extends Bootstrapper {

	private $cssPlugin;
	private $_BootstrapVersion  = '3.0.0';
	public static $_CRON_JOB = 'GEO IP - MaxMind Aktualisierung';

	/**
	 * @inheritdoc
	 */
	public function boot(Dispatcher $dispatcher) {
		parent::boot($dispatcher);
		$plugin = $this->getPlugin();

		$dispatcher->listen('backend.notification', [$this, 'checkNotification']);

// cronjobs
		if(!empty(self::$_CRON_JOB)) {
			$dispatcher->listen(\JTL\Events\Event::GET_AVAILABLE_CRONJOBS, function (array $args) use ($plugin)	{
				if(self::getCssInstance($plugin)) {
					$this->availableCronjobType($args);
				}
			});

			$dispatcher->listen(\JTL\Events\Event::MAP_CRONJOB_TYPE, function (array $args) use ($plugin)	{
				if(self::getCssInstance($plugin)) {
					$this->mappingCronjobType($args);
				}
			});
		}

		if ((isset($_REQUEST['kPlugin']) && $plugin->getID() == (int)$_REQUEST['kPlugin'])) {
			self::getCssInstance($plugin);
		}

		// Frontend hooks

		$dispatcher->listen('shop.hook.' . \HOOK_JTL_PAGE_KUNDENDATEN_PLAUSI, function (array $args) use ($plugin) {
			if(self::getCssInstance($plugin)) {
				$this->cssPlugin->hookJtlPageKundendatenPlausi($args);
			}
		});


		$dispatcher->listen('shop.hook.' . \HOOK_CORE_SESSION_CONSTRUCTOR, function () use ($plugin) {
			if(self::getCssInstance($plugin)) {
				$this->cssPlugin->hookCoreSessionConstructor();
			}
		});


		$dispatcher->listen('shop.hook.' . \HOOK_SMARTY_OUTPUTFILTER, function () use ($plugin)			{
			if(self::getCssInstance($plugin)) {
				$this->cssPlugin->hookSmartyOutputfilter();
			}
		});

		$dispatcher->listen('shop.hook.' . \HOOK_BESTELLVORGANG_PAGE_STEPVERSAND  , function () use ($plugin)			{
			if(self::getCssInstance($plugin)) {
				$this->cssPlugin->hookBestellvorgangPageStepversand();
			}
		});


		$dispatcher->listen('shop.hook.' . \HOOK_LETZTERINCLUDE_INC, function (array $args) use ($plugin)			{
			if(self::getCssInstance($plugin)) {
				$this->cssPlugin->hookLetzterincludeInc($args);
			}
		});

		$dispatcher->listen('shop.hook.' . \HOOK_KUNDE_DB_INSERT, function (array $args) use ($plugin)			{
			if(self::getCssInstance($plugin)) {
				$this->cssPlugin->hookKundeDbInsert($args);
			}
		});

		$dispatcher->listen('shop.hook.' . \HOOK_KUNDE_CLASS_HOLLOGINKUNDE, function (array $args) use ($plugin)			{
			if(self::getCssInstance($plugin)) {
				$this->cssPlugin->hookKundeClassHolloginkunde($args);
			}
		});


		$dispatcher->listen('shop.hook.' . \HOOK_IO_HANDLE_REQUEST, function (array $args) use ($plugin)			{
			if(self::getCssInstance($plugin)) {
				$this->cssPlugin->hookIoHandleRequest($args);
			}
		});

// Backend Hook
		$dispatcher->listen('shop.hook.' . \HOOK_IO_HANDLE_REQUEST_ADMIN, function (array $args) use ($plugin)		{
			if(self::getCssInstance($plugin)) {
				$this->cssPlugin->hookIoHandleAdminRequest($args);
			}
		});
	}


// Bootstrap Functions

	public function getCssInstance($plugin) {
		$this->cssPlugin = $this->cssPlugin ?? src\cssPlugin\cssPlugin::getInstance($plugin);
		return ($this->cssPlugin->getConfig()->pluginActive === 'Y') ;
	}

	public function availableCronjobType(array &$args): void  {
		if (!\in_array(self::$_CRON_JOB, $args['jobs'], true)) {
			$args['jobs'][] = self::$_CRON_JOB;
		}
	}

	public function mappingCronjobType(array &$args): void {
		/** @var string $type */
		$type = $args['type'];
		if ($type === self::$_CRON_JOB) {
			$args['mapping'] = src\cssPlugin\CronJob::class;
		}
	}

	public function columnExist($table, $field) {
		// false bedeutet das es die Spalte nicht gibt
		if ($this->tableExist($table)) {
			return $this->getDB()->query("Show columns from `" . $table . "` like '" . $field . "' ", 1);
		}
		return false;
	}

	public function tableExist($table) {
		// in Rows steht die Anzahl der Zeilen, false bedeutet das es die Tabelle nicht gibt
		$obj = $this->getDB()->query("SHOW TABLE STATUS  like '" . $table . "'", 1);
		if ($obj && (int)$obj->Rows == 0) {
			$o = $this->getDB()->query("SELECT COUNT(*) AS anzahl FROM " . $table . " WHERE 1", 1);
			$obj->Rows = (int)$o->anzahl;
			return $obj;
		}
		return $obj;
	}

	// löscht alle Caches vom Plugin sowie eventuelle zusätzliche Dinge
	public function ClearCaches() {
		$plugin = $this->getPlugin();
		$minify = new MinifyService();
		$minify->flushCache();
		Shop::Container()->getCache()->flush($plugin->getPluginID()."_Config");
		Shop::Container()->getCache()->flushTags(array(CACHING_GROUP_PLUGIN, CACHING_GROUP_TEMPLATE));
		if(!empty(self::$_CRON_JOB)) {
			$this->getDB()->delete("tcron","jobType",self::$_CRON_JOB);
		}
	}


	// ab hier die normalen Bootstrap Funktionen
	public function installed() {
		$plugin = $this->getPlugin();
		$obj = new \stdClass();
		$obj->cAktiv = 'Y';
		$obj->nFehlerhaft = '0';
		$this->getDB()->update('temailvorlage', 'kPlugin', $plugin->getID(), $obj);
		self::ClearCaches();
		parent::installed();
	}

	public function updated($oldVersion, $newVersion) {
		$plugin = $this->getPlugin();


		if ($this->columnExist('css_licence_log', 'notifySubscriptionMail')) {
			$obj = new \stdClass();
			$obj->notifyUpdate = '';
			$obj->notifyUpdateMail = '';
			$obj->cPluginVersion = $newVersion;
			$this->getDB()->update('css_licence_log', 'cPluginID', $plugin->getPluginID(), $obj);
		}

		$obj = new \stdClass();
		$obj->cAktiv = 'Y';
		$obj->nFehlerhaft = '0';
		$this->getDB()->update('temailvorlage', 'kPlugin', $plugin->getID(), $obj);

		self::ClearCaches();
		\error_log('updated from ' . $oldVersion . ' to ' . $newVersion);
		parent::updated($oldVersion, $newVersion);
	}


	public function uninstalled(bool $deleteData = true) {
		$plugin = $this->getPlugin();
		if ($deleteData === true) {
			$query = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = '" . DB_NAME . "' AND table_name like '" . $plugin->getPluginID() . "%'";
			$obj = $this->getDB()->query($query, 2);
			if ($obj !== null && count($obj)) {
				foreach ($obj as $oTable) {
					$this->getDB()->query('DROP TABLE IF EXISTS ' . $oTable->TABLE_NAME, 3);
				}
			}
		}
		$this->getDB()->delete('css_licence_log', 'cPluginID', $this->getPlugin()->getPluginID());
		self::ClearCaches();
		parent::uninstalled($deleteData);
	}

	public function disabled() {
		self::ClearCaches();
		parent::disabled();
	}

	public function enabled() {
		self::ClearCaches();
		parent::enabled();
	}

	public function getPluginLink($oPlugin) {
		if (version_compare(APPLICATION_VERSION, "5.2.0-beta", ">=") === true) {
			return Shop::getAdminURL() . '/' . Route::PLUGIN . '/' . $oPlugin->kPlugin;
		} else {
			return Shop::getAdminURL() . '/' . "plugin.php?kPlugin=" . $oPlugin->kPlugin;
		}
	}


	public function addSubscriptionNotify(Notification $notification, $oUpdate) {
		$days = ceil(((int)$oUpdate->notifyTimeSubscription - time()) / 86400);
		if ((int)$days <= 0) return;
		$notification->add(
			NotificationEntry::TYPE_DANGER,
			(string)$oUpdate->cName,
			((int)$days == 1) ? "<div>Ihre Subscription f&uuml;r " . $oUpdate->cDomain . "</div>l&auml;uft morgen ab." : "<div>Ihre Subscription f&uuml;r " . $oUpdate->cDomain . "</div> l&auml;uft in  " . $days . " Tagen ab.",
			$this->getPluginLink($oUpdate),
			\md5($oUpdate->kPlugin . '_subscriptionInfo_' . mb_convert_encoding($oUpdate->notifyUpdate, 'ISO-8859-1', 'UTF-8'))
		);
	}


	public function addUpdateNotify(Notification $notification, $oUpdate) {
		$notification->add(
			NotificationEntry::TYPE_WARNING,
			(string)mb_convert_encoding($oUpdate->cName, 'UTF-8', mb_list_encodings()),
			"Update verf&uuml;gbar Version " . mb_convert_encoding($oUpdate->notifyUpdate, 'UTF-8', mb_list_encodings()),
			$this->getPluginLink($oUpdate),
			\md5($oUpdate->kPlugin . '_updateInfo_' . $oUpdate->notifyUpdate)
		);
	}

	public function checkNotification(Notification $notification): void {
		if (Shop::has('cssCheckNotification')) return;
		Shop::set('cssCheckNotification', true);

		if ($this->columnExist('css_licence_log', 'notifySubscriptionMail') == false) return;

		$query = "
					SELECT
					    p.cName,
					    p.kPlugin,
					    li.*
					FROM
					    css_licence_log AS li
					LEFT JOIN tplugin AS p
					ON
					    MD5(p.cPluginID) = MD5(li.cPluginID)
					WHERE
					    (
					        notifyUpdate != '' OR notifyTimeSubscription > 0
					    ) AND p.nStatus = 2	
		";

		$aData = $this->getDB()->query($query, 2);

		if ($aData !== null && count($aData) > 0) {
			$aHasNotify = array();
			foreach ($aData as $oData) {
				if (!empty($oData->notifyTimeSubscription)) {
					$this->addSubscriptionNotify($notification, $oData);
				}
				if (!empty($oData->notifyUpdate) && !in_array($oData->kPlugin, $aHasNotify)) {
					$aHasNotify[] = $oData->kPlugin;
					$this->addUpdateNotify($notification, $oData);
				}
			}
		}
	}
}
