<?php

namespace App\Policies;

use App\Album;
use App\Group;
use App\Permission;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class AlbumPolicy
{
    use HandlesAuthorization;

    /**
     * Create a new policy instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    public function before($user, $ability)
    {
        if ($user->is_admin)
        {
            // Admins can do anything
            return true;
        }
    }

    public function changePermissions(User $user, Album $album)
    {
        // Only the album's owner (or an admin, matched by the before() rule) can change permissions
        return $user->id == $album->user_id;
    }

    public function changePhotoMetadata(User $user, Album $album)
    {
        if ($user->id == $album->user_id)
        {
            // The album's owner and can do everything
            return true;
        }

        // Get the edit permission
        $permission = Permission::where([
            'section' => 'album',
            'description' => 'change-photo-metadata'
        ])->first();

        return $this->userHasPermission($user, $album, $permission);
    }

    public function delete(User $user, Album $album)
    {
        if ($user->id == $album->user_id)
        {
            // The album's owner and can do everything
            return true;
        }

        // Get the edit permission
        $permission = Permission::where([
            'section' => 'album',
            'description' => 'delete'
        ])->first();

        return $this->userHasPermission($user, $album, $permission);
    }

    public function deletePhotos(User $user, Album $album)
    {
        if ($user->id == $album->user_id)
        {
            // The album's owner and can do everything
            return true;
        }

        // Get the edit permission
        $permission = Permission::where([
            'section' => 'album',
            'description' => 'delete-photos'
        ])->first();

        return $this->userHasPermission($user, $album, $permission);
    }

    public function edit(User $user, Album $album)
    {
        if ($user->id == $album->user_id)
        {
            // The album's owner and can do everything
            return true;
        }

        // Get the edit permission
        $permission = Permission::where([
            'section' => 'album',
            'description' => 'edit'
        ])->first();

        return $this->userHasPermission($user, $album, $permission);
    }

    public function manipulatePhotos(User $user, Album $album)
    {
        if ($user->id == $album->user_id)
        {
            // The album's owner and can do everything
            return true;
        }

        // Get the edit permission
        $permission = Permission::where([
            'section' => 'album',
            'description' => 'manipulate-photos'
        ])->first();

        return $this->userHasPermission($user, $album, $permission);
    }

    public function uploadPhotos(User $user, Album $album)
    {
        if ($user->id == $album->user_id)
        {
            // The album's owner and can do everything
            return true;
        }

        // Get the edit permission
        $permission = Permission::where([
            'section' => 'album',
            'description' => 'upload-photos'
        ])->first();

        return $this->userHasPermission($user, $album, $permission);
    }

    public function view(User $user, Album $album)
    {
        if ($user->id == $album->user_id)
        {
            // The album's owner and can do everything
            return true;
        }

        // Get the edit permission
        $permission = Permission::where([
            'section' => 'album',
            'description' => 'view'
        ])->first();

        return $this->userHasPermission($user, $album, $permission);
    }

    private function userHasPermission(User $user, Album $album, Permission $permission)
    {
        if ($user->isAnonymous())
        {
            $query = Album::query()->join('album_anonymous_permissions', 'album_anonymous_permissions.album_id', '=', 'albums.id')
                ->join('permissions', 'permissions.id', '=', 'album_anonymous_permissions.permission_id')
                ->where([
                    ['albums.id', $album->id],
                    ['permissions.id', $permission->id]
                ]);

            return $query->count() > 0;
        }

        // If any of the user's groups are granted the permission
        /** @var Group $group */
        foreach ($user->groups as $group)
        {
            $groupPermission = $album->groupPermissions()->where([
                'group_id' => $group->id,
                'permission_id' => $permission->id
            ])->first();

            if (!is_null($groupPermission))
            {
                return true;
            }
        }

        // If the user is directly granted the permission
        $userPermission = $album->userPermissions()->where([
            'user_id' => $user->id,
            'permission_id' => $permission->id
        ])->first();

        if (!is_null($userPermission))
        {
            return true;
        }

        // Nope, no permission
        return false;
    }
}
