<?php


namespace ModulesGarden\ProxmoxAddon\App\Repositories;


use ModulesGarden\ProxmoxAddon\Core\Models\ModuleSettings\Model;

/**
 * Class ModuleSettingsRepository
 * @package ModulesGarden\ProxmoxAddon\App\Repositories
 * @property $consoleHost
 * @method isPermissionStart()
 * @method isPermissionReboot()
 * @method isPermissionStop()
 * @method isPermissionShutdown()
 * @method isPermissionNovnc()
 * @method isPermissionSpice()
 * @method isPermissionXtermjs()
 * @method isPermissionMigrate()
 * @method isPermissionInformation()
 * @method isPermissionIpAddresses()
 * @method isPermissionIpSet()
 * @method isPermissionReinstall()
 * @method isPermissionGraph()
 * @method isPermissionUserDetails()
 * @method isPermissionAccountResources()
 * @method isPermissionVms()
 */
class ModuleSettingRepository
{

    protected $fillable = ['consoleHost','consoleApiKey','permissionStart', 'permissionReboot','permissionStop','permissionShutdown','permissionNovnc','permissionSpice',
        'permissionXtermjs','permissionMigrate','permissionInformation','permissionIpAddresses','permissionIpSet','permissionReinstall','permissionGraph','permissionUserDetails',
        'permissionAccountResources','permissionVms'];
    protected $encryption = ['consoleApiKey'];
    /**
     *
     * @var Model[]
     */
    protected $entries;
    protected $force = false;

    public function getForce()
    {
        return $this->force;
    }

    public function setForce($force)
    {
        $this->force = $force;
        return $this;
    }

    public function isEmpty()
    {
        return empty($this->entries);
    }

    public function flush()
    {
        Model::delete();
        return $this;
    }

    /**
     * Delete keys
     * @param string $keys
     * @param array $keys
     * @return $this
     */
    public function forget($keys)
    {
        if (is_array($keys))
        {
            Model::whereIn('setting', $keys)
                ->delete();
            foreach ($keys as $k)
            {
                unset($this->entries[$k]);
            }
        }
        else
        {
            Model::where('setting', $keys)
                ->limit(1)
                ->delete();
            unset($this->entries[$keys]);
        }
        return $this;
    }

    public function all($default = [])
    {
        $this->force = true;
        foreach (Model::pluck('value', 'setting')->all() as $key => $value)
        {
            if(in_array($key, $this->encryption)){
                $value = decrypt($value);
            }
            $this->entries[$key] = $value;
        }
        if (!$this->isEmpty())
        {
            return $this->entries;
        }
        return $default;
    }

    public function store(array $values)
    {
        foreach ($values as $k => $v)
        {
            $this->set($k, $v);
        }
        return $this;
    }

    public function exist($key)
    {
        return Model::where('setting', $key)
                ->count() > 0;
    }

    public function set($key, $value)
    {
        $this->entries[$key] = $value;
    }

    public function __isset($key)
    {
        return isset($this->entries[$key]);
    }

    public function get($key, $default = null)
    {
        if (isset($this->entries[$key]))
        {
            return $this->entries[$key];
        }
        else
        {
            if (!$this->force)
            {
                $this->getEntery($key);
                if (isset($this->entries[$key]))
                {
                    return $this->entries[$key];
                }
            }
        }
        return $default;
    }

    /**
     *
     * @param string $key
     * @return Model
     */
    protected function getEntery($key)
    {
        if (isset($this->entries[$key]))
        {
            return $this->entries[$key];
        }
        else
        {
            if (!$this->force)
            {
                $this->entries[$key] = Model::ofSetting($key)
                    ->value("value");
                return $this->entries[$key];
            }
        }
    }

    public function fill(array $setting)
    {
        $this->entries = $setting;
        return $this;
    }

    public function fillAndSave(array $setting)
    {
        $this->entries = $setting;
        foreach ($this->entries as $key => $value)
        {
            //fillable
            if(!in_array($key, $this->fillable)){
                unset($this->entries[$key]);
                continue;
            }
            //encrypt
            if(in_array($key, $this->encryption)){
                $value =  encrypt($value);
            }
            $setting =  Model::firstOrNew([
                'setting' => $key
            ]);
            $setting->value      = $value;
            $setting->save();
        }
        return $this;
    }

    public function save()
    {
        foreach ($this->entries as $key => $value)
        {
            $setting             = new Model();
            $setting->setting    = $key;
            $setting->value      = $value;
            $setting->save();
        }
    }

    public function __get($name)
    {
        return  $this->get($name);
    }

    public function setConsoleApiKey($consoleApiKey){
        $this->set('consoleApiKey',encrypt($consoleApiKey));
        return $this;
    }

    public function getConsoleApiKey()
    {
        return decrypt($this->consoleApiKey);
    }

    public function hasConsoleApiKey()
    {
        return decrypt($this->consoleApiKey) !="";
    }

    public function __call($method, $args)
    {
        $name = preg_replace('/^is/',"",$method);
        $name = lcfirst($name );
        return $this->get($name) != "off";
    }

    public function isPermissionServiceActions(){
        return $this->isPermissionStart() ||
        $this->isPermissionReboot() ||
        $this->isPermissionStop() ||
        $this->isPermissionShutdown() ||
        $this->isPermissionNovnc() ||
        $this->isPermissionSpice() ||
        $this->isPermissionXtermjs() ||
        $this->isPermissionMigrate() ;
    }

}