<?php

namespace App\Packages\Capsule\Models;

use App\Packages\Capsule\Repository\CapsuleRepository;
use App\Packages\Capsule\Services\CapsuleTeaserUploadService;
use App\Packages\Core\Models\Address;
use App\Packages\Core\Traits\RepositoryTrait;
use App\Packages\User\Models\User;
use App\Packages\User\Service\UserMentionService;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Carbon;
use Ramsey\Uuid\Uuid;

/**
 * Class Capsule
 * @package App\Packages\Capsule\Models
 *
 * @property int $id
 * @property string $uuid
 * @property int $user_id
 * @property int $preview_id
 * @property int $cropped_id
 * @property int $thumbnail_id
 * @property int $video_id
 * @property int $teaser_id
 * @property int $address_id
 *
 * @property string $status
 * @property boolean $is_private
 * @property boolean $is_complete
 * @property boolean $is_complete_upload
 * @property boolean $blocked // @TODO: Refactore to is_blocked
 * @property string $caption
 *
 * @property int $search_setting
 * @property int $search_position
 * @property int $suggested_position
 *
 * @property int $count_likes
 * @property int $count_comments
 * @property int $count_subscribers
 * @property int $count_tagged_users
 * @property int $count_reports
 *
 * @property string|Carbon $open_at
 * @property string|Carbon|null $set_suggested
 * @property string|Carbon $created_at
 * @property string|Carbon $updated_at
 * @property string|Carbon $deleted_at
 *
 * @property Address $address
 * @property User $user
 * @property CapsuleVideo $video
 * @property CapsuleTeaser $teaser
 * @property CapsulePreview $thumbnail
 * @property CapsulePreview $preview
 * @property CapsulePreview $cropped
 * @property CapsuleStats $share_stats
 *
 * @property-read string $share_key
 *
 * @method static CapsuleRepository repository()
 */
class Capsule extends Model
{
	const STATUS_OPENED = 0;
	const STATUS_HATCHED = 1;
	const STATUS_LOCKED = 2;

	const PRIVACY_PUBLIC = 0;
	const PRIVACY_PRIVATE = 1;

	/** Search setting values  */
	const SEARCH_DEFAULT = 0;
	const SEARCH_SHOW_FOR_ALL = 1;
	const SEARCH_SHOW_FOR_NEW = 2;

	use RepositoryTrait;
	use SoftDeletes;

	/** @var string */
	public static $repositoryClass = CapsuleRepository::class;

	/** @var string */
	protected $table = 'table_capsule';

	protected $dates = [
		'open_at',
        'set_suggested',
		'created_at',
		'updated_at',
		'deleted_at',
	];

	public static function boot()
	{
		parent::boot();
		static::creating(function ($model) {
			/** @var static $model */
			$model->uuid = Uuid::uuid4();
		});
	}

	public function getShareKeyAttribute() {
	    return hash('crc32', $this->id);
    }

	/**
	 * @param User $user
	 *
	 * @return Capsule
	 */
	public static function createBlankCapsule(User $user)
	{
		$capsule = new Capsule();
		$capsule->user_id = $user->id;
		$capsule->count_subscribers = 0;
		$capsule->count_likes = 0;
		$capsule->count_comments = 0;
		$capsule->count_tagged_users = 0;
		$capsule->status = static::STATUS_LOCKED;
		$capsule->is_complete = false;
		$capsule->save();

		return $capsule;
	}

	/**
	 * @param CapsuleVideo $capsuleVideo
	 *
	 * @return $this
	 */
	public function setMediaFile(CapsuleVideo $capsuleVideo)
	{
		$this->video_id = $capsuleVideo->id;
		$this->save();

		return $this;
	}

	/**
	 * @return bool
	 */
	public function isLocked()
	{
		return $this->status == static::STATUS_LOCKED;
	}

	/**
	 * @return string
	 */
	public function getFormattedOpenDate()
	{
		return ($this->open_at instanceof Carbon) ? $this->open_at->format('Y-m-d H:i:s') : '';
	}

    public function getFormattedOpenTime() {
        return ($this->open_at instanceof Carbon) ? $this->open_at->format('M d, Y H:i:s') : '';
    }

    public function getDiffOpenDate() {
	    $diff = $this->open_at->diffAsCarbonInterval();
	    $str = '';

	    $y = $diff->y;
	    $m = $diff->m;
	    $d = $diff->d;

        $str .= $y ? $y .'Y ' : '';
        $str .= $m ? $m .'M ' : '';
        $str .= $d ? $d .'D ' : '';

        return $str;
    }

    /**
     * @return string
     */
    public function getFormattedCreatedDate()
    {
        return ($this->created_at instanceof Carbon) ? $this->created_at->format('Y-m-d H:i:s') : '';
    }

    public function getPublicCreatedDate() {
        return ($this->created_at instanceof Carbon) ? $this->created_at->format('F d, Y') : '';
    }

	/**
	 * @return bool
	 */
	public function canBeOpened()
	{
		return ($this->open_at <= now());
	}

	/**
	 * @return int
	 */
	public function determineCapsuleStatus()
	{
		return ($this->canBeOpened())
			? Capsule::STATUS_HATCHED
			: Capsule::STATUS_LOCKED;
	}

	/**
	 * @return $this
	 */
	public function hatchCapsule()
	{
		$this->status = Capsule::STATUS_HATCHED;
		$this->save();

		return $this;
	}

	/**
	 * @return string
	 */
	public function getCapsuleStatusAttribute()
	{
		$statuesText = [
			static::STATUS_OPENED => trans('admin.capsule.opened'),
			static::STATUS_HATCHED => trans('admin.capsule.hatched'),
			static::STATUS_LOCKED => trans('admin.capsule.locked'),
		];

		return $statuesText[$this->status];
	}

	/**
	 * @return string
	 */
	public function getMediaUrl()
	{
		if (!$this->video) {
			return '';
		}

		return videoAwsPathCDN($this->video->aws_key);
	}

	public function getTeaserUrl()
    {
        if (!$this->teaser) {
            return '';
        }

        $teaserUploadService = app(CapsuleTeaserUploadService::class);

        if ($teaserUploadService->checkIfExist($this->teaser->aws_key)) {
            return teaserAwsPathCDN($this->teaser->aws_key);
        }

        return '';
    }

    /**
     * @return string
     */
	public function getInviteText()
    {
        $caption = UserMentionService::normalizeString(trim($this->caption));

        if (empty($caption)) return __('main.sms_capsule_invite_no_caption');

        if (mb_strlen($caption) >= 97) {
            $message = mb_substr($caption, 0, 97);
            return str_replace('{{caption}}', '“'.$message.'”...', __('main.sms_capsule_invite_caption'));
        }

        return str_replace('{{caption}}', '“'.$caption.'”', __('main.sms_capsule_invite_caption'));
    }

    /**
     * @return $this
     */
	public function refreshLikeCount()
    {
        $this->count_likes = $this->capsuleLikes()->count();
        $this->save();

        return $this;
    }

    /**
     * @return $this
     */
    public function refreshCommentCount()
    {
        $this->count_comments = $this->capsuleComments()->count();
        $this->save();

        return $this;
    }

    /**
     * @return $this
     */
    public function refreshSubscribersCount()
    {
        $this->count_subscribers = $this->capsuleSubscribers()->count();
        $this->save();

        return $this;
    }

    /**
     * @return $this
     */
    public function refreshTaggedUserCount()
    {
        $this->count_tagged_users = $this->taggedUsers()->count();
        $this->save();

        return $this;
    }

    /**
     * @return $this
     */
    public function refreshReportCount()
    {
        $this->count_reports = $this->reports()->count();
        $this->save();

        return $this;
    }

	/**
	 * @return BelongsToMany
	 */
	public function capsuleSubscribers()
	{
		return $this->belongsToMany(User::class, 'table_capsule_subscriber', 'capsule_id', 'user_id');
	}

	/**
	 * @return HasMany
	 */
	public function capsuleComments()
	{
		return $this->hasMany(CapsuleComment::class, 'capsule_id', 'id');
	}

	/**
	 * @return BelongsToMany
	 */
	public function capsuleLikes()
	{
		return $this->belongsToMany(User::class, 'table_capsule_like', 'capsule_id', 'user_id');
	}

	/**
	 * @return BelongsTo
	 */
	public function user()
	{
		return $this->belongsTo(User::class, 'user_id')
            ->with(['avatar']);
	}

	/**
	 * @return BelongsTo
	 */
	public function video()
	{
		return $this->belongsTo(CapsuleVideo::class, 'video_id');
	}

    /**
     * @return BelongsTo
     */
	public function teaser()
    {
        return $this->belongsTo(CapsuleTeaser::class, 'teaser_id');
    }

	/**
	 * @return BelongsTo
	 */
	public function address()
	{
		return $this->belongsTo(Address::class, 'address_id');
	}

	/**
	 * @return BelongsTo
	 */
	public function preview()
	{
		return $this->belongsTo(CapsulePreview::class, 'preview_id');
	}

	/**
	 * @return BelongsTo
	 */
	public function thumbnail()
	{
		return $this->belongsTo(CapsulePreview::class, 'thumbnail_id');
	}

    /**
     * @return BelongsTo
     */
    public function cropped()
    {
        return $this->belongsTo(CapsulePreview::class, 'cropped_id');
    }

	/**
	 * @return BelongsToMany|CapsuleTaggedUser[]
	 */
	public function taggedUsers()
	{
		return $this->belongsToMany(User::class, 'table_capsule_tagged_user', 'capsule_id', 'user_id');
	}

    /**
     * @return HasMany
     */
	public function reports()
    {
        return $this->hasMany(CapsuleReport::class, 'capsule_id');
    }

    /**
     * @return HasOne
     */
    public function block()
    {
        return $this->hasOne(CapsuleBlock::class, 'capsule_id');
    }

    /**
     * @return HasOne
     */
    public function share_stats() {
        return $this->hasOne(CapsuleStats::class, 'capsule_id');
    }
}
