<?php

/*
* @package   s9e\TextFormatter
* @copyright Copyright (c) 2010-2019 The s9e Authors
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
*/
namespace s9e\TextFormatter\Configurator\JavaScript\Minifiers;
use RuntimeException;
use s9e\TextFormatter\Configurator\JavaScript\Minifier;
class ClosureCompilerApplication extends Minifier
{
	public $closureCompilerBin;
	public $command;
	public $compilationLevel = 'ADVANCED_OPTIMIZATIONS';
	public $excludeDefaultExterns = \true;
	public $javaBin = 'java';
	public $options = '--use_types_for_optimization';
	public function __construct($filepathOrCommand = \null)
	{
		if (isset($filepathOrCommand))
			if (\file_exists($filepathOrCommand) && \substr($filepathOrCommand, -4) === '.jar')
				$this->closureCompilerBin = $filepathOrCommand;
			else
				$this->command = $filepathOrCommand;
	}
	public function getCacheDifferentiator()
	{
		$key = [
			$this->compilationLevel,
			$this->excludeDefaultExterns,
			$this->options
		];
		if (isset($this->closureCompilerBin))
			$key[] = $this->getClosureCompilerBinHash();
		if ($this->excludeDefaultExterns)
			$key[] = \file_get_contents(__DIR__ . '/../externs.application.js');
		return $key;
	}
	public function minify($src)
	{
		$this->testFilepaths();
		$options = ($this->options) ? ' ' . $this->options : '';
		if ($this->excludeDefaultExterns && $this->compilationLevel === 'ADVANCED_OPTIMIZATIONS')
			$options .= ' --externs ' . __DIR__ . '/../externs.application.js --env=CUSTOM';
		$crc     = \crc32($src);
		$inFile  = \sys_get_temp_dir() . '/' . $crc . '.js';
		$outFile = \sys_get_temp_dir() . '/' . $crc . '.min.js';
		\file_put_contents($inFile, $src);
		if (isset($this->command))
			$cmd = $this->command;
		else
			$cmd = \escapeshellcmd($this->javaBin) . ' -jar ' . \escapeshellarg($this->closureCompilerBin);
		$cmd .= ' --compilation_level ' . \escapeshellarg($this->compilationLevel)
		     . $options
		     . ' --js ' . \escapeshellarg($inFile)
		     . ' --js_output_file ' . \escapeshellarg($outFile);
		\exec($cmd . ' 2>&1', $output, $return);
		\unlink($inFile);
		if (\file_exists($outFile))
		{
			$src = \trim(\file_get_contents($outFile));
			\unlink($outFile);
		}
		if (!empty($return))
			throw new RuntimeException('An error occured during minification: ' . \implode("\n", $output));
		return $src;
	}
	protected function getClosureCompilerBinHash()
	{
		static $cache = [];
		if (!isset($cache[$this->closureCompilerBin]))
			$cache[$this->closureCompilerBin] = \md5_file($this->closureCompilerBin);
		return $cache[$this->closureCompilerBin];
	}
	protected function testFilepaths()
	{
		if (isset($this->command))
			return;
		if (!isset($this->closureCompilerBin))
			throw new RuntimeException('No path set for Closure Compiler');
		if (!\file_exists($this->closureCompilerBin))
			throw new RuntimeException('Cannot find Closure Compiler at ' . $this->closureCompilerBin);
	}
}