<?php
namespace WpieFw\Settings\I18n;

use WpieFw\Exceptions\WpieRuntimeException;
use WpieFw\Files\WpieFile;
use WpieFw\Files\WpieFileFinder;
use WpieFw\Helpers\WpieMiscHelper;
use WpieFw\Settings\Iterator\WpieSettingsCollection;

if( ! defined( 'ABSPATH' ) ) exit;

/**
 * @author WeePie Plugins
 *
 */
final class WpieSettingsI18n
{
	/**
	 * @var WpieSettingsCollection
	 */
	private $settings;

	/**
	 * @var WpieFileFinder
	 */
	private $finder;

	/**
	 * @var WpieFile
	 */
	private $file;

	/**
	 * @var string
	 */
	private $nameSpace;

	/**
	 * Constructor
	 *
	 * @param WpieSettingsCollection $collection
	 * @param WpieFileFinder $finder
	 * @param string $nameSpace
	 */
	public function __construct( WpieSettingsCollection $collection, WpieFileFinder $finder, $nameSpace = '' )
	{
		// Store the settigs collection
		$this->settings = $collection;
		$this->finder = $finder;
		$this->nameSpace = $nameSpace;
	}

	/**
	 * Get the WpieFile instance
	 *
	 * @uses WpieFileFinder::getFile()
	 *
	 * @return \WpieFw\Files\WpieFile|boolean false if file does not exist
	 */
	public function getFile()
	{
		return $this->finder->getFile();
	}

	/**
	 * Process the creation of the translatable settings strings
	 *
	 * @uses WpieFileFinder::findFiles()
	 * @uses WpieSetting::getI18nValues()
	 * @uses self::write()
	 *
	 * @throws WpieRuntimeException
	 *
	 * @return WpieSettingsI18n
	 */
	public function process()
	{
		// Find file(s) and force to create if file not exist
		$this->finder->findFiles( null, true );

		// Try to create the file if it is not found
		if( !$this->finder->filesFound ) {
			throw new WpieRuntimeException( sprintf( 'i18n file couldn\'t be created for path "%s".' , $this->finder->getSearchPath() ) );
		}

		// Get a WpieFile instance for the I18n file
		$this->file = $this->getFile();

		// Write the I18n strings for each setting
		foreach ( $this->settings as $setting ) {
			if( $setting->getIsNew() ) {
				$strings = [];
				foreach ( $setting->getI18nValues() as $string ) {
					$strings[] = PHP_EOL.$this->line( $string );
				}
				$this->write( $setting->getName(), $strings );
			}
		}

		return $this;
	}

	/**
	 * Include the I18n file if it exists
	 *
	 * @uses include_once()
	 * @uses WpieFile::isReadable()
	 * @uses WpieFile::getPathname()
	 */
	public function includeFile()
	{
		if( $this->file && $this->file->isReadable() ) {
			@include_once $this->file->getPathname();
		}
	}

	/**
	 * Construct a translatble line
	 *
	 * Use the WordPress translation function __() for given string
	 *
	 * @param string $string
	 * @return string
	 */
	private function line( $string = '' )
	{
		$string = trim( str_replace( "'", "\'", $string ) );
		return "__('$string','$this->nameSpace');";
	}

	/**
	 * Write the I18n strings to the I18n PHP file
	 *
	 * @param string $settingsName
	 * @param array $strings
	 */
	private function write( $settingsName = '', array $strings = [] )
	{
		static $firstrun = false;

		$content     = implode( "", $strings );
		$beginPhrase = '//BEGIN '.$settingsName;
		$endPhrase   = '//END '  .$settingsName;
		$content     = $beginPhrase.$content.PHP_EOL.$endPhrase.PHP_EOL;

		clearstatcache();

		if( file_exists( $this->file->getPathname() ) ) {
			$curContent =  $this->file->getContent();
			$beginPhrase = WpieMiscHelper::escapeRegexChars( $beginPhrase );
			$endPhrase = WpieMiscHelper::escapeRegexChars( $endPhrase );
			$pattern = '#('.$beginPhrase.'.+'.$endPhrase.')#s';

			if( preg_match( $pattern, $curContent, $matches) ) {
				$content = trim( $content );
				$content = preg_replace( $pattern, $content, $curContent );
				// be sure we have a php opening tag
				if( !preg_match( '/\?php{1}/', $content ) ) {
					$content = '<?php'.PHP_EOL.$content;
				}
			} else {
				$content = $curContent . $content;
				// be sure we have a php opening tag
				if( !preg_match( '/\?php{1}/', $content ) ) {
					$content = '<?php'.PHP_EOL.$content;
				}
			}
			$firstrun = true;
		} else {
			// file is empty, begin as new PHP file
			$content = '<?php'.PHP_EOL.$content;
		}

		// append content
		if( $handle = @fopen( $this->file->getPathname(), 'w+' ) ) {
			fwrite( $handle, $content );
			fclose($handle);
		}

	}
}