<?php

namespace App\Model;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use File;
use Image;
use StringOperation;

abstract class Photo extends Model
{

    /**
     * Protected values by mass assignament
     *
     * @var array
     */
    protected $guarded = ['id'];
    protected $width = 1980;
    protected $thumbWidth = 512;
    protected $entity = 'item';

    protected function getItemForeignKey()
    {
        return $this->entity . '_id';
    }

    protected function getItemForeignKeyValue()
    {
        return $this->{$this->getItemForeignKey()};
    }

    public function setItemForeignKeyValue($value)
    {
        return $this->{$this->getItemForeignKey()} = $value;
    }

    protected function getItemNamespace()
    {
        return Str::plural($this->entity);
    }

    public static function boot()
    {
        parent::boot();

        static::saving(function ($model) {
            // default priority
            if ($model->priority === null) {
                $model->priority = 99;
            }
        });

        static::saved(function ($model) {
            // just set item main photo if not set already or changed priorirty.
            if (!$model->item->photo || !$model->priority) {
                $model->item->photo_id = $model->id;
                $model->item->save();
            }
        });

        static::deleting(function ($model) {
            // delete only if there aren't any more photos with the same filename
            if ($model->item->photos()
                    ->where('id', '!=', $model->id)
                    ->where('filename', $model->filename)
                    ->count() === 0) {
                $photo_root_path = StringOperation::getCompletePathFromNumber($model->getItemForeignKeyValue(), $model->getItemNamespace(), false);

                File::delete($photo_root_path . $model->filename);
                File::delete($photo_root_path . 'thumb_' . $model->filename);
            }
        });

        static::deleted(function ($model) {
            // if this is the main photo, we should get the next one
            if ($model->item->photo_id === $model->id) {
                $model->item->photo_id = count($model->item->photos) ? $model->item->photos->first()->id :  null;
                $model->item->save();
            }
        });
    }

    abstract function item();

    public function upload($photo)
    {
        if (!$photo) {
            return;
        }

        // get photo root path
        $photo_root_path = StringOperation::getCompletePathFromNumber($this->getItemForeignKeyValue(), $this->getItemNamespace(), false);

        // check if folder exists and create it recursively if N/a
        if (!File::isDirectory($photo_root_path)) {
            File::makeDirectory($photo_root_path, 0755, true);
        }

        $basename = basename($photo->getClientOriginalName(), '.' . $photo->getClientOriginalExtension());

        // remove the last [digit], eg: [0], [1].. when uploading via copy/paste a URL.
        $basename = preg_replace('#\[[0-9]+\]$#', '', $basename);

        // set filename, but first do a lil of cleanup.
        $this->filename = $this->getItemForeignKeyValue() . '-' . Str::slug($basename) . '.' . strtolower($photo->getClientOriginalExtension());

        // generate photo
        Image::make($photo->getRealPath())
            ->resize($this->width, null, function ($constraint) {
                $constraint->aspectRatio();
                $constraint->upsize();
            })
            ->save($photo_root_path . $this->filename);

        // generate thumb
        Image::make($photo->getRealPath())
            ->resize($this->thumbWidth, null, function ($constraint) {
                $constraint->aspectRatio();
                $constraint->upsize();
            })
            ->save($photo_root_path . 'thumb_' . $this->filename);
    }

    public function process($source_path)
    {
        if (!$source_path) {
            return;
        }

        // get photo root path
        $photo_root_path = StringOperation::getCompletePathFromNumber($this->getItemForeignKeyValue(), $this->getItemNamespace(), false);

        // check if folder exists and create it recursively if N/a
        if (!File::isDirectory($photo_root_path)) {
            File::makeDirectory($photo_root_path, 0755, true);
        }

        $path_parts = pathinfo($source_path);

        // set filename, but first do a lil of cleanup.
        $this->filename = $this->getItemForeignKeyValue() . '-' . Str::slug($path_parts['filename']) . '.' . strtolower($path_parts['extension']);

        // generate photo
        Image::make($source_path)
            ->resize($this->width, null, function ($constraint) {
                $constraint->aspectRatio();
                $constraint->upsize();
            })
            ->save($photo_root_path . $this->filename);

        // generate thumb
        Image::make($source_path)
            ->resize($this->thumbWidth, null, function ($constraint) {
                $constraint->aspectRatio();
                $constraint->upsize();
            })
            ->save($photo_root_path . 'thumb_' . $this->filename);
    }


    public function getPhotoUrl($show_thumb = false)
    {
        return StringOperation::getPhotoUrlFromNumber($this->getItemForeignKeyValue(), $this->getItemNamespace(), $this->filename, $show_thumb);
    }

    public function getThumbUrl()
    {
        return $this->getPhotoUrl(true);
    }

}
