<?php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use App\Repository\ClientRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

#[ORM\Entity(repositoryClass: ClientRepository::class)]
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_IP', fields: ['ip'])]
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_MAC', fields: ['mac'])]
#[UniqueEntity(fields: ['ip'], message: 'This IP address is already in use.')]
#[UniqueEntity(fields: ['mac'], message: 'This MAC address is already in use.')]
#[ORM\Index(fields: ['status'], name: 'IDX_STATUS')]
#[ORM\Index(fields: ['updatedAt'], name: 'IDX_UPDATED_AT')]
#[ORM\Index(fields: ['status', 'updatedAt'], name: 'IDX_STATUS_UPDATED_AT')]
class Client extends AbstractEntity
{
    use NameableTrait;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $serialNumber = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $netiface = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $netDriver = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $mac = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $ip = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $status = null;

    #[ORM\ManyToOne(inversedBy: 'clients')]
    #[ORM\JoinColumn( onDelete: 'CASCADE')]
    private ?OrganizationalUnit $organizationalUnit = null;

    /**
     * @var Collection<int, Partition>
     */
    #[ORM\OneToMany(mappedBy: 'client', targetEntity: Partition::class)]
    #[ORM\OrderBy(['partitionNumber' => 'ASC'])]
    private Collection $partitions;

    #[ORM\ManyToOne]
    #[ORM\JoinColumn( onDelete: 'SET NULL')]
    private ?Menu $menu = null;

    #[ORM\ManyToOne]
    private ?HardwareProfile $hardwareProfile = null;

    #[ORM\Column(nullable: true)]
    private ?bool $validation = null;

    #[ORM\Column(nullable: true)]
    private ?array $position = ['x' => 0, 'y' => 0];

    #[ORM\ManyToOne(inversedBy: 'clients')]
    #[ORM\JoinColumn( onDelete: 'SET NULL')]
    private ?PxeTemplate $template = null;

    #[ORM\ManyToOne()]
    private ?ImageRepository $repository = null;

    #[ORM\ManyToOne(inversedBy: 'clients')]
    #[ORM\JoinColumn( onDelete: 'SET NULL')]
    private ?Subnet $subnet = null;
    
    #[ORM\ManyToOne(inversedBy: 'clients')]
    #[ORM\JoinColumn( onDelete: 'SET NULL')]
    private ?OgLive $ogLive = null;

    #[ORM\Column]
    private ?bool $maintenance = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $agentJobId = null;

    #[ORM\Column(nullable: true)]
    private ?bool $pxeSync = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $firmwareType = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $token = null;

    public function __construct()
    {
        parent::__construct();
        $this->partitions = new ArrayCollection();
    }

    public function getSerialNumber(): ?string
    {
        return $this->serialNumber;
    }

    public function setSerialNumber(?string $serialNumber): static
    {
        $this->serialNumber = $serialNumber;

        return $this;
    }

    public function getNetiface(): ?string
    {
        return $this->netiface;
    }

    public function setNetiface(?string $netiface): static
    {
        $this->netiface = $netiface;

        return $this;
    }

    public function getNetDriver(): ?string
    {
        return $this->netDriver;
    }

    public function setNetDriver(?string $netDriver): static
    {
        $this->netDriver = $netDriver;

        return $this;
    }

    public function getMac(): ?string
    {
        return $this->mac;
    }

    public function setMac(?string $mac): static
    {
        $this->mac = $mac;

        return $this;
    }

    public function getIp(): ?string
    {
        return $this->ip;
    }

    public function setIp(?string $ip): static
    {
        $this->ip = $ip;

        return $this;
    }

    public function getStatus(): ?string
    {
        return $this->status;
    }

    #[ORM\PostPersist]
    public function setStatus(?string $status): static
    {
        $this->status = $status;

        return $this;
    }

    public function getOrganizationalUnit(): ?OrganizationalUnit
    {
        return $this->organizationalUnit;
    }

    public function setOrganizationalUnit(?OrganizationalUnit $organizationalUnit): static
    {
        $this->organizationalUnit = $organizationalUnit;

        return $this;
    }

    /**
     * @return Collection<int, Partition>
     */
    public function getPartitions(): Collection
    {
        return $this->partitions;
    }

    public function addPartition(Partition $partition): static
    {
        if (!$this->partitions->contains($partition)) {
            $this->partitions->add($partition);
            $partition->setClient($this);
        }

        return $this;
    }

    public function removePartition(Partition $partition): static
    {
        if ($this->partitions->removeElement($partition)) {
            // set the owning side to null (unless already changed)
            if ($partition->getClient() === $this) {
                $partition->setClient(null);
            }
        }

        return $this;
    }

    public function getMenu(): ?Menu
    {
        return $this->menu;
    }

    public function setMenu(?Menu $menu): static
    {
        $this->menu = $menu;

        return $this;
    }

    public function getHardwareProfile(): ?HardwareProfile
    {
        return $this->hardwareProfile;
    }

    public function setHardwareProfile(?HardwareProfile $hardwareProfile): static
    {
        $this->hardwareProfile = $hardwareProfile;

        return $this;
    }

    public function getValidation(): ?bool
    {
        return $this->validation;
    }

    public function setValidation(?bool $validation): static
    {
        $this->validation = $validation;

        return $this;
    }

    public function getPosition(): ?array
    {
        return $this->position;
    }

    public function setPosition(?array $position): static
    {
        $this->position = $position;

        return $this;
    }

    public function getTemplate(): ?PxeTemplate
    {
        return $this->template;
    }

    public function setTemplate(?PxeTemplate $template): static
    {
        $this->template = $template;

        return $this;
    }


    public function getRepository(): ?ImageRepository
    {
        return $this->repository ?? $this->getOrganizationalUnit()->getNetworkSettings()?->getRepository();
    }

    public function setRepository(?ImageRepository $repository): static
    {
        $this->repository = $repository;

        return $this;
    }

    public function getSubnet(): ?Subnet
    {
        return $this->subnet;
    }

    public function setSubnet(?Subnet $subnet): static
    {
        $this->subnet = $subnet;

        return $this;
    }

    public function getOgLive(): ?OgLive
    {
        return $this->ogLive;
    }

    public function setOgLive(?OgLive $ogLive): static
    {
        $this->ogLive = $ogLive;

        return $this;
    }

    public function isMaintenance(): ?bool
    {
        return $this->maintenance;
    }

    public function setMaintenance(bool $maintenance): static
    {
        $this->maintenance = $maintenance;

        return $this;
    }

    public function getAgentJobId(): ?string
    {
        return $this->agentJobId;
    }

    public function setAgentJobId(?string $agentJobId): static
    {
        $this->agentJobId = $agentJobId;

        return $this;
    }

    public function isPxeSync(): ?bool
    {
        return $this->pxeSync;
    }

    public function setPxeSync(?bool $pxeSync): static
    {
        $this->pxeSync = $pxeSync;

        return $this;
    }

    public function getFirmwareType(): ?string
    {
        return $this->firmwareType;
    }

    public function setFirmwareType(?string $firmwareType): static
    {
        $this->firmwareType = $firmwareType;

        return $this;
    }

    public function getToken(): ?string
    {
        return $this->token;
    }

    public function setToken(?string $token): static
    {
        $this->token = $token;

        return $this;
    }
}
