<?php
namespace ModulesAbstract\PluginReports\Report\Model\Exporter;

abstract class ExporterAutoFileManagement extends ExporterWithStorageAbstract
{
	/**
	 * Opened file handlers, automatically closed by destroy()
	 * @var array
	 */
	protected $openFiles= [];

	public function destroy()
	{
		// closed files handlers
		if ($this->openFiles) {
			foreach ($this->openFiles as $key => $handler) {
				fclose($handler);
				unset($this->openFiles[$key]);
			}
			$this->openFiles= [];
		}

		parent::destroy();
	}

	protected function fileOpen($filename)
	{
		if (!isset($this->openFiles[$filename])) {
			$file = fopen($this->basePath.$filename, "w" );
			// there should be a chmod(0777) here but picking the right permissions is a bit tricky, we'll leave the decision whenever we get to give up 0777 as default permissions
			if ($file===false) {
				throw new \Exception(sprintf("Cannot open report file. Path: %s", $this->basePath.$filename));
			}
			$this->openFiles[$filename] = $file;
		}

		return $this->openFiles[$filename];
	}

	protected function fileAppend($filename, $str)
	{
		$file = $this->fileOpen($filename);
		if (fwrite($file, $str)===false) {
			throw new \Exception(sprintf("Cannot write to report file. Path: %s", $this->basePath.$filename));
		}
	}

	/**
	 * This method builds a csv line from an array (that we can later encode it, such as it the case with the Japanese encoding)
	 * Since only as of php 8.0 fputcsv has the eol parameter, we have to implement this method
	 * @param string $filename
	 * @param array $fields
	 * @param string $separator
	 * @param string $enclosure
	 * @param string $escape
	 * @param string $eol
	 * @return string
	 */
	protected function getCSVLine($filename, array $fields, string $separator = ",", string $enclosure = "\"", string $escape = "\\", string $eol = "\n")
	{
		array_walk($fields, [$this, 'filePutCSV_dataEncoder'], [
			'enclosure' => $enclosure,
			'escape' => $escape,
		]);
		$line = implode($separator, $fields) . $eol;

		return $line;
	}

	/**
	 * Encodes the input value
	 * @param string $inputValue
	 * @param array $args
	 */
	public function filePutCSV_dataEncoder(&$inputValue, $index, $args)
	{
		$useEnclosure = false;

		$regexp = sprintf("/[\s%s%s]/", preg_quote($args['enclosure']), preg_quote($args['escape']));
		if (preg_match($regexp, $inputValue)) {
			$useEnclosure = true;
		}

		$replacements = [
			$args['escape'].$args['enclosure'] => $args['escape'].$args['enclosure'],
			$args['enclosure'] => $args['enclosure'].$args['enclosure'],
		];
		$inputValue = str_replace(array_keys($replacements), array_values($replacements), $inputValue);

		if ($useEnclosure) {
			$inputValue = $args['enclosure'] . $inputValue . $args['enclosure'];
		}

	}
}