<?php
namespace ShortPixel\Model\Converter;

if ( ! defined( 'ABSPATH' ) ) {
 exit; // Exit if accessed directly.
}

use ShortPixel\Replacer\Replacer as Replacer;
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
use ShortPixel\Model\File\DirectoryModel as DirectoryModel;
use ShortPixel\Model\File\FileModel as FileModel;
use ShortPixel\Controller\ResponseController as ResponseController;

/* ShortPixel Image Optimiser Converters. Unified interface for handling conversion between file types */
abstract class Converter
{
	  const CONVERTABLE_EXTENSIONS = array('png', 'heic');

		const ERROR_LIBRARY = -1; /// PNG Library error
		const ERROR_PATHFAIL = -2; // Couldn't create replacement path
		const ERROR_RESULTLARGER = -3; // Converted file is bigger than the original
		const ERROR_WRITEERROR = -4; // Result file could not be written
		const ERROR_BACKUPERROR = -5; // Backup didn't work.
		const ERROR_TRANSPARENT = -6; // Transparency when it is not allowed.

		protected $imageModel;  // The current ImageModel from SPIO

		// Method specific
		abstract public function convert($args = array());
		abstract public function isConvertable();
		abstract public function restore();
		abstract public function getCheckSum();

		// Media Library specific
		abstract protected function updateMetaData($params);
		abstract public function getUpdatedMeta();
		abstract protected function setupReplacer();
		abstract protected function setTarget($file);

		public function __construct($imageModel)
		{
				$this->imageModel = $imageModel;
				$this->imageModel->getMeta()->convertMeta()->setFileFormat($imageModel->getExtension());
		}

		public function isConverterFor($extension)
		{
			 if ($extension === $this->imageModel->getMeta()->convertMeta()->getFileFormat())
			 {
				  return true;
			 }
			 return false;
		}

		// ForConversion:  Return empty if file can't be converted or is already converrted
		public static function getConverter($imageModel, $forConversion = false)
		{
			  $extension = $imageModel->getExtension();

				$converter = false;

				$converter = self::getConverterByExt($extension, $imageModel);

				// No Support (yet)
				if ($imageModel->get('type') == 'custom')
				{
					return false;
				}

				// Second option for conversion is image who have been placeholdered.
				if (true === $imageModel->getMeta()->convertMeta()->hasPlaceHolder() && false === $imageModel->getMeta()->convertMeta()->isConverted() && ! is_null($imageModel->getMeta()->convertMeta()->getFileFormat()))
				{
					 $converter = self::getConverterByExt($imageModel->getMeta()->convertMeta()->getFileFormat(), $imageModel);
				}

				if (true === $forConversion) // don't check more.
				{
					 return $converter;
				}

				if (false === $converter)
				{
					 if ($imageModel->getMeta()->convertMeta()->isConverted() && ! is_null($imageModel->getMeta()->convertMeta()->getFileFormat()) )
					 {
						 $converter = self::getConverterByExt($imageModel->getMeta()->convertMeta()->getFileFormat(), $imageModel);
					 }
					 else
					 {
					 		return false;
					 }
				}


				return $converter;
		}

		/** Own function to get a unique filename since the WordPress wp_unique_filename seems to not function properly w/ thumbnails */
    protected function unique_file(DirectoryModel $dir, FileModel $file, $number = 0)
    {
      if (! $file->exists())
        return $file;

			if ($file->is_virtual())
			{
				 return $file;
			}

      $number = 0;
      $fs = \wpSPIO()->filesystem();

      $base = $file->getFileBase();
      $ext = $file->getExtension();

      while($file->exists())
      {
        $number++;
        $numberbase = $base . '-' . $number;
        Log::addDebug('check for unique file -- ' . $dir->getPath() . $numberbase . '.' . $ext);
        $file = $fs->getFile($dir->getPath() . $numberbase . '.' . $ext);
      }

      return $file;
    }

		protected function getReplacementPath()
		{
			$fs = \wpSPIO()->filesystem();

			$filename = $this->imageModel->getFileName();
			$newFileName = $this->imageModel->getFileBase() . '.jpg'; // convert extension to .jpg

			$fsNewFile = $fs->getFile($this->imageModel->getFileDir() . $newFileName);

			$uniqueFile = $this->unique_file( $this->imageModel->getFileDir(), $fsNewFile);
			$newPath =  $uniqueFile->getFullPath(); //(string) $fsFile->getFileDir() . $uniquepath;

			if (! $this->imageModel->getFileDir()->is_writable())
			{
					Log::addWarn('Replacement path for PNG not writable ' . $this->imageModel->getFileDir()->getPath());
					$msg = __('Replacement path for PNG not writable', 'shortpixel-image-optimiser');
					ResponseController::addData($this->imageModel->get('id'), 'message', $msg);

				return false;
			}

			$this->setTarget($uniqueFile);

			return $newPath;

		}



		private static function getConverterByExt($ext, $imageModel)
		{
					$converter = false;
					switch($ext)
					{
						 case 'png':
							$converter = new PNGConverter($imageModel);
						 break;
						 case 'heic':
							$converter = new ApiConverter($imageModel);
						 break;

					}
					return $converter;

		}


}
