<?php

namespace ModulesGarden\ProxmoxAddon\App\Listeners\Cloud;

use Illuminate\Database\Capsule\Manager as DB;
use MGProvision\Proxmox\v2\Api;
use MGProvision\Proxmox\v2\models\Features;
use ModulesGarden\ProxmoxAddon\App\Events\Cloud\LxcUpdateEvent;
use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
use ModulesGarden\ProxmoxAddon\App\Traits\Cloud\VmNetwork;
use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;

class LxcUpdateListener extends VmListener
{
    use VmNetwork;

    public function handle(LxcUpdateEvent $event)
    {
        $this->event    = $event;
        $this->api();
        $this->initVmAnVmModel();
        try
        {
            Api::beginTransaction();
            DB::beginTransaction();
            //Disk size
            $diskSize = $this->event->getConfig()['disk'];
            $masterHardDiskSize = sl('Vm')->getVm()->getMasterHddSize();
            if ($diskSize && $diskSize - $masterHardDiskSize > 0)
            {
                $disk = ['disk' => "rootfs", 'size' => sprintf('+%sG', $diskSize - $masterHardDiskSize)];
                sl('Vm')->getVm()->resize($disk);
            }
            //init container
            $container = [];
            //hostname
            if ($hostname = $this->event->getVmModel()->name)
            {
                $container['hostname'] = $this->event->getVmModel()->name;
            }
            //description
            $container['description'] =  htmlspecialchars($this->event->getConfig()['description'], ENT_QUOTES);
            if ($this->event->getVmModel()->cpulimit )
            {
                $container['cpulimit'] = $this->event->getVmModel()->cpulimit ;
            }
            //Memory
            $container['memory'] = $this->event->getVmModel()->memory;
            //SWAP
            $container['swap'] = $this->event->getVmModel()->swap;
            //cpuunits
            $container['cpuunits'] = $this->event->getVmModel()->cpuunits;
            //Name servers
            $ns = [];
            for ($i = 0; $i <= 1; $i++)
            {
                $n = $this->event->getConfig()['nameserver'][$i];
                if (!empty($n) && !filter_var($n, FILTER_VALIDATE_IP))
                {
                    $n = gethostbyname($n);
                }
                if (!empty($n) && filter_var($n, FILTER_VALIDATE_IP))
                {
                    $ns[] = $n;
                }
            }
            if ($ns)
            {
                $container['nameserver'] = implode(" ", $ns);
            }
            if (sl('Vm')->getVm()->isRunning() && sl('Vm')->getVm()->config()['nameserver'] == $container['nameserver'])
            {
                unset($container['nameserver']);
            }
            //cores
            if ($this->event->getVmModel()->cores)
            {
                $container['cores'] = $this->event->getVmModel()->cores;
            }
            //arch
            if ($this->configuration()->getArch())
            {
                $container['arch'] = $this->configuration()->getArch();
            }
            //cmode
            if ($this->configuration()->getCmode() && !sl('Vm')->getVm()->isRunning())
            {
                $container['cmode'] = $this->configuration()->getCmode() ;
            }
            //console
            if ($this->configuration()->isConsole() && !sl('Vm')->getVm()->isRunning())
            {
                $container['console'] = 1;
            }
            //onboot
            if ($this->configuration()->isOnboot())
            {
                $container['onboot'] = 1;
            }
            //protection
            if ($this->configuration()->isProtection())
            {
                $container['protection'] = 1;
            }
            //startup
            if ($this->configuration()->getStartup())
            {
                $container['startup'] = $this->configuration()->getStartup();
            }
            //tty
            if ($this->configuration()->getTty() && !sl('Vm')->getVm()->isRunning())
            {
                $container['tty'] = $this->configuration()->getTty();
            }
            //Features
            $features = new Features();
            //Keyctl
            if($this->configuration()->isFeatureKeyctl() && sl('Vm')->getVm()->config()['unprivileged']){
                $features->setKeyctl(1);
            }
            //Nesting
            if($this->configuration()->isFeatureNesting() ){
                $features->setNesting(1);
            }
            //NFS
            if($this->configuration()->isFeatureNfs() ){
                $features->addNfs();
            }
            //CIFS
            if($this->configuration()->isFeatureCifs() ){
                $features->addCifs();
            }
            //Fuse
            if($this->configuration()->isFeatureFuse() ){
                $features->setFuse(1);
            }
            //Mknod
            if($this->configuration()->isFeatureMknod() ){
                $features->setMknod(1);
            }
            $container[Features::ID] = $features->asConfig();
            //Network create & update
            $container += $this->createNetwork();
            $container += $this->updateNetwork();
            //Update container
            sl('Vm')->getVm()->updateConfig($container);
            DB::commit();
        }
        catch (\Exception $ex)
        {
            echo $ex->getMessage();
            DB::rollBack();
            Api::commit();
            throw $ex;
        }

    }

    private function updateNetwork()
    {
        $container         = [];
        $updateNetworkRate = !$this->configuration()->getMinimumRate() || !$this->hosting()->isBandwidthOverageUsage();
        $rate      = null;
        if ($this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE,$this->configuration()->getRate()) &&
            $this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE,$this->configuration()->getRate())  != "-1")
        {
            $rate = $this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE,$this->configuration()->getRate()) ;
        }
        foreach (sl('Vm')->getVm()->getNetworkDevices($this->configuration()->getBridge()) as $entity)
        {
            $hash = $entity->getHashCode();
            if ($updateNetworkRate && $entity->getRate() != $rate)
            {
                $entity->setRate($rate);
            }
            if ($hash != $entity->getHashCode())
            {
                $container[$entity->getId()] = $entity->asConfig();
            }
        }
        return $container;
    }


}