<?php

namespace App\Utils\Wkhtmltopdf;

/**
 * The class manages the wkhtmltopdf command. It makes sure that the app is installed; if not, it
 * downloads it from LIDIA. This is not included in TINA as a third party as it occupies around 80MB
 * and for the moment it is used only by some plugins.
 * @author Gabriel Grosu
 *
 */
class Installer
{

	/**
	 * The location (relative to files/) where wkhtmltopdf executable is/will be installed.
	 * @var string
	 */
	private $libParentPath = '3parties/wkhtmltopdf/';

	/**
	 * The location of the executables (relative to libParentPath).
	 * @var string
	 */
	private $libExecpath = 'bin/';

	/**
	 * The lib full path (binary dir).
	 * @var string
	 */
	private $libFullPath = '';

	/**
	 * Indicates if the lib is installed.
	 * @var string
	 */
	private $installed = false;

	/**
	 * Singleton instance.
	 * @var \App\Utils\Wkhtmltopdf\Installer
	 */
	private static $instance;

	/**
	 * Singleton constructor.
	 */
	private function __construct()
	{

		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();
		$this->libFullPath = APP_REAL_PATH.$CFG['paths']['files'].$this->libParentPath.$this->libExecpath;
		if (\Engine\Dir::check($this->libFullPath)) {
			$this->installed = true;
		}

	}

	/**
	 * Singleton instantiation.
	 * @return \App\Utils\Wkhtmltopdf\Installer
	 */
	static public function getInstance()
	{
		if (!self::$instance) {
			self::$instance = new self();
		}
		return self::$instance;
	}


	/**
	 * If the lib is not installed - installs it.
	 * @return boolean
	 */
	public function install()
	{

		// skip if installed
		if ($this->installed) {
			return true;
		}

		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();

		// CREATE APP DIR ---------------------------------------------------------------------------
		$folderWkhtmltopdf = APP_REAL_PATH.$CFG['paths']['files'].$this->libParentPath;
		if ( !\Engine\Dir::create( $folderWkhtmltopdf ) ) {
			throw new \Exception\IO\Base("The folder '{$this->libFullPath}' couldn't be created.");
		}

		// COMPOSE REQUEST FROM LIDIA ---------------------------------------------------------------
		$requestObject = new \App\Lidia\GetWkhtmltopdfVersions\Request();
		$requestObject->operation = 'getWkhtmltopdfVersions';

		// execute operation and get response from LIDIA
		$responseObject = new \App\Lidia\GetWkhtmltopdfVersions\Response();
		$apiObject = new \App\Lidia\GetWkhtmltopdfVersions\Api($CFG['global']['newLicenseServerAddress']);
		$apiObject->executeOperation($requestObject, $responseObject);
		$responseObject->check();

		$operatingSystem = php_uname("m");

		if ($operatingSystem == 'x86_64' || $operatingSystem == 'ia64' || $operatingSystem == 'amd64') {
			$arch = 'amd64';
		}
		else {
			$arch = 'i386';
		}

		$mkhtmltopdfVersions = $responseObject->getVersions();
		$mkhtmltopdfVersions = array_filter($mkhtmltopdfVersions, function($mkhtmltopdfVersions) use ($arch) {
			if ($mkhtmltopdfVersions['version'] == '0.12.4' &&
				$mkhtmltopdfVersions['arch'] == $arch &&
				$mkhtmltopdfVersions['compression'] == 'zip' &&
				count($mkhtmltopdfVersions['support']) == 1 && $mkhtmltopdfVersions['support'][0] == 'pdf'
			) {
				return true;
			}
			return false;
		});


		// get url for downloading the archive
		if (count($mkhtmltopdfVersions) != 1) {
			throw new \Exception\IO\Base("Lidia returned more versions of mkhtmltopdf available for plugin 'StatementOfAccount'.");
		}

		$mkhtmltopdfVersions = reset($mkhtmltopdfVersions);

		// download the version
		$conn = new \App\Utils\FileTransfer\HttpTransfer();
		$tempFileName = \Engine\File::tempnam(sprintf("wkhtmltopdf-%s.zip", \Engine\RandomGenerator::randomString(10)));
		$conn->downloadFile($mkhtmltopdfVersions['url'], $tempFileName);

		\Log::getInstance()->info(sprintf("[%s] Downloaded the wkhtmltopdf compress library.", __METHOD__), [
			'version' => new \Engine\Logger\Context\ArrayAssoc($mkhtmltopdfVersions),
		]);

		// unzip
		\App\Archive\Uncompress\Zip::create()
			->open($tempFileName)
			->extractTo($folderWkhtmltopdf)
			->close();

		\Log::getInstance()->info(sprintf("[%s] Uncompress the wkhtmltopdf library.", __METHOD__));

		// change permission
		\Engine\Dir::changePermissions($folderWkhtmltopdf);
		\Engine\File::setDefaultPermissions($folderWkhtmltopdf."/bin/wkhtmltopdf");

		\Log::getInstance()->info(sprintf("[%s] Change permissions for wkhtmltopdf library.", __METHOD__));

		// remove old file
		\Engine\File::delete($tempFileName);

		// write version
		\Engine\File::create($folderWkhtmltopdf."version.json", json_encode($mkhtmltopdfVersions));

		$this->installed = true;
		return true;
	}

	/**
	 * Returns whether the lib is installed or not.
	 * @return boolean
	 */
	public function isInstalled()
	{
		return $this->installed;
	}

	/**
	 * Returns the lib full path.
	 * @return String
	 */
	public function getLibFullPath()
	{
		return $this->libFullPath;
	}

}




