<?php

namespace App\Packages\Capsule\Services;

use App\Packages\Capsule\Models\Capsule;
use App\Packages\Capsule\Models\CapsuleComment;
use App\Packages\Capsule\Models\CapsuleLike;
use App\Packages\Capsule\Models\CapsuleOpen;
use App\Packages\Capsule\Models\CapsuleSubscriber;
use App\Packages\Capsule\Models\CapsuleTaggedUser;
use App\Packages\Capsule\Repository\CapsuleLikeRepository;
use App\Packages\Capsule\Repository\CapsuleSubscriberRepository;
use App\Packages\Capsule\Repository\CapsuleTaggedUserRepository;
use App\Packages\User\Models\User;
use App\Packages\User\Notifications\NotificationComment;
use App\Packages\User\Notifications\NotificationHatchedMy;
use App\Packages\User\Notifications\NotificationHatchedSubscriber;
use App\Packages\User\Notifications\NotificationHatchedTagged;
use App\Packages\User\Notifications\NotificationLike;
use App\Packages\User\Notifications\NotificationSubscriber;
use App\Packages\User\Notifications\TypesNotification;

/**
 * Class CapsuleService
 * @package App\Packages\Capsule\Services
 */
class CapsuleService
{
	/**
	 * @var Capsule
	 */
	private $capsule;

	public function __construct(Capsule $capsule)
	{
		$this->capsule = $capsule;
	}

    /**
     * @param User $user
     * @return Capsule
     *
     * @throws \Exception
     */
	public function toggleLike(User $user)
	{
	    /** @var CapsuleLike $like */
		if ($like = CapsuleLikeRepository::init()->capsuleUserLike($this->capsule, $user)) {
		    $like->delete();
		} else {
			CapsuleLike::createLike($this->capsule, $user);

			/** Send notification for capsule like */
			NotificationLike::dispatch($this->capsule, $user)
                ->onQueue(TypesNotification::QUEUE_NOTIFICATIONS);
		}

        $this->capsule->refreshLikeCount();

		return $this->capsule;
	}

    /**
     * @param User $user
     *
     * @return Capsule
     *
     * @throws \Exception
     */
	public function toggleSubscriber(User $user)
	{
		if ($subscriber = CapsuleSubscriberRepository::init()->capsuleUserSubscriber($this->capsule, $user)) {
			$subscriber->delete();
		} else {
		    CapsuleSubscriber::createSubscriber($this->capsule, $user);

			/** Send notification for capsule like */
			NotificationSubscriber::dispatch($this->capsule, $user)
                ->onQueue(TypesNotification::QUEUE_NOTIFICATIONS);
		}

        $this->capsule->user->refreshSubscriptionCount();
        $this->capsule->refreshSubscribersCount();

		return $this->capsule;
	}

	/**
	 * @param User $user
	 * @param string $content
	 *
	 * @return CapsuleComment
	 */
	public function addComment(User $user, string $content)
	{
		$comment = CapsuleComment::createComment(
			$this->capsule,
			$user,
			$content
		);

		/** Send notification for capsule like */
		NotificationComment::dispatch($comment, $user)
            ->onQueue(TypesNotification::QUEUE_NOTIFICATIONS);

        $user->refreshCommentCount();
        $this->capsule->refreshCommentCount();

		return $comment;
	}

	public function editComment(CapsuleComment $comment, string $content)
    {
        $comment->content = $content;
        $comment->save();

        return $comment;
    }

    /**
     * @param CapsuleComment $comment
     *
     * @return CapsuleComment
     *
     * @throws \Exception
     */
	public function deleteComment(CapsuleComment $comment)
	{
	    $user = $comment->user;
	    $capsule = $comment->capsule;

		$comment->delete();

        $user->refreshCommentCount();
        $capsule->refreshCommentCount();

        return $comment;
	}

    /**
     * @param User $user
     *
     * @return Capsule
     */
	public function openCapsule(User $user)
	{
        $capsuleOpened = CapsuleOpen::isOpenedByUser($this->capsule, $user);
        if (!$capsuleOpened) {
            CapsuleOpen::createOpen($this->capsule, $user);
        }

		return $this->capsule;
	}

	/**
	 * @return Capsule
	 */
	public function hatchCapsule()
	{
		$this->capsule->hatchCapsule();

		/** Capsule owner notifications */
		NotificationHatchedMy::dispatch($this->capsule)
            ->onQueue(TypesNotification::QUEUE_NOTIFICATIONS);

        /** Tagged user notifications */
        $taggedUsers = CapsuleTaggedUserRepository::init()->capsuleTaggedUsers($this->capsule);
        $taggedUsers->each(function(User $taggedUser) {

            NotificationHatchedTagged::dispatch($this->capsule, $taggedUser)
                ->onQueue(TypesNotification::QUEUE_NOTIFICATIONS);
        });

		/** Subscriber capsule users notifications */
		$subscribers = CapsuleSubscriberRepository::init()->capsuleSubscribersNotTagged($this->capsule);
		$subscribers->each(function(User $subscriber) {

            NotificationHatchedSubscriber::dispatch($this->capsule, $subscriber)
                ->onQueue(TypesNotification::QUEUE_NOTIFICATIONS);
        });

		return $this->capsule;
	}
}
