<?php

namespace Meoran\Images\Http\Controllers;

use Closure;
use Illuminate\Http\Request;
use Laravel\Lumen\Routing\Controller as BaseController;
use Meoran\Images\Model\Image;

class ImagesController extends BaseController
{

    public function get($filename, $template = null)
    {
        if ($template === null) {
            $template = 'original';
        }
        switch (strtolower($template)) {
            case 'original':
                return $this->getOriginal($filename);
            case 'download':
                return $this->getDownload($filename);
            default:
                return $this->getImage($template, $filename);
        }
    }

    public function upload(Request $request)
    {
        $this->validate($request, [
            'image' => 'required|file|image'
        ]);

        $image = new Image(['content' => $request->file('image')]);
        $image->save();

        return response()->json($image);
    }

    private function getOriginal($filename)
    {
        $path = $this->getImagePathOrAbort($filename);
        return $this->buildResponse(file_get_contents($path));
    }

    private function getDownload($filename)
    {
        $response = $this->getOriginal($filename);

        return $response->header(
            'Content-Disposition',
            'attachment; filename=' . $filename
        );
    }

    private function getImagePathOrAbort($filename)
    {
        $path = Image::getAbsolutePath($filename);
        if (is_file($path)) {
            return $path;
        }
        abort(404);
    }

    public function getImage($template, $filename)
    {
        $template = $this->getTemplate($template);
        $path = $this->getImagePathOrAbort($filename);

        $lifetime = config('image.lifetime');
        if (empty($lifetime)) {
            $content = $this->applyTemplate($template, $path)->encode();
        } else {
            $content = app('image')->cache(function ($image) use ($template, $path) {
                $this->applyTemplate($template, $path, $image);
                return $image;
            }, $lifetime);
        }

        return $this->buildResponse($content);
    }

    private function applyTemplate($template, $path, $image = null)
    {
        if (empty($image)) {
            $image = app('image');
        }

        if ($template instanceof Closure) {
            // build from closure callback template
            return $template($image->make($path));
        } else {
            // build from filter template
            return $image->make($path)->filter($template);
        }
    }

    /**
     * Returns corresponding template object from given template name
     *
     * @param  string $template
     * @return mixed
     */
    private function getTemplate($template)
    {
        $template = config("images.templates.{$template}");
        switch (true) {
            // closure template found
            case is_callable($template):
                return $template;

            // filter template found
            case class_exists($template):
                return new $template;

            default:
                // template not found
                abort(404);
                break;
        }
    }

    private function buildResponse($content)
    {
        // define mime type
        $mime = finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $content);

        // return http response
        return response($content, 200, array(
            'Content-Type' => $mime,
            'Cache-Control' => 'max-age=' . (config('image.lifetime') * 60) . ', public',
            'Etag' => md5($content)
        ));
    }
}