<?php
namespace PreviewGenerator;

use WideImage\WideImage;
use WideImage\Image;

/*
	$pg = new PreviewGenerator;
	$image = WideImage::load('image.jpg');
	$wm = WideImage::load('logo.png');
	$pg->putWatermark($image, $wm)->saveToFile('image.jpg');
	
	$pg->create($image, 240, 180)->saveToFile('preview.jpg');
*/

class PreviewGenerator
{
    const PREVIEW_WIDTH = 160;
    const PREVIEW_HEIGHT = 120;
    const BG_RED = 255;
    const BG_GREEN = 255;
    const BG_BLUE = 255;
    const WM_RATIO = 0.2;

    private $previewWidth;
    private $previewHeight;
    private $image;

    public function create(
        Image $image,
        $width = self::PREVIEW_WIDTH,
        $height = self::PREVIEW_HEIGHT,
        $red = self::BG_RED,
        $green = self::BG_GREEN,
        $blue = self::BG_BLUE
    ) {
        $this->previewWidth = $width;
        $this->previewHeight = $height;
        $this->image = $image;

        $bg = WideImage::createPaletteImage($width, $height);
        $bgColor = $bg->allocateColor($red, $green, $blue);
        $bg->fill(0, 0, $bgColor);

        if ($this->tooSmall()) {
            $preview = $bg->merge($this->image);
        } elseif ($this->isWide()) {
            $resized = $this->image->resizeDown($this->previewWidth);
            $preview = $this->bg->merge(
                $resized, 0, $this->getTopOffset($resized)
            );
        } else {
            $resized = $this->image->resizeDown(null, $this->previewHeight);
            $preview = $bg->merge(
                $resized, $this->getLeftOffset($resized), 0
            );
        }
        return $preview;
    }

    public function putWatermark(
        Image $image,
        Image $wm,
        $opacity = 100,
        $wmRatio = self::WM_RATIO,
        $margin = 10
    ) {
        $desiredWidth = intval($this->getSmallerSide() * $wmRatio);
        $wmResized = $wm->resizeDown($desiredWidth);
        return $image->merge(
            $wmResized,
            $this->image->getWidth() - $wmResized->getWidth() - $margin,
            $this->image->getHeight() - $wmResized->getHeight() - $margin,
            $opacity
        );
    }

    private function isWide()
    {
        return $this->imageRatio() >= $this->previewRatio();
    }

    private function imageRatio()
    {
        return $this->image->getWidth()
            / $this->image->getHeight();
    }

    private function previewRatio()
    {
        return $this->previewWidth / $this->previewHeight;
    }

    private function tooSmall()
    {
        return ($this->image->getWidth() <= $this->previewWidth)
        and ($this->image->getHeight() <= $this->previewHeight);
    }

    private function getSmallerSide()
    {
        if ($this->image->getWidth() < $this->image->getHeight()) {
            return $this->image->getWidth();
        } else {
            return $this->image->getHeight();
        }
    }

    private function getTopOffset($resized)
    {
        return intval(
            ($this->previewHeight - $resized->getHeight()) / 2
        );
    }

    private function getLeftOffset($resized)
    {
        return intval(
            ($this->previewWidth - $resized->getWidth()) / 2
        );
    }
}
