<?php


namespace ModulesGarden\Servers\ProxmoxVps\App\Config\Packages;

use MGProvision\Proxmox\v2\ProxmoxApiException;
use MGProvision\Proxmox\v2\repository\ClusterResourcesRepository;
use MGProvision\Proxmox\v2\repository\FileRepository;
use MGProvision\Proxmox\v2\repository\StorageRepository;
use ModulesGarden\ProxmoxAddon\App\Models\CloudInitScript;
use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
use ModulesGarden\ProxmoxAddon\App\Services\Vps\ProductService;
use ModulesGarden\Servers\ProxmoxVps\App\Libs\AwsIntegration\ClientWrapper;
use ModulesGarden\Servers\ProxmoxVps\App\Models\AvailableImages\Repository;
use ModulesGarden\Servers\ProxmoxVps\App\UI\Admin\ProductConfig\Providers\Config;
use ModulesGarden\Servers\ProxmoxVps\Core\App\Packages\AppPackageConfiguration;
use ModulesGarden\Servers\ProxmoxVps\Core\FileReader\Reader\Json;
use ModulesGarden\Servers\ProxmoxVps\Core\ModuleConstants;
use ModulesGarden\Servers\ProxmoxVps\Core\UI\Traits\RequestObjectHandler;
use ModulesGarden\Servers\ProxmoxVps\Core\UI\Traits\WhmcsParams;
use ModulesGarden\Servers\ProxmoxVps\Packages\WhmcsService\Config\Enum;

class WhmcsService extends AppPackageConfiguration
{
    use RequestObjectHandler;
    use WhmcsParams;
    use ProductService;
    use ApiService;

    const APP_CONFIGURATION =
        [
            self::PACKAGE_STATUS => self::PACKAGE_STATUS_ACTIVE,

            Enum::CUSTOM_FIELDS => [
                [
                    Enum::FIELD_NAME       => 'vmid|VMID',
                    Enum::FIELD_TYPE       => Enum::FIELD_TYPE_TEXT_BOX,
                    Enum::FIELD_ADMIN_ONLY => Enum::FIELD_ADMIN_ONLY_ON
                ],
                [
                    Enum::FIELD_NAME       => 'node|Node',
                    Enum::FIELD_TYPE       => Enum::FIELD_TYPE_TEXT_BOX,
                    Enum::FIELD_ADMIN_ONLY => Enum::FIELD_ADMIN_ONLY_ON
                ],
                [
                    Enum::FIELD_NAME       => 'VLAN Tag|VLAN Tag',
                    Enum::FIELD_TYPE       => Enum::FIELD_TYPE_TEXT_BOX,
                    Enum::FIELD_ADMIN_ONLY => Enum::FIELD_ADMIN_ONLY_ON
                ],
                [
                    Enum::FIELD_NAME       => 'userName|Username',
                    Enum::FIELD_TYPE       => Enum::FIELD_TYPE_TEXT_BOX,
                    Enum::FIELD_ADMIN_ONLY => Enum::FIELD_ADMIN_ONLY_ON
                ],
                [
                    Enum::FIELD_NAME       => 'ciuser|Cloud-Init User',
                    Enum::FIELD_TYPE       => Enum::FIELD_TYPE_TEXT_BOX,
                    Enum::FIELD_ADMIN_ONLY => Enum::FIELD_ADMIN_ONLY_ON
                ],
                [
                    Enum::FIELD_NAME       => 'cipassword|Cloud-Init Password',
                    Enum::FIELD_TYPE       => Enum::FIELD_TYPE_PASSWORD,
                    Enum::FIELD_ADMIN_ONLY => Enum::FIELD_ADMIN_ONLY_OFF,
                ],
                [
                    Enum::FIELD_NAME        => 'sshkeys|SSH Public Key',
                    Enum::FIELD_TYPE        => Enum::FIELD_TYPE_TEXTAREA,
                    Enum::FIELD_ADMIN_ONLY  => Enum::FIELD_ADMIN_ONLY_ON,
                    Enum::FIELD_REG_EXPR    => '#ssh-rsa AAAA[0-9A-Za-z+/]+[=]{0,3}( [^@]+@[^@]+)?#',
                    Enum::FIELD_SHOW_ORDER  => Enum::FIELD_SHOW_ORDER_ON,
                    Enum::FIELD_DESCRIPTION => 'Enter your public key in the OpenSSH format here (e.g. ssh-rsa).'
                ]
            ],
        ];

    public function VMTemplateGetSubOptions()
    {
        $subOptions = [];
        try
        {
            //kvm
            if ($this->configuration()->isQemu())
            {
                $subOptions[]               = [
                    Enum::OPTION_SUB_NAME  => '0|Disabled',
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ];
                $clusterResourcesRepository = new ClusterResourcesRepository();
                $clusterResourcesRepository->setApi($this->api());
                $clusterResourcesRepository->findKvmTemplate();
                $templates = [];
                foreach ($clusterResourcesRepository->fetch() as $resurce)
                {
                    if (preg_match('/^custom[0-9]*/', $resurce->getName()))
                    {
                        continue;
                    }
                    if (in_array($resurce->getName(), $templates))
                    {
                        continue;
                    }
                    $subOptions[] = [
                        Enum::OPTION_SUB_NAME  => $resurce->getName() . '|' . $resurce->getName(),
                        Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                    ];
                }
                unset($templates);
            }
            else
            {
                if ($this->configuration()->isLxc())
                { //lxc
                    //node
                    $node = $this->getDefaultNode();
                    //storages
                    $storageRepository = new StorageRepository();
                    $storageRepository->findByNodes([$node->getNode()])
                        ->findEnabed();
                    //osTemplates
                    $fileRepository = new FileRepository();
                    $fileRepository->setApi($this->api());
                    $fileRepository->findLxcTemplates();
                    $fileRepository->findByNode($node);
                    $fileRepository->findByStorages($storageRepository->fetchAsArray());
                    foreach ($fileRepository->fetch() as $file)
                    {
                        $subOptions[] = [
                            Enum::OPTION_SUB_NAME  => $file->getVolid() . '|' . $file->getFriendlyName(),
                            Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                        ];
                    }
                }
            }
        }
        catch (ProxmoxApiException $ex)
        {
            return $subOptions;
        }
        return $subOptions;
    }

    public function NetworkRateGetSubOptions()
    {
        return [
            [
                Enum::OPTION_SUB_NAME  => "0|Unlimited",
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ],
            [
                Enum::OPTION_SUB_NAME  => '5|5 (MB/s) (' . (5 * 8) . ' Mbps)',
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ],
            [
                Enum::OPTION_SUB_NAME  => '10|10 (MB/s) (' . (10 * 8) . ' Mbps)',
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ],
            [
                Enum::OPTION_SUB_NAME  => '20|20 (MB/s) (' . (20 * 8) . ' Mbps)',
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ],
            [
                Enum::OPTION_SUB_NAME  => '30|30 (MB/s) (' . (30 * 8) . ' Mbps)',
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ],
            [
                Enum::OPTION_SUB_NAME  => '40|40 (MB/s) (' . (40 * 8) . ' Mbps)',
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ],
            [
                Enum::OPTION_SUB_NAME  => '50|50 (MB/s) (' . (50 * 8) . ' Mbps)',
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ],
        ];
    }

    public function vcpusGetSubOptions()
    {
        return [
            [
                Enum::OPTION_SUB_NAME  => "0|Unlimited",
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ],
            [
                Enum::OPTION_SUB_NAME  => '1|1',
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ]
        ];
    }

    public function ISOImageGetSubOptions()
    {
        $subOptions = [
            [
                Enum::OPTION_SUB_NAME  => 'none|None',
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ]
        ];
        try
        {
            //node
            $node = $this->getDefaultNode();
            //storages
            $storageRepository = new StorageRepository();
            $storageRepository->findByNodes([$node->getNode()])
                ->findEnabed();
            //file  repository
            $fileRepository = new FileRepository();
            $fileRepository->setApi($this->api());
            $fileRepository->findIso();
            $fileRepository->findByNode($node);
            $fileRepository->findByStorages($storageRepository->fetchAsArray());
            foreach ($fileRepository->fetch() as $file)
            {
                $subOptions[] = [
                    Enum::OPTION_SUB_NAME  => $file->getVolid() . '|' . $file->getFriendlyName(),
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ];
            }
        }
        catch (ProxmoxApiException $ex)
        {
            return $subOptions;
        }
        return $subOptions;
    }

    public function osTypeGetSubOptions()
    {
        $subOptions = [];
        $ostype     = new Json('ostype.json', ModuleConstants::getFullPathWhmcs('modules', 'addons', 'proxmoxAddon', 'storage', 'app'));
        foreach ($ostype->get() as $k => $ostype)
        {
            $subOptions[] = [
                Enum::OPTION_SUB_NAME  => $k . '|' . $ostype,
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ];
        }
        return $subOptions;
    }

    public function getConfigurableOptions()
    {
        $configOptions = [];
        if ($this->configuration()->isQemu())
        {
            $configOptions[] = [
                Enum::OPTION_NAME         => 'The number of CPU sockets|CPU Sockets',
                Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
                Enum::OPTION_QUANTITY_MIN => 1,
                Enum::OPTION_QUANTITY_MAX => 100,
                Enum::CONFIG_SUB_OPTIONS  => [
                    [
                        Enum::OPTION_SUB_NAME  => 'Unit|Unit',
                        Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                    ]
                ]
            ];
            $configOptions[] = [
                Enum::OPTION_NAME         => 'The number of cores per socket|CPU Cores',
                Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
                Enum::OPTION_QUANTITY_MIN => 1,
                Enum::OPTION_QUANTITY_MAX => 10,
                Enum::CONFIG_SUB_OPTIONS  => [
                    [
                        Enum::OPTION_SUB_NAME  => 'Unit|Unit',
                        Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                    ]
                ]
            ];
        }
        if ($this->configuration()->isLxc())
        {
            $configOptions[] = [
                Enum::OPTION_NAME         => 'cores|CPU Cores',
                Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
                Enum::OPTION_QUANTITY_MIN => 1,
                Enum::OPTION_QUANTITY_MAX => 10,
                Enum::CONFIG_SUB_OPTIONS  => [
                    [
                        Enum::OPTION_SUB_NAME  => 'Unit|Unit',
                        Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                    ]
                ]
            ];
        }
        $configOptions[] = [
            Enum::OPTION_NAME         => 'cpulimit|Limit Of CPU',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => 0,
            Enum::OPTION_QUANTITY_MAX => 100,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $configOptions[] = [
            Enum::OPTION_NAME         => 'CPU weight for a VM|CPU Weight For The VM',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => 1024,
            Enum::OPTION_QUANTITY_MAX => 99999,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $unit            = strtoupper($this->configuration()->getMemoryUnit());
        $min             = 128;
        $max             = 1024 * 10;
        if ($this->configuration()->getMemoryUnit() == 'gb')
        {
            $min = 1;
            $max = 10;
        }
        $configOptions[] = [
            Enum::OPTION_NAME         => 'Amount of RAM|Amount Of RAM',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => $min,
            Enum::OPTION_QUANTITY_MAX => $max,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => "{$unit}|{$unit}",
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        if ($this->configuration()->isLxc())
        {
            $unit = strtoupper($this->configuration()->getSwapUnit());
            $min  = 128;
            $max  = 1024 * 10;
            if ($this->configuration()->getSwapUnit() == 'gb')
            {
                $min = 1;
                $max = 10;
            }
            $configOptions[] = [
                Enum::OPTION_NAME         => 'Amount of SWAP|Amount Of SWAP',
                Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
                Enum::OPTION_QUANTITY_MIN => $min,
                Enum::OPTION_QUANTITY_MAX => $max,
                Enum::CONFIG_SUB_OPTIONS  => [
                    [
                        Enum::OPTION_SUB_NAME  => "{$unit}|{$unit}",
                        Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                    ]
                ]
            ];
        }
        $unit = strtoupper($this->configuration()->getDiskUnit());
        $min  = 128;
        $max  = 1024 * 1000;
        if ($this->configuration()->getDiskUnit() == 'gb' || $this->configuration()->getDiskUnit() == 'tb')
        {
            $min = 1;
            $max = 1000;
        }
        $configOptions[] = [
            Enum::OPTION_NAME         => 'Disk Space|Disk Space',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => $min,
            Enum::OPTION_QUANTITY_MAX => $max,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => "{$unit}|{$unit}",
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $unit            = strtoupper($this->configuration()->getAdditionalDiskUnit());
        $max             = 1024 * 1000;
        if ($this->configuration()->getAdditionalDiskUnit() == 'gb' || $this->configuration()->getAdditionalDiskUnit() == 'tb')
        {
            $max = 1000;
        }
        $configOptions[] = [
            Enum::OPTION_NAME         => 'additionalDisksSpace|Additional Disks Space',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => 0,
            Enum::OPTION_QUANTITY_MAX => $max,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => "{$unit}|{$unit}",
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $configOptions[] = [
            Enum::OPTION_NAME         => 'IP Addresses|IPv4 Addresses',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => 0,
            Enum::OPTION_QUANTITY_MAX => 100,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $configOptions[] = [
            Enum::OPTION_NAME         => 'IPv6 Addresses|IPv6 Addresses',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => 0,
            Enum::OPTION_QUANTITY_MAX => 100,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $configOptions[] = [
            Enum::OPTION_NAME         => 'Backups Limit|Backups Size',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => 0,
            Enum::OPTION_QUANTITY_MAX => 10 * 100,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => 'GB|GB',
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $configOptions[] = [
            Enum::OPTION_NAME         => 'Backups Files Limit|Backup Files',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => 0,
            Enum::OPTION_QUANTITY_MAX => 100,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $configOptions[] = [
            Enum::OPTION_NAME         => 'snapshots|Snapshots',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => 0,
            Enum::OPTION_QUANTITY_MAX => 100,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $configOptions[] = [
            Enum::OPTION_NAME         => 'snapshotJobs|Snapshot Jobs',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => 0,
            Enum::OPTION_QUANTITY_MAX => 100,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $configOptions[] = [
            Enum::OPTION_NAME         => 'Bandwidth|Bandwidth',
            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
            Enum::OPTION_QUANTITY_MIN => 0,
            Enum::OPTION_QUANTITY_MAX => 10 * 100,
            Enum::CONFIG_SUB_OPTIONS  => [
                [
                    Enum::OPTION_SUB_NAME  => 'GB|GB',
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ]
            ]
        ];
        $configOptions[] = [
            Enum::OPTION_NAME => 'VM Template|VM Template',
            Enum::OPTION_TYPE => Enum::OPTION_TYPE_DROPDOWN,
        ];
        $configOptions[] = [
            Enum::OPTION_NAME => 'Network Rate|Network Rate',
            Enum::OPTION_TYPE => Enum::OPTION_TYPE_DROPDOWN,
        ];
        if ($this->configuration()->isQemu())
        {
            $configOptions[] = [
                Enum::OPTION_NAME => 'vcpus|VCPUs',
                Enum::OPTION_TYPE => Enum::OPTION_TYPE_DROPDOWN,
            ];
            $configOptions[] = [
                Enum::OPTION_NAME => 'ISO Image|ISO Image',
                Enum::OPTION_TYPE => Enum::OPTION_TYPE_DROPDOWN,
            ];
            $configOptions[] = [
                Enum::OPTION_NAME => 'osType|OS Type',
                Enum::OPTION_TYPE => Enum::OPTION_TYPE_DROPDOWN,
            ];
            $configOptions[] = [
                Enum::OPTION_NAME => 'cicustom|Custom Cloud-Init Configuration',
                Enum::OPTION_TYPE => Enum::OPTION_TYPE_DROPDOWN,
            ];
            $configOptions[] = [
                Enum::OPTION_NAME => 'ciscript|Cloud-Init Script',
                Enum::OPTION_TYPE => Enum::OPTION_TYPE_DROPDOWN,
            ];
        }
        return $configOptions;
    }

    public function cloudInitScriptGetSubOptions()
    {
        $subOptions = [];
        //kvm
        if ($this->configuration()->isQemu())
        {
            $subOptions[]               = [
                Enum::OPTION_SUB_NAME  => '0|Disabled',
                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
            ];
            foreach (CloudInitScript::get()  as $item){
                $subOptions[] = [
                    Enum::OPTION_SUB_NAME  => $item->id . '|' . $item->name,
                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
                ];
            }
        }
        return $subOptions;
    }
}
