<?php

namespace IZON\Thumber\Image;

use IZON\IO\Image;
use IZON\Thumber\Exceptions\ImageNotFoundException;
use IZON\Thumber\Exceptions\ImageSizeIsNotSetException;
use IZON\Thumber\ImageConfiguration\IImageConfiguration;
use IZON\Thumber\ImageConfiguration\ImageConfiguration;
use function IZON\File\normalizePath;

/**
 * ImageUrlBuilder
 * @author Aleš Kopecký <kopecky@izon.cz>
 */
class ImageUrlBuilder implements IImageUrlBuilder {

    /**
     *
     * @var string
     */
    protected $path = '';
    
    /**
     * Sets path to image lazy controller.
     * @param string $path
     */
    public function setPath(string $path) {
        $this->path = $path;
    }

    /**
     * Create URL to controller with params.
     * @param IImageConfiguration $config
     * @return string
     */
    public function buildUrl(IImageConfiguration $config): string {
        $params = [
            'image' => $this->getImageLocationString($config->getImage()),
            'width' => $config->getWidth(),
            'height' => $config->getHeight(),
            'quality' => $config->getQuality(),
            'type' => $config->getType(),
            'name' => $config->getName()
        ];
        if($config->hasCrop()) {
            if($config->getCropPoint() instanceof IImagePoint) {
                $params['cropPointX'] = $config->getCropPoint()->getX();
                $params['cropPointY'] = $config->getCropPoint()->getY();
            }
            if($config->getCropSize() instanceof IImageSize) {
                $params['cropSizeWidth'] = $config->getCropSize()->getWidth();
                $params['cropSizeHeight'] = $config->getCropSize()->getHeight();
            }
        }
        $url = $this->path.'?'.http_build_query($params);
        return $url;
    }
    
    /**
     * Creates image config from parameters in given array.
     * @param array $params
     * @return IImageConfiguration
     */
    public static function fromArray(array $params): IImageConfiguration {
        $imgDir = __BASE_DIR__.$params['image'];
        if(!is_file($imgDir)) {
            throw new ImageNotFoundException("Image '{$params['image']}' not found.");
        }
        
        $imageIO = new Image($imgDir);
        
        $hasNoWidth = !isset($params['width']) || is_null($params['width']);
        $hasNoHeight = !isset($params['height']) || is_null($params['height']);
        
        if($hasNoWidth && $hasNoHeight) {
            throw new ImageSizeIsNotSetException("Width and height is not set");
        } else if($hasNoWidth) {
            throw new ImageSizeIsNotSetException("Width is not set");
        } else if($hasNoHeight) {
            throw new ImageSizeIsNotSetException("Height is not set");
        }
        
        $size = ImageSize::create($params['width'], $params['height']);
        
        $cropPoint = null;
        $cropSize = null;
        # Create crop point and crop size if params set
        if(isset($params['cropPointX'])
                && isset($params['cropPointY'])
                && isset($params['cropSizeWidth'])
                && isset($params['cropSizeHeight'])) {
            $cropPoint = new ImagePoint($params['cropPointX'], $params['cropPointY']);
            $cropSize = ImageSize::create($params['cropSizeWidth'], $params['cropSizeHeight']);
        }
        
        # Create image configuration object
        $imageConfiguration = new ImageConfiguration();
        $imageConfiguration
                ->setImage($imageIO)
                ->setImageSize($size)
                ->setQuality($params['quality'])
                ->setType($params['type'])
                ->setName($params['name']);
        if($cropPoint instanceof IImagePoint && $cropSize instanceof IImageSize) {
            $imageConfiguration
                    ->setCropPoint($cropPoint)
                    ->setCropSize($cropSize);
        }
        return $imageConfiguration;
    }
    
    /**
     * Gets image location after www folder.
     * To prevent displaying file system path in URLs on web.
     * @param Image $image
     * @return string
     */
    protected function getImageLocationString(Image $image): string {
        $fsPath = normalizePath($image->getFsPath());
        $parts = array_reverse(explode('/', $fsPath));
        $newParts = [];
        foreach($parts as $part) {
            $newParts[] = $part;
            if($part == 'www') {
                break;
            }
        }
        $path = implode('/', array_reverse($newParts));
        return '/'.$path;
    }

}
