<?php


namespace App\Model;


use App\Model\Crates\UploaderNode;
use App\Model\Exceptions\Uploader\ImageCacheExpiredException;
use Nette\Caching\Cache;
use Nette\Caching\IStorage;
use Nette\Http\FileUpload;
use Nette\Utils\Image;
use WebChemistry\Images\AbstractStorage;
use Zet\FileUpload\Model\IUploadModel;

class Uploader implements IUploadModel
{
    const GALLERY = 'gallery';

    /** @var IStorage */
    protected $storage;
    /** @var AbstractStorage */
    protected $imageStorage;

    public function __construct(IStorage $storage, AbstractStorage $imageStorage)
    {
        $this->storage = $storage;
        $this->imageStorage = $imageStorage;
    }

    /**
     * @param FileUpload $file
     * @return UploaderNode
     */
    public function save(FileUpload $file)
    {
        $key = $file->getSanitizedName() . microtime();

        $cache = $this->getImageCache();
        $cache->save($key, $file->toImage()->toString(), array(Cache::EXPIRE => '15 minutes'));
        $cache->clean();

        // remove extension from filename
        $temp = explode('.', $file->getSanitizedName());
        $ext  = array_pop($temp);
        $name = implode('.', $temp);

        return new UploaderNode($key, $name);
    }

    /**
     * @param UploaderNode $upload
     * @param string $newName
     * @return UploaderNode
     */
    public function rename($upload, $newName)
    {
        return $upload->rename($newName);
    }

    /**
     * @param UploaderNode $uploaded
     */
    public function remove($uploaded)
    {
        $this->getImageCache()->remove($uploaded->getCacheKey());
    }

    /**
     * @param string $fileKey
     * @param string $destination
     * @return string
     * @throws ImageCacheExpiredException
     */
    public function saveFileFromCache(string $fileKey, string $destination) : string
    {
        $cache = $this->getImageCache();
        $cache->clean();

        $imageString = $cache->load($fileKey);

        if ($imageString === null) {
            throw new ImageCacheExpiredException();
        }

        $fileName = $this->imageStorage->saveImage(Image::fromString($imageString), uniqid() . '.jpg', $destination);

        $cache->remove($fileKey);
        return $fileName;
    }

    public function deleteImage(string $fileName)
    {
        $this->imageStorage->delete($fileName);
    }

    /**
     * @return Cache
     */
    protected function getImageCache()
    {
        return new Cache($this->storage, 'uploader');
    }
}