<?php

namespace App\Dto\Input;

use ApiPlatform\Metadata\ApiProperty;
use App\Dto\Output\HardwareProfileOutput;
use App\Dto\Output\ImageRepositoryOutput;
use App\Dto\Output\MenuOutput;
use App\Dto\Output\OgLiveOutput;
use App\Dto\Output\PxeTemplateOutput;
use App\Entity\NetworkSettings;
use App\Validator\Constraints\OrganizationalUnitMulticastMode;
use App\Validator\Constraints\OrganizationalUnitMulticastPort;
use App\Validator\Constraints\OrganizationalUnitP2PMode;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;

class NetworkSettingsInput
{
    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El servidor siguiente (next server) para PXE',
        example: '192.168.1.1'
    )]
    public ?string $nextServer = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El nombre del archivo de arranque',
        example: 'pxelinux.0'
    )]
    public ?string $bootFileName = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El servidor proxy',
        example: 'http://proxy.example.com:8080'
    )]
    public ?string $proxy = null;

    #[Assert\Ip(message: 'validators.network_settings.ip_address.invalid')]
    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El servidor DNS',
        example: '8.8.8.8'
    )]
    public ?string $dns = null;

    #[Assert\Ip(message: 'validators.network_settings.ip_address.invalid')]
    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La máscara de red',
        example: '255.255.255.0'
    )]
    public ?string $netmask = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La puerta de enlace (router)',
        example: '192.168.1.1'
    )]
    public ?string $router = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El servidor NTP',
        example: 'pool.ntp.org'
    )]
    public ?string $ntp = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La interfaz de red',
        example: 'eth0'
    )]
    public ?string $netiface = null;

    #[OrganizationalUnitP2PMode]
    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El modo P2P para despliegues torrent',
        example: 'seed'
    )]
    public ?string $p2pMode = null;

    #[Assert\GreaterThan(0, message: 'validators.network_settings.p2p_time.invalid')]
    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El tiempo P2P en segundos',
        example: 3600
    )]
    public ?int $p2pTime = null;

    #[Assert\Ip(message: 'validators.network_settings.ip_address.invalid')]
    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La dirección IP de multicast',
        example: '239.255.255.250'
    )]
    public ?string $mcastIp = null;

    #[Assert\GreaterThan(0, message: 'validators.network_settings.mcast_speed.invalid')]
    #[Groups(['organizational-write:write'])]
    #[ApiProperty(
        description: 'La velocidad de multicast en Mbps',
        example: 100
    )]
    public ?int $mcastSpeed = null;

    #[OrganizationalUnitMulticastPort]
    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El puerto de multicast',
        example: 8000
    )]
    public ?int $mcastPort = null;

    #[OrganizationalUnitMulticastMode]
    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El modo de multicast',
        example: 'full'
    )]
    public ?string $mcastMode = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El menú de la configuración de red'
    )]
    public ?MenuOutput $menu = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El perfil de hardware de la configuración de red'
    )]
    public ?HardwareProfileOutput $hardwareProfile = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La configuración OgLive de la configuración de red'
    )]
    public ?OgLiveOutput $ogLive = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El repositorio de imágenes de la configuración de red'
    )]
    public ?ImageRepositoryOutput $repository = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La plantilla PXE de la configuración de red'
    )]
    public ?PxeTemplateOutput $pxeTemplate = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La ruta de ogshare',
        example: '/var/ogshare'
    )]
    public ?string $ogshare = null;

    public function __construct(?NetworkSettings $networkSettings = null)
    {
        if (!$networkSettings) {
            return;
        }

        $this->nextServer = $networkSettings->getNextServer();
        $this->bootFileName = $networkSettings->getBootFileName();
        $this->proxy = $networkSettings->getProxy();
        $this->dns = $networkSettings->getDns();
        $this->netmask = $networkSettings->getNetmask();
        $this->router = $networkSettings->getRouter();
        $this->ntp = $networkSettings->getNtp();
        $this->netiface = $networkSettings->getNetiface();
        $this->p2pMode = $networkSettings->getP2pMode();
        $this->p2pTime = $networkSettings->getP2pTime();
        $this->mcastIp = $networkSettings->getMcastIp();
        $this->mcastSpeed = $networkSettings->getMcastSpeed();
        $this->mcastPort = $networkSettings->getMcastPort();
        $this->mcastMode = $networkSettings->getMcastMode();
        $this->ogshare = $networkSettings->getOgshare();

        if ($networkSettings->getMenu()) {
            $this->menu = new MenuOutput($networkSettings->getMenu());
        }

        if ($networkSettings->getHardwareProfile()) {
            $this->hardwareProfile = new HardwareProfileOutput($networkSettings->getHardwareProfile());
        }

        if ($networkSettings->getOgLive()) {
            $this->ogLive = new OgLiveOutput($networkSettings->getOgLive());
        }

        if ($networkSettings->getRepository()) {
            $this->repository = new ImageRepositoryOutput($networkSettings->getRepository());
        }

        if ($networkSettings->getPxeTemplate()) {
            $this->pxeTemplate = new PxeTemplateOutput($networkSettings->getPxeTemplate());
        }
    }

    public function createOrUpdateEntity(?NetworkSettings $networkSettings = null): NetworkSettings
    {
        if (!$networkSettings) {
            $networkSettings = new NetworkSettings();
        }

        $networkSettings->setNextServer($this->nextServer);
        $networkSettings->setBootFileName($this->bootFileName);
        $networkSettings->setProxy($this->proxy);
        $networkSettings->setDns($this->dns);
        $networkSettings->setNetmask($this->netmask);
        $networkSettings->setRouter($this->router);
        $networkSettings->setNetiface($this->netiface);
        $networkSettings->setNtp($this->ntp);
        $networkSettings->setP2pMode($this->p2pMode);
        $networkSettings->setP2pTime($this->p2pTime);
        $networkSettings->setMcastIp($this->mcastIp);
        $networkSettings->setMcastSpeed($this->mcastSpeed);
        $networkSettings->setMcastPort($this->mcastPort);
        $networkSettings->setMcastMode($this->mcastMode);
        $networkSettings->setOgshare($this->ogshare);

        if ($this->menu) {
            $networkSettings->setMenu($this->menu->getEntity());
        }

        if ($this->hardwareProfile) {
            $networkSettings->setHardwareProfile($this->hardwareProfile->getEntity());
        }

        if ($this->ogLive) {
            $networkSettings->setOgLive($this->ogLive->getEntity());
        }

        if ($this->repository) {
            $networkSettings->setRepository($this->repository->getEntity());
        }

        if ($this->pxeTemplate) {
            $networkSettings->setPxeTemplate($this->pxeTemplate->getEntity());
        }

        return $networkSettings;
    }
}