<?php

/*
 * kohinos_cooperatic
 * Copyright (C) 2019-2020  ADML63
 * Copyright (C) 2020- Cooperatic
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
namespace App\Entity;

use App\Entity\EntityTrait\EnablableEntityTrait;
use App\Entity\EntityTrait\HasCompteEntity;
use App\Entity\EntityTrait\HasEcompteEntity;
use App\Entity\Groupeprestataire;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Mapping\Annotation\Slug;
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Symfony\Component\Validator\Constraints as Assert;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource(
 *     attributes={"security"="is_granted('ROLE_ADMIN_PRESTATAIRE_GERER_VIEW') or is_granted('ROLE_API')"},
 *     collectionOperations={
 *         "get"={"security"="is_granted('ROLE_ADMIN_PRESTATAIRE_GERER_LIST') or is_granted('ROLE_API')"},
 *         "post"={"security"="is_granted('ROLE_ADMIN_PRESTATAIRE_GERER_EDIT')"}
 *     },
 *     itemOperations={
 *         "get"={"security"="is_granted('ROLE_ADMIN_PRESTATAIRE_GERER_VIEW') or is_granted('ROLE_API')"},
 *         "put"={"security"="is_granted('ROLE_ADMIN_PRESTATAIRE_GERER_EDIT')"},
 *     },
 *     normalizationContext={"groups"={"read"}},
 *     denormalizationContext={"groups"={"write"}}
 * )
 * @ORM\Entity(repositoryClass="App\Repository\PrestataireRepository")
 * @ORM\Table(name="prestataire")
 */
class Prestataire
{
    use EnablableEntityTrait,
        TimestampableEntity,
        HasEcompteEntity;

    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue
     * @Groups({"read"})
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(name="raison", type="string", length=100)
     * @Groups({"read", "write"})
     */
    private $raison;

    /**
     * @var string|null
     *
     * @ORM\Column(type="text", nullable=true)
     * @Groups({"read", "write"})
     */
    private $description;

    /**
     * @var string|null
     *
     * @Gedmo\Slug(fields={"raison"})
     * @ORM\Column(length=100, unique=true)
     * @Groups({"read"})
     */
    protected $slug;

    /**
     * @var string
     *
     * @ORM\Column(name="metier", type="string", length=100, nullable=true)
     * @Groups({"read", "write"})
     */
    private $metier;

    /**
     * @var null|string
     *
     * @ORM\Column(name="statut", type="string", length=50, nullable=true)
     * @Groups({"read", "write"})
     */
    private $statut;

    /**
     * @var null|string
     *
     * @ORM\Column(name="responsable", type="string", length=200, nullable=true)
     * @Groups({"read", "write"})
     */
    private $responsable;

    /**
     * @ORM\Column(name="iban", type="string", length=100, nullable=true)
     * @todo : vérification de l'IBAN via assert/iban
     * Assert\Iban(message="L'IBAN(International Bank Account Number) est invalide.")
     * @Groups({"read", "write"})
     */
    private $iban;

    /**
     * @var string
     *
     * @ORM\Column(name="siret", type="string", length=50, nullable=true)
     * @Groups({"read", "write"})
     */
    private $siret;

    /**
     * @var null|string
     *
     * @ORM\Column(name="web", type="string", length=255, nullable=true)
     * @Assert\Url(message = "L'adresse : '{{ value }}' est invalide.")
     * @Groups({"read", "write"})
     */
    private $web;

    /**
     * Le prestataire peut recevoir des cotisations (En règle générale, l'association gérant la monnaie locale)
     * Ce prestataire est normalement crée à l'installation du kohinos
     * @var bool
     *
     * @ORM\Column(name="mlc", type="boolean", nullable=false, options={"default" : false})
     * @Groups({"read"})
     */
    private $mlc = false;

    /**
     * @var null|string (champ libre)
     *
     * @ORM\Column(name="horaires", type="string", length=255, nullable=true)
     * @Groups({"read", "write"})
     */
    private $horaires;

    /**
     * @var TypePrestataire
     *
     * @ORM\ManyToOne(targetEntity="TypePrestataire", cascade={"persist"}, inversedBy="prestataires")
     * @Groups({"read", "write"})
     */
    private $typeprestataire;

    /**
     * @var ArrayCollection|Rubrique[]
     * @ORM\ManyToMany(targetEntity="Rubrique", mappedBy="prestataires", cascade={"persist"}, fetch="EXTRA_LAZY")
     * @Groups({"read", "write"})
     */
    private $rubriques;

    /**
    * @var \Application\Sonata\MediaBundle\Entity\Media
    * @ORM\ManyToOne(targetEntity="App\Application\Sonata\MediaBundle\Entity\Media", cascade={"persist"}, fetch="LAZY")
    * @ORM\JoinColumn(name="media_id", referencedColumnName="id", nullable=true)
    * @Groups({"read", "write"})
    */
    protected $media;

    /**
     * @var ArrayCollection|GeolocPrestataire[]
     * @ORM\OneToMany(targetEntity="GeolocPrestataire", cascade={"persist"}, mappedBy="prestataire")
     * @Groups({"read", "write"})
     */
    private $geolocs;

    /**
     * @var ArrayCollection|ContactPrestataire[]
     * @ORM\OneToMany(targetEntity="ContactPrestataire", cascade={"persist"}, mappedBy="prestataire")
     * @Groups({"read", "write"})
     */
    private $contacts;

    /**
     * @var ArrayCollection|User[]
     *
     * @ORM\ManyToMany(targetEntity="User", inversedBy="prestataires", cascade={"persist"})
     * @Groups({"read", "write"})
     */
    protected $users;

    /**
     * @var Groupe $groupe
     *
     * @ORM\ManyToOne(targetEntity="Groupe", inversedBy="prestataires", cascade={"persist"})
     * @Assert\NotBlank
     * @Groups({"read", "write"})
     */
    private $groupe;

    /**
     * AMAP / Marché
     * @var ArrayCollection|Groupeprestataire[]
     * @ORM\ManyToMany(targetEntity="Groupeprestataire", cascade={"persist"}, mappedBy="prestataires")
     * @ORM\JoinTable(name="groupes_prestataires")
     * @Groups({"read", "write"})
     */
    private $groupeprestataires;

    /**
     * EtatPrestataire $etats
     * @var ArrayCollection|EtatPrestataire[]
     * @ORM\ManyToMany(targetEntity="EtatPrestataire", cascade={"persist"}, mappedBy="prestataires", fetch="EXTRA_LAZY")
     * @Groups({"read", "write"})
     */
    private $etats;

    /**
     * Taux de reconversion propre au prestataire
     * @var float
     * @ORM\Column(name="tauxreconversion", type="decimal", precision=7, scale=2, nullable=true)
     * @Groups({"read", "write"})
     */
    protected $tauxreconversion;

    /**
     * @var ArrayCollection|User[]
     *
     * @ORM\ManyToMany(targetEntity="User", inversedBy="caissierprestataires", cascade={"persist"})
     * @ORM\JoinTable(name="user_prestataire_caissier",
     *      joinColumns={@ORM\JoinColumn(name="prestataire_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}
     * )
     * @Groups({"read", "write"})
     */
    private $caissiers;

    public function __construct()
    {
        $this->users = new ArrayCollection();
        $this->groupeprestataires = new ArrayCollection();
        $this->geolocs = new ArrayCollection();
        $this->etats = new ArrayCollection();
        $this->rubriques = new ArrayCollection();
        $this->caissiers = new ArrayCollection();
    }

    /**
     * @return mixed
     */
    public function getId(): int
    {
        return $this->id;
    }

    /**
     * @return string
     */
    public function getRaison(): ?string
    {
        return $this->raison;
    }

    /**
     * @param string $raison
     * @return Prestataire
     */
    public function setRaison(string $raison): self
    {
        $this->raison = $raison;
        return $this;
    }

    public function getSlug(): ?string
    {
        return $this->slug;
    }

    public function setSlug(?string $slug): self
    {
        $this->slug = $slug;
        return $this;
    }

    public function setDescription(?string $description)
    {
        $this->description = $description;
        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    /**
     * @return string
     */
    public function getMetier(): ?string
    {
        return $this->metier;
    }

    /**
     * @param string $metier
     * @return Prestataire
     */
    public function setMetier(string $metier): self
    {
        $this->metier = $metier;
        return $this;
    }

    /**
     * @return null|string
     */
    public function getStatut(): ?string
    {
        return $this->statut;
    }

    /**
     * @param null|string $statut
     * @return Prestataire
     */
    public function setStatut(?string $statut): self
    {
        $this->statut = $statut;
        return $this;
    }

    /**
     * @return null|string
     */
    public function getResponsable(): ?string
    {
        return $this->responsable;
    }

    /**
     * @param null|string $responsable
     * @return Prestataire
     */
    public function setResponsable(?string $responsable): self
    {
        $this->responsable = $responsable;
        return $this;
    }

    /**
     * @return string
     */
    public function getIban(): ?string
    {
        return $this->iban;
    }

    /**
     * @param string $iban
     * @return Prestataire
     */
    public function setIban(?string $iban): self
    {
        $this->iban = $iban;
        return $this;
    }

    /**
     * @return string
     */
    public function getSiret(): ?string
    {
        return $this->siret;
    }

    /**
     * @param string $siret
     * @return Prestataire
     */
    public function setSiret(?string $siret): self
    {
        $this->siret = $siret;
        return $this;
    }

    /**
     * @return null|string
     */
    public function getWeb(): ?string
    {
        return $this->web;
    }

    /**
     * @param null|string $web
     * @return Prestataire
     */
    public function setWeb(?string $web): self
    {
        $this->web = $web;
        return $this;
    }

    /**
     * @return bool
     */
    public function isMlc(): bool
    {
        return $this->mlc;
    }

    /**
     * @param bool $mlc
     * @return Prestataire
     */
    public function setMlc(bool $mlc): self
    {
        $this->mlc = $mlc;
        return $this;
    }

    /**
     * getgeolocs
     * @return ArrayCollection geoloc
     */
    public function getGeolocs()
    {
        return $this->geolocs;
    }

    /**
     * setGeolocs
     * @param [type] $geolocs [description]
     */
    public function setGeolocs($geolocs): self
    {
        $this->geolocs = $geolocs;
        return $this;
    }

    /**
     * @param GeolocPrestataire $geoloc
     * @return $this
     */
    public function addGeoloc(GeolocPrestataire $geoloc): self
    {
        if (!$this->geolocs->contains($geoloc)) {
            $this->geolocs[] = $geoloc;
            $geoloc->setPrestataire($this);
        }
        return $this;
    }

    /**
     * @param GeolocPrestataire $geoloc
     * @return $this
     */
    public function removeGeoloc(GeolocPrestataire $geoloc): self
    {
        if ($this->geolocs->contains($geoloc)) {
            $this->geolocs->removeElement($geoloc);
            $geoloc->setPrestataire(null);
        }
        return $this;
    }

    /**
     * getcontacts
     * @return ArrayCollection contact
     */
    public function getContacts()
    {
        return $this->contacts;
    }

    /**
     * setContacts
     * @param [type] $contacts [description]
     */
    public function setContacts($contacts): self
    {
        $this->contacts = $contacts;
        return $this;
    }

    /**
     * @param ContactPrestataire $contact
     * @return $this
     */
    public function addContact(ContactPrestataire $contact): self
    {
        if (is_null($this->contacts)) {
            $this->contacts = new ArrayCollection();
        }
        if (!$this->contacts->contains($contact)) {
            $this->contacts[] = $contact;
            $contact->setPrestataire($this);
        }
        return $this;
    }

    /**
     * @param ContactPrestataire $contact
     * @return $this
     */
    public function removeContact(ContactPrestataire $contact): self
    {
        if ($this->contacts->contains($contact)) {
            $this->contacts->removeElement($contact);
            $contact->setPrestataire(null);
        }
        return $this;
    }

    /**
     * @return ArrayCollection[]|User
     */
    public function getUsers()
    {
        return $this->users;
    }

    public function getUsersString()
    {
        return join(' - ', array_map(function ($user) {
            return $user->getName().':'.$user->getEmail();
        }, $this->users->getValues()));
    }

    /**
     * @param User $user
     * @return $this
     */
    public function addUser(User $user): self
    {
        if (!$this->users->contains($user)) {
            $this->users[] = $user;
            $user->addPrestataire($this);
        }
        return $this;
    }

    /**
     * @param User $user
     * @return $this
     */
    public function removeUser(User $users)
    {
        if ($this->users->contains($user)) {
            $this->users->removeElement($user);
            $user->removePrestataire($this);
        }
        return $this;
    }

    /**
     * @param ArrayCollection[]|User $users
     * @return Prestataire
     */
    public function setUsers($users): self
    {
        $this->users = $users;
        return $this;
    }

    /**
     * @param null|Groupe $groupe
     * @return $this
     */
    public function setGroupe(?Groupe $groupe): self
    {
        $this->groupe = $groupe;
        return $this;
    }

    /**
     * @return null|Groupe
     */
    public function getGroupe(): ?Groupe
    {
        return $this->groupe;
    }

    /**
    * Get typeprestataire
    * @return
    */
    public function getTypeprestataire()
    {
        return $this->typeprestataire;
    }

    /**
    * Set typeprestataire
    * @return $this
    */
    public function setTypeprestataire($typeprestataire): self
    {
        $this->typeprestataire = $typeprestataire;
        return $this;
    }

    /**
     * @return Rubrique[]|ArrayCollection
     */
    public function getRubriques()
    {
        return $this->rubriques;
    }

    public function getRubriquesString(): ?string
    {
        return join(' - ', array_map(function ($rubrique) {
            return $rubrique->getName();
        }, $this->rubriques->getValues()));
    }

    /**
     * @param Rubrique $rubrique
     * @return $this
     */
    public function addRubrique(Rubrique $rubrique): self
    {
        if (!$this->rubriques->contains($rubrique)) {
            $this->rubriques[] = $rubrique;
            $rubrique->addPrestataire($this);
        }
        return $this;
    }

    /**
     * @param Rubrique $rubrique
     * @return $this
     */
    public function removeRubrique(Rubrique $rubrique): self
    {
        if ($this->rubriques->contains($rubrique)) {
            $this->rubriques->removeElement($rubrique);
            $rubrique->removePrestataire($this);
        }
        return $this;
    }

    /**
     * @return Amap[]|ArrayCollection
     */
    public function getGroupeprestataires()
    {
        return $this->groupeprestataires;
    }

    /**
     * @param Amap[]|ArrayCollection
     * @return this
     */
    public function setGroupeprestataires($groupeprestataires): self
    {
        $this->groupeprestataires = $groupeprestataires;
        return $this;
    }

    /**
     * @param Amap $amap
     * @return $this
     */
    public function addGroupeprestataire(Groupeprestataire $groupeprestataire): self
    {
        if (!$this->groupeprestataires->contains($groupeprestataire)) {
            $this->groupeprestataires[] = $groupeprestataire;
            $groupeprestataire->addPrestataire($this);
        }
        return $this;
    }

    /**
     * @param Amap $amap
     * @return $this
     */
    public function removeGroupeprestataire(Groupeprestataire $groupeprestataire): self
    {
        if ($this->groupeprestataires->contains($groupeprestataire)) {
            $this->groupeprestataires->removeElement($groupeprestataire);
            $groupeprestataire->removePrestataire($this);
        }
        return $this;
    }

    /**
     * @return EtatPrestataire[]|ArrayCollection
     */
    public function getEtats()
    {
        return $this->etats;
    }

    public function getEtatsString(): ?string
    {
        return join(' - ', array_map(function ($etat) {
            return $etat->getName();
        }, $this->etats->getValues()));
    }

    /**
     * @param EtatPrestataire[]|ArrayCollection
     * @return this
     */
    public function setEtats($etats): self
    {
        $this->etats = $etats;
        return $this;
    }

    /**
     * @param EtatPrestataire $etat
     * @return $this
     */
    public function addEtat(EtatPrestataire $etat): self
    {
        if (!$this->etats->contains($etat)) {
            $this->etats[] = $etat;
            $etat->addPrestataire($this);
        }
        return $this;
    }

    /**
     * @param Etat Prestataire $etat
     * @return $this
     */
    public function removeEtat(EtatPrestataire $etat): self
    {
        if ($this->etats->contains($etat)) {
            $this->etats->removeElement($etat);
            $etat->removePrestataire($this);
        }
        return $this;
    }

    /**
    * Get horaires
    * @return string Horaires
    */
    public function getHoraires(): ?string
    {
        return $this->horaires;
    }

    /**
    * Set horaires
    * @return $this
    */
    public function setHoraires($horaires): self
    {
        $this->horaires = $horaires;
        return $this;
    }

    /**
    * Get media
    * @return
    */
    public function getMedia()
    {
        return $this->media;
    }

    /**
    * Set media
    * @return $this
    */
    public function setMedia($media): self
    {
        $this->media = $media;
        return $this;
    }

    /**
    * Get tauxreconversion
    * @return
    */
    public function getTauxreconversion(): ?float
    {
        return $this->tauxreconversion;
    }

    /**
    * Set tauxreconversion
    * @return $this
    */
    public function setTauxreconversion(?float $tauxreconversion): self
    {
        $this->tauxreconversion = $tauxreconversion;
        return $this;
    }

    public function __toString(): string
    {
        return ($this->raison?$this->raison:'Prestataire '.$this->id);
    }

    public function getMapContent(): ?string
    {
        return 'mapcontentpresta';
    }

    /**
     * @return Collection|User[]
     */
    public function getCaissiers(): Collection
    {
        return $this->caissiers;
    }

    public function getCaissiersString()
    {
        return join(' - ', array_map(function ($user) {
            return $user->getName() . ':' . $user->getEmail();
        }, $this->caissiers->getValues()));
    }

    public function addCaissier(User $caissier): self
    {
        if (!$this->caissiers->contains($caissier)) {
            $this->caissiers[] = $caissier;
        }

        return $this;
    }

    /**
     * @param ArrayCollection[]|User $caissiers
     *
     * @return Prestataire
     */
    public function setCaissiers($caissiers): self
    {
        $this->caissiers = $caissiers;

        return $this;
    }


    public function removeCaissier(User $caissier): self
    {
        if ($this->caissiers->contains($caissier)) {
            $this->caissiers->removeElement($caissier);
        }

        return $this;
    }
}
