<?php

/**
 * Lifestyle Webconsulting GmbH
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is private by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * @copyright  2018 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */

namespace Sso\WebserviceBundle\Entity\Webservice\Type;

use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Validator\ValidatorInterface as Validator;
use Sso\WebserviceBundle\Api\Exception\Type\Api as ApiException;

/**
 * Class Application
 *
 * @copyright  2017 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package    Sso\WebserviceBundle\Entity\Webservice\Type
 */
class Application extends Base
{
    /**
     * Application id
     *
     * @var string
     */
    private $Id;

    /**
     * Application name
     *
     * @var string
     */
    private $Name;

    /**
     * Application name lower case
     *
     * @var string
     */
    private $Lowername;

    /**
     * Application Description
     *
     * @var string
     */
    private $Description;

    /**
     * List of roles
     *
     * @var ArrayCollection|Role[]
     */
    private $Roles;

    /**
     * @var ArrayCollection|Attribute[]
     */
    private $Attributes;

    /**
     * @var ArrayCollection|UserApplication[]
     */
    private $UserApplications;

    /**
     * Constructor
     *
     * @param Validator $valApi
     */
    public function __construct(Validator $valApi)
    {
        parent::__construct($valApi);
        $this->Roles = new ArrayCollection();
        $this->Attributes = new ArrayCollection();
        $this->UserApplications = new ArrayCollection();
    }

    /**
     * Initialize object with new values
     *
     * @param array|object $values
     * @param array|null $validationGroups Null for full validation, array of group-name(s) for group specific validation
     */
    public function init($values, $validationGroups = null)
    {
        // Generate new application-id
        $this->generateId();

        parent::init($values, $validationGroups);
    }

    /**
     * Set Id
     *
     * @param string $id
     * @return Application
     * @throws ApiException
     */
    public function setId($id)
    {
        if (null !== $this->Id && $id !== $this->Id) {
            throw new ApiException('It is not allowed, to change the application-id!');
        }

        $this->Id = $id;

        return $this;
    }

    /**
     * Get application id
     *
     * @return string
     */
    public function getId()
    {
        return $this->Id;
    }

    /**
     * Generate unique user id
     *
     * @throws ApiException
     * @return string User-Id
     */
    public function generateId()
    {
        if (null !== $this->Id) {
            throw new ApiException('Changing the application-id is not allowed!');
        }
        return $this->Id = hash('sha256', mt_rand() . '#' . microtime());
    }

    /**
     * Set application name
     *
     * @param string $Name
     * @return Application
     */
    public function setName($Name)
    {
        $this->Name = $Name;
        $this->Lowername = strtolower($Name);

        return $this;
    }

    /**
     * Get application name
     *
     * @return string
     */
    public function getName()
    {
        return $this->Name;
    }

    /**
     * Get application lowername
     *
     * @return string
     */
    public function getLowername()
    {
        return $this->Lowername;
    }

    /**
     * Set application description
     *
     * @param string $Description
     * @return Application
     */
    public function setDescription($Description)
    {
        $this->Description = $Description;

        return $this;
    }

    /**
     * Get application description
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->Description;
    }

    /**
     * Add Role
     *
     * @param Role $Role
     * @return Application
     */
    public function addRole(Role $Role)
    {
        $this->Roles[] = $Role;

        return $this;
    }

    /**
     * Remove Role
     *
     * @param Role $Role
     */
    public function removeRole(Role $Role)
    {
        $this->Roles->removeElement($Role);
    }

    /**
     * Get Roles
     *
     * @return ArrayCollection|Role[]
     */
    public function getRoles()
    {
        return $this->Roles;
    }

    /**
     * Returns true, if application has any roles
     *
     * @return bool
     */
    public function hasRoles()
    {
        return 0 < count($this->Roles);
    }

    /**
     * Returns true, if application has this role
     *
     * @param RoleInterface $role
     * @return bool
     */
    public function hasRole(RoleInterface $role)
    {
        return null !== $this->getRole($role->getName());
    }

    /**
     * Get role by name
     *
     * @param string $name
     * @return Role|null
     */
    public function getRole($name)
    {
        foreach ($this->Roles as $role) {
            if (0 === strcasecmp($name, $role->getName())) {
                return $role;
            }
        }
        return null;
    }

    /**
     * Add Attribute
     *
     * @param Attribute $attribute
     * @return Application
     */
    public function addAttribute(Attribute $attribute)
    {
        $this->Attributes[] = $attribute;

        return $this;
    }

    /**
     * Remove Attribute
     *
     * @param Attribute $attribute
     */
    public function removeAttribute(Attribute $attribute)
    {
        $this->Attributes->removeElement($attribute);
    }

    /**
     * Get Attributes
     *
     * @return ArrayCollection|Attribute[]
     */
    public function getAttributes()
    {
        return $this->Attributes;
    }

    /**
     * Returns true, if application has any attributes
     *
     * @return bool
     */
    public function hasAttributes()
    {
        return 0 < count($this->Attributes);
    }

    /**
     * Returns true, if application has this attribute
     *
     * @param AttributeInterface $attribute
     * @return bool
     */
    public function hasAttribute(AttributeInterface $attribute)
    {
        return null !== $this->getAttribute($attribute->getName());
    }

    /**
     * Get attribute by name
     *
     * @param string $name
     * @return Attribute|null
     */
    public function getAttribute($name)
    {
        foreach ($this->Attributes as $attribute) {
            if (0 === strcasecmp($name, $attribute->getName())) {
                return $attribute;
            }
        }
        return null;
    }

    /**
     * Add UserApplication
     *
     * @param UserApplication $userApplication
     * @return Application
     */
    public function addUserApplication(UserApplication $userApplication)
    {
        $this->UserApplications[] = $userApplication;

        return $this;
    }

    /**
     * Remove UserApplication
     *
     * @param UserApplication $userApplication
     */
    public function removeUserApplication(UserApplication $userApplication)
    {
        $this->UserApplications->removeElement($userApplication);
    }

    /**
     * Get UserApplications
     *
     * @return ArrayCollection|UserApplication[]
     */
    public function getUserApplications()
    {
        return $this->UserApplications;
    }
}
