<?php

/* * ********************************************************************
 * ProxmoxVPS product developed. (2019-09-06)
 * *
 *
 *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
 *  CONTACT                        ->       contact@modulesgarden.com
 *
 *
 * This software is furnished under a license and may be used and copied
 * only  in  accordance  with  the  terms  of such  license and with the
 * inclusion of the above copyright notice.  This software  or any other
 * copies thereof may not be provided or otherwise made available to any
 * other person.  No title to and  ownership of the  software is  hereby
 * transferred.
 *
 *
 * ******************************************************************** */

namespace ModulesGarden\ProxmoxAddon\App\Repositories;

use ModulesGarden\ProxmoxAddon\App\Models\ServerConfiguration;
use ModulesGarden\ProxmoxAddon\Core\Helper\WhmcsVersionComparator;

/**
 * Description of ServerConfigurationRepository
 *
 * @author Pawel Kopec <pawelk@modulesgarden.com>
 * @version 1.0.1
 */
abstract class AbstractServerConfigurationRepository
{
    protected $serverId;
    /**
     *
     * @var ServerConfiguration[]
     */
    protected $entries;
    protected $force = false;

    public function __construct($serverId)
    {
        if (!is_numeric($serverId) || $serverId <= 0)
        {
            throw new \InvalidArgumentException(sprintf("Server id: %s is invalid", $serverId));
        }
        $this->serverId = $serverId;
    }

    /**
     * @return int|string
     */
    public function getServerId()
    {
        return $this->serverId;
    }

    /**
     * @param int|string $serverId
     */
    public function setServerId($serverId)
    {
        $this->serverId = $serverId;
    }

    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()
    {
        ServerConfiguration::ofServerId($this->serverId)
                          ->delete();
        return $this;
    }

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

    public function all($default = [])
    {
        $this->force = true;
        $decode = !WhmcsVersionComparator::isWhmcsVersionHigherOrEqual('8.0.0');
        foreach (ServerConfiguration::ofServerId($this->serverId)->pluck('value', 'setting')->all() as $key => $value)
        {
            if($decode){
                $value                = json_decode($value, true);
            }
            $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 ServerConfiguration::ofServerId($this->serverId)
                ->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 ServerConfiguration
     */
    protected function getEntery($key)
    {
        if (isset($this->entries[$key]))
        {
            return $this->entries[$key];
        }
        else
        {
            if (!$this->force)
            {
                $this->entries[$key] = ServerConfiguration::ofServerId($this->serverId)
                    ->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)
        {
            $setting =  ServerConfiguration::firstOrNew([
                'server_id' => $this->serverId,
                'setting' => $key
            ]);
            $setting->value      = $value;
            $setting->server_id = $this->serverId;
            $setting->save();
        }


        return $this;
    }

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

}