<?php

namespace App;

use App\AlbumSources\IAlbumSource;
use App\AlbumSources\LocalFilesystemSource;
use App\Helpers\MiscHelper;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;

class Album extends Model
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'description', 'url_alias', 'user_id', 'storage_id', 'default_view', 'parent_album_id', 'url_path', 'is_permissions_inherited'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
    ];

    /**
     * Gets an array of parent items
     * @return array
     */
    public function albumParentTree()
    {
        $albums = [];
        $current = $this;

        while (!is_null($current))
        {
            $albums[] = $current;

            $current = $current->parent;
        }

        $albums = array_reverse($albums);
        return $albums;
    }

    public function anonymousPermissions()
    {
        return $this->belongsToMany(Permission::class, 'album_anonymous_permissions');
    }

    public function cameras()
    {
        return DB::table('photos')
            ->where([
                ['album_id', $this->id],
                ['camera_make', '!=', ''],
                ['camera_model', '!=', '']
            ])
            ->groupBy('camera_make', 'camera_model', 'camera_software')
            ->select('camera_make', 'camera_model', 'camera_software', DB::raw('count(*) as photo_count'))
            ->orderBy('photo_count', 'desc')
            ->orderBy('camera_make')
            ->orderBy('camera_model')
            ->orderBy('camera_software')
            ->get();
    }

    public function children()
    {
        return $this->hasMany(Album::class, 'parent_album_id')->withCount('photos');
    }

    public function doesGroupHavePermission(Group $group, Permission $permission)
    {
        return $this->groupPermissions()->where([
                'group_id' => $group->id,
                'permission_id' => $permission->id
            ])->count() > 0;
    }

    public function doesUserHavePermission($user, Permission $permission)
    {
        // User will be null for anonymous users
        if (is_null($user))
        {
            return $this->anonymousPermissions()->where(['permission_id' => $permission->id])->count() > 0;
        }
        else
        {
            return $this->userPermissions()->where([
                    'user_id' => $user->id,
                    'permission_id' => $permission->id
                ])->count() > 0;
        }
    }

    /**
     * Try and locate the parent album ID that permissions are inherited from.
     * @return integer
     */
    public function effectiveAlbumIDForPermissions()
    {
        $current = $this;

        while (!is_null($current->parent_album_id))
        {
            if ($current->is_permissions_inherited)
            {
                $current = $current->parent;
            }
            else
            {
                break;
            }
        }

        if (is_null($current->parent_album_id) && $current->is_permissions_inherited)
        {
            // Use default permissions list
            return 0;
        }

        return $current->id;
    }

    public function generateAlias()
    {
        $this->url_alias = MiscHelper::capitaliseWord(preg_replace('/[^a-z0-9\-]/', '-', strtolower($this->name)));
    }

    public function generateUrlPath()
    {
        $parts = [];
        $current = $this;

        while (!is_null($current))
        {
            $parts[] = $current->url_alias;

            $current = $current->parent;
        }

        $parts = array_reverse($parts);
        $this->url_path = join('/', $parts);
    }

    /**
     * @return IAlbumSource
     */
    public function getAlbumSource()
    {
        $fullClassName = sprintf('App\AlbumSources\%s', $this->storage->source);

        /** @var IAlbumSource $source */
        $source = new $fullClassName;
        $source->setAlbum($this);
        $source->setConfiguration($this->storage);

        return $source;
    }

    public function groupPermissions()
    {
        return $this->belongsToMany(Permission::class, 'album_group_permissions');
    }

    /**
     * Returns true if this album is a descendant of the given album.
     * @param Album $album
     */
    public function isChildOf(Album $album)
    {
        $currentAlbum = $this;
        while (!is_null($currentAlbum))
        {
            if ($currentAlbum->parent_album_id == $album->id)
            {
                return true;
            }

            $currentAlbum = Album::where('id', $currentAlbum->parent_album_id)->first();
        }

        return false;
    }

    public function parent()
    {
        return $this->belongsTo(Album::class, 'parent_album_id');
    }

    public function photos()
    {
        return $this->hasMany(Photo::class);
    }

    public function redirects()
    {
        return $this->hasMany(AlbumRedirect::class);
    }

    public function storage()
    {
        return $this->belongsTo(Storage::class);
    }

    public function thumbnailUrl($thumbnailName)
    {
        /** @var Photo $photo */
        $photo = $this->photos()
            ->inRandomOrder()
            ->first();

        if (!is_null($photo))
        {
            return $photo->thumbnailUrl($thumbnailName);
        }

        // See if any child albums have an image
        $images = [];

        /** @var Album $childAlbum */
        foreach ($this->children as $childAlbum)
        {
            if ($childAlbum->photos()->count() > 0)
            {
                $images[] = $childAlbum->thumbnailUrl($thumbnailName);
            }
        }

        if (count($images) == 0)
        {
            // Rotate standard images
            $images = [
                asset('themes/base/images/empty-album-1.jpg'),
                asset('themes/base/images/empty-album-2.jpg'),
                asset('themes/base/images/empty-album-3.jpg')
            ];
        }

        return $images[rand(0, count($images) - 1)];
    }

    public function url()
    {
        if (is_null($this->url_path))
        {
            $this->generateUrlPath();
            $this->save();
        }

        return route('viewAlbum', $this->url_path);
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function userPermissions()
    {
        return $this->belongsToMany(Permission::class, 'album_user_permissions');
    }
}