<?php

namespace Fivable\Buildable\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Auth;

class BuildableActivity extends Model
{
    use SoftDeletes;

    /* Columns that are mass-assignable */
    protected $fillable = ['user_id', 'page_id', 'type_mask', 'message'];
    /* Columns to convert to Carbon */
    protected $dates = ['created_at', 'updated_at'];


    /** Relationships
     * ----------------*/

    /**
     * Return the User associated with this BuildableActivity
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user() : BelongsTo
    {
        return $this->belongsTo('App\User');
    }

    /**
     * Return the BuildablePage with this BuildableActivity
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function buildable_page() : BelongsTo
    {
        return $this->belongsTo('Fivable\Buildable\Models\BuildablePage');
    }


    /** CRUD Helpers
     * ---------------*/

    /**
     * @param string $message
     * @param array|string $type
     * @return BuildableActivity
     */
     public static function log(string $message, $type = ['feed', 'audit']) : BuildableActivity
     {
         return static::create([
             'user_id' => Auth::user() ?? NULL,
             'type_mask' => static::toTypeMask($type),
             'message' => $message
         ]);
     }

    /**
     * Generate an index Query Builder using options
     * @param int|NULL $days
     * @param array|NULL $types
     * @return Builder
     */
     public static function indexFor(int $days = NULL, array $types = NULL)
     {
         return static::whereNull('deleted_at')
                    ->when(!is_null($days), function($query) use ($days) {
                        $query->where('created_at', '>=', Carbon::now()->subDays($days));
                    })
                    ->when(!is_null($types), function($query) use ($types) {
                        $query->whereRaw('type_mask & ' . static::toTypeMask($types));
                    });
     }


    /** Misc Helpers
     * ---------------*/

    /**
     * @param  array|string|NULL $type
     * @return int  BuildableActivity type_mask
     */
    public static function toTypeMask($type = NULL) : int
    {
        $mask = 0;
        $type = is_string($type) ? [$type] : $type;
        foreach ($type as $string) {
            switch ($string) {
                case 'feed':
                    $mask |= 1;
                    break;
                case 'audit':
                    $mask |= 2;
                    break;
                case NULL:
                    return NULL;
                    break;
            }
        }
        return $mask;
    }


    /** Status Helpers
     * -------------------------*/

    /**
     * Returns whether or not this BuildableActivity is a 'feed' type
     * @return bool
     */
    public function isFeed() : bool
    {
        return !!($this->type_mask & 1);
    }

    /**
     * Returns whether or not this BuildableActivity is an 'audit' type
     * @return bool
     */
    public function isAudit() : bool
    {
        return !!($this->type_mask & 2);
    }
}
