<?php
namespace App\Models\Admin;

use Encore\Admin\Traits\AdminBuilder;
use Encore\Admin\Traits\ModelTree;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class AdminPermission extends Model
{
    use AdminBuilder, ModelTree {
        ModelTree::boot as treeBoot;
    }

    protected $table = 'admin_permissions';

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);

        $this->setParentColumn('parent_id');
        $this->setOrderColumn('listorder');
        $this->setTitleColumn('name');
    }

    /**
     * @var array
     */
    protected $fillable = ['name', 'slug', 'http_method', 'http_path', 'parent_id', 'type', 'listorder', 'menu_id'];

    /**
     * @var array
     */
    public static $httpMethods = [
        'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD',
    ];



    public function children()
    {
        return $this->hasMany(AdminPermission::class, 'parent_id')->orderBy('listorder');
    }

    /**
     * Permission belongs to many roles.
     *
     * @return BelongsTo
     */
    public function menu() : BelongsTo
    {
        return $this->belongsTo(AdminMenu::class, 'menu_id');
    }

    /**
     * Permission belongs to many roles.
     *
     * @return BelongsToMany
     */
    public function roles() : BelongsToMany
    {
        $pivotTable = config('admin.database.role_permissions_table');

        $relatedModel = config('admin.database.roles_model');

        return $this->belongsToMany($relatedModel, $pivotTable, 'permission_id', 'role_id');
    }

    /**
     * If request should pass through the current permission.
     *
     * @param Request $request
     *
     * @return bool
     */
    public function shouldPassThrough(Request $request) : bool
    {
        if (empty($this->http_path)) {
            return false;
        }

        $method = $this->http_method;

        $matches = array_map(function ($path) use ($method) {
            $path = trim(config('admin.route.prefix'), '/').$path;

            if (Str::contains($path, ':')) {
                list($method, $path) = explode(':', $path);
                $method = explode(',', $method);
            }

            return compact('method', 'path');
        }, explode("\r\n", $this->http_path));

        foreach ($matches as $match) {
            if ($this->matchRequest($match, $request)) {
                return true;
            }
        }

        return false;
    }

    /**
     * If a request match the specific HTTP method and path.
     *
     * @param array   $match
     * @param Request $request
     *
     * @return bool
     */
    protected function matchRequest(array $match, Request $request) : bool
    {
        if (!$request->is(trim($match['path'], '/'))) {
            return false;
        }

        $method = collect($match['method'])->filter()->map(function ($method) {
            return strtoupper($method);
        });

        return $method->isEmpty() || $method->contains($request->method());
    }


    /**
     * @param $method
     */
    public function setHttpMethodAttribute($method)
    {
        if (is_array($method)) {
            $this->attributes['http_method'] = implode(',', $method);
        }
    }

    /**
     * @param $method
     *
     * @return array
     */
    public function getHttpMethodAttribute($method)
    {
        if (is_string($method)) {
            return array_filter(explode(',', $method));
        }

        return $method;
    }

    /**
     * Detach models from the relationship.
     *
     * @return void
     */
    protected static function boot()
    {
        static::treeBoot();

        static::deleting(function ($model) {
            $model->roles()->detach();
        });
    }


    /**
     * 菜单封装装.
     * return object
     */
    public static function permissionArr()
    {
        $order="`listorder` = 0,`listorder`";
        $permissions = self::orderByRaw($order)->select(['id', 'parent_id', 'subsite_id', 'name'])->get();
        $permission_array=[];
        foreach ($permissions as $permission) {
            $permission_array[$permission['id']]=$permission;
        }
        $permission_res=[];
        foreach ($permission_array as $key => $value) {
            if (get_subsite_id() == 0) {
                $permission_res[$key] = self::getName($value, $permission_array);
            } elseif ($value['subsite_id'] == -1 || $value['subsite_id'] == get_subsite_id()) {
                $permission_res[$key] = self::getName($value, $permission_array);
            }
        }
        return $permission_res;
    }

    public static function getName($value, $list)
    {
        if ($value['parent_id'] == 0) {
            return $value['name'];
        } elseif (isset($list[$value['parent_id']])) {
            return self::getName($list[$value['parent_id']], $list)."-{$value['name']}";
        }
        return "";
    }
}