<?php
namespace ShortPixel\Controller\Backup;

use ShortPixel\Model\Backup\BackupModel;
use ShortPixel\Model\Backup\LocalBackupModel;
use ShortPixel\Model\File\FileModel;
use ShortPixel\Model\Image\CustomImageModel;
use ShortPixel\Model\Image\ImageModel;
use ShortPixel\Model\Image\MediaLibraryModel;
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;

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

/** 
BackupController, need to implement the following : 

1) Get and check Backup Directories. Controll all hooks, actions, filters for directories here (with FS) 
2) CreateBackup, CheckBackup, RestoreBackup functions with a ImageModel(FileModel) Parameter here 
3) RemoveBackups older than X functionality and Cron Handler. 
4) Implement it's possible to store only main file as backup (with checks and what not) and if so, on restore regenerate the thumbnails back . Need checking for special filetypes such as pnh, heic etc 
5) Should pave the way for remote/cloud backups as well(?)
*/

abstract class BackupController 
{
    protected static $instance;

    protected static $models = []; 
    protected static $model; 

    abstract protected function autoRemoveBackups();

    public function __construct()
    {
         
    }

    public static function getBackupController()
    {
      $settings = \wpSPIO()->settings(); 

      if (is_null(self::$instance))
      {

      // @todo  The problem here is perhaps that the localBackupModel is not set, but reference in getBackup by ID. 
        if (false === $settings->backupImages)
        {
          self::$instance = new NoBackupController();  
          
        } 
        else
        {
          self::$instance = new LocalBackupController();
          self::$model = '\ShortPixel\Model\Backup\LocalBackupModel'; 
        }
        // Here check with settings which backup method is active 
      }

      return self::$instance; 
    }

    public static function getBackupModel(ImageModel $imageItem)
    {
      //MediaLibraryModel|CustomImageModel
      if (! ($imageItem instanceof MediaLibraryModel) && ! ($imageItem instanceof CustomImageModel))
      {
        throw new \Exception('BackupController - BackupModel initialization class must be of the highest level either media or custom');
      } 

      $backupController = self::getBackupController();

      return $backupController->getModel($imageItem);
    }

    /**
     * Get BackupModel via mediaItem. This saves getting the image via filesystemcontroller.
     *
     * @param ImageModel $mediaItem
     * @return void
     */
    public function getModel(ImageModel $mediaItem)
    {
        $id = $mediaItem->get('id');
        $type = $mediaItem->get('type');
        
        return $this->getModelById($id, $type, $mediaItem);
    }

    /** Get BackupModel via ID and Type.  This should be called via getModel or static function. No direct access, because the FS getImage might result in an init loop via MediaLibraryModel / CustomImageModel 
     * 
     * @param int $id 
     * @param string $type 
     * @param mixed $mediaItem 
     * @return BackupModel 
     */
    protected function getModelById(int $id, $type = 'media', $mediaItem = null) : BackupModel
    {
      if (! isset(self::$models[$type]) || ! isset(self::$models[$type][$id]))
      {
          // It needs to be the main MediaItem here, because it checks ConvertMeta for IsConvertered, which is only set there.
          if (is_null($mediaItem) || false === $mediaItem->get('is_main_file'))
          {
             $fs = \wpSPIO()->filesystem();
             $mediaItem = $fs->getImage($id, $type); 
          }
          
          // The issue here is when the backups are off, the model var isn't loaded properly, leading to crash 
          //$model = new self::$model(self::$instance, $mediaItem);
          $model = new \ShortPixel\Model\Backup\LocalBackupModel(self::$instance, $mediaItem);


          if (! isset(self::$models[$type]))
          {
            self::$models[$type] = []; 
          }
          self::$models[$type][$id] = $model; 
      }
      
      return self::$models[$type][$id];
    }

    public function withItem($mediaItem)
    {
        
    }

    
    /** Hook function for Cron. Should only handle cron, all functionality should be separate. 
     * 
     * @return void 
     */
    public function cronRemoveBackups()
    {
        $bool = $this->checkRemoveBackups();
        if (false === $bool || $bool !== true)
        {
          return false; 
        }

        $this->autoRemoveBackups();
        
    }

    public function cliRemoveBackups()
    {
      $bool = $this->checkRemoveBackups();
      if (false === $bool || $bool !== true)
      {
        return false; 
      }

      $this->autoRemoveBackups();
    }

    protected function checkRemoveBackups()
    {
        $settings = \wpSPIO()->settings(); 
        $bool = false; 

        $removeBackups = $settings->autoRemoveBackups; 
        $removePeriod = $settings->autoRemoveBackupsPeriod; 

        if (true !== $removeBackups)
        {
           return false; 
        }

        if (is_null($removePeriod))
        {
           return false; 
        }

        // After many double checks, -better fail than fault- perhaps return true. 
        if (is_string($removePeriod) && true === $removeBackups)
        {
           return true;
        }

        return false;         
        
    }  

} // class