<?php


namespace ModulesGarden\ProxmoxAddon\App\Services\Vps;


use MGProvision\Proxmox\v2\models\IpConfig;
use MGProvision\Proxmox\v2\models\Kvm;
use MGProvision\Proxmox\v2\models\Lxc;
use MGProvision\Proxmox\v2\models\NetworkDeviceKvm;
use MGProvision\Proxmox\v2\models\NetworkDeviceLxc;
use ModulesGarden\ProxmoxAddon\App\Enum\Vps\ConfigurableOption;
use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
use ModulesGarden\ProxmoxAddon\Core\UI\Traits\WhmcsParams;

class VmIpAddressConveter
{
    use WhmcsParams;
    use ProductService;

    /**
     * @var Kvm|Lxc|null
     */
    protected $vm;

    /**
     * @var NetworkDeviceKvm[]
     */
    protected $networkDevices;

    /**
     * @var IpConfig[]
     */
    protected $ipConfigs=[];

    /**
     * @var VmIpAddress[]
     */
    protected $vmIpAddress;

    /**
     * VmIpAddressConveter constructor.
     * @param Kvm|Lxc|null $vm
     * @param VmIpAddress[] $vmIpAddress
     */
    public function __construct( array $vmIpAddress, $vm=null)
    {
        $this->vmIpAddress = $vmIpAddress;
        $this->vm = $vm;
    }

    public function convert(){
        $rate      = $this->getRate();
        $networkId = $this->freeNetworDeviceId();
        foreach ($this->vmIpAddress as $vmIpAddress){
            $bridge = $this->getBridge($vmIpAddress);
            if ($this->configuration()->isQemu())
            {
                $networkDevice = new NetworkDeviceKvm('net' . $networkId);
                $networkDevice->setBridge($bridge)
                    ->setRate($rate)
                    ->setFirewall($this->configuration()->isNetworkFirewall() ? 1 : 0);
                //ip config
                $ipConfig = new IpConfig('ipconfig' . $networkId);
                //ipv4
                if(!preg_match("/\:/",$vmIpAddress->ip)){
                    $ipConfig->setIp(trim($vmIpAddress->ip))
                        ->setCidr(trim($vmIpAddress->cidr))
                        ->setGw(trim($vmIpAddress->gateway));
                }else{
                    //ipv6
                    $ipConfig->setIp6(trim($vmIpAddress->ip))
                        ->setCidr6(trim($vmIpAddress->cidr))
                        ->setGw6(trim($vmIpAddress->gateway));
                }
                $networkDevice->setTag($vmIpAddress->tag)
                    ->setMacAddress($vmIpAddress->mac_address)
                    ->setTrunks($vmIpAddress->trunks)
                    ->setQueues(trim($this->configuration()->getQueues()));
                if(filter_var($vmIpAddress->ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)){
                    $networkDevice->setModel($this->configuration()->getNetworkModel());
                }else{
                    //private
                    $networkDevice->setModel($this->configuration()->getNetworkPrivateModel());
                }
                $this->networkDevices[] = $networkDevice;
                $this->ipConfigs[] = $ipConfig;
            }
            //lxc
            if ($this->configuration()->isLxc())
            {
                $networkDevice = new NetworkDeviceLxc('net' . $networkId);
                $networkDevice->setName('eth' . $networkId)
                    ->setBridge($bridge)
                    ->setFirewall($this->configuration()->isNetworkFirewall() ? 1 : 0)
                    ->setIp($vmIpAddress->ip)
                    ->setRate($rate)
                    ->setCidr($vmIpAddress->cidr)
                    ->setGw($vmIpAddress->gateway)
                    ->setTag($vmIpAddress->tag)
                    ->setHwaddr($vmIpAddress->mac_address)
                    ->setTrunks($vmIpAddress->trunks);
                $this->networkDevices[] = $networkDevice;
            }
            $vmIpAddress->net = $networkDevice->getId();
            $vmIpAddress->save();
            $networkId++;
            unset($ip);
        }
    }

    public function asConfig(){
        $this->convert();
        return array_merge($this->getNetworkDevicesAsConfig(), $this->getIpConfigsAsConfig());
    }

    public function getNetworkDevicesAsConfig(){
        $container=[];
        foreach ($this->networkDevices as $networkDevice){
            $container[$networkDevice->getId()] = $networkDevice->asConfig();
        }
        return $container;
    }

    public function getIpConfigsAsConfig(){
        $container=[];
        foreach ($this->ipConfigs as $ipConfig){
            $container[$ipConfig->getId()] = $ipConfig->asConfig();
        }
        return $container;
    }

    private function getRate(){
        if ($this->isWhmcsConfigOption(ConfigurableOption::NETWORK_RATE) && $this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE) != "-1")
        {
            return $this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE);
        }
        return  $this->configuration()->getRate();
    }

    private function getBridge(VmIpAddress $ipAddress){
        //public
        if(filter_var($ipAddress->ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)){
            return $this->configuration()->getBridge();
        }
        //private
        return $this->configuration()->getPrivateBridge() ? $this->configuration()->getPrivateBridge() :  $this->configuration()->getBridge();
    }

    private function freeNetworDeviceId(){
        if($this->vm){
            return $this->vm->findFreeNetworDeviceId();
        }
        return 0;
    }


}