<?php
namespace Cobblestone\CcLogin\Security;

use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUser;
use Cobblestone\CcLogin\Entity\Asset;
use Cobblestone\CcLogin\Entity\Position;

/**
 * Class CCUser
 *
 * This class representes a user logged in through Auth0, and a user that has a profile in the
 * CC User Right Management (CC-UR;) system. When logging in, the CC-URM will be called to fetch
 * relevant info for the user including, name, language preferences and which roles the user has
 *
 * This data is available in the getProfileData, but convenience methods for most used data (name
 * etc.) are supplied.
 *
 * @package Cobblestone\CcLogin\Security
 */
class CCUser extends OAuthUser {

    /**
     * @var
     */
    protected $profileData;

    /**
     * @var bool
     */
    protected $isAdmin = false;

    /**
     * @param mixed $profileData
     */
    public function setProfileData($profileData): void
    {
        $this->profileData = $profileData;
    }

    /**
     * @var Asset[]|array
     */
    protected $assets = [];

    /**
     * @var array
     */
    protected $assetRoles = [];

    /**
     * Array of all Asset Poitions that exist in the system, including the ones that the user doesn't necessarily have access to
     *
     * @var Position[]
     */
    protected $positions;

    /**
     * Array mapping the Asset Positions available to the user
     *
     * @var array
     */
    protected $userAssetPositions;

    /**
     * @return mixed
     */
    public function getProfileData()
    {
        return $this->profileData;
    }

    /**
     * @return string
     */
    public function getName() {
        return $this->getProfileDataValue("name", $this->getUserName());
    }

    /**
     * @return string
     */
    public function getIdToken() {
        return $this->getProfileDataValue("id_token");
    }

    /**
     * @return string
     */
    public function getUserId() {
       return $this->getProfileDataValue("id");
    }

    /**
     * @return mixed
     */
    public function getPictureUrl() {
        return $this->getProfileDataValue("picture_url");
    }

    /**
     * @return mixed
     */
    public function getLanguage() {
        return $this->getProfileDataValue("locale", "en");
    }

    /**
     * @param $key
     * @return mixed
     */
    private function getProfileDataValue($key, $default = null) {
        if ($this->profileData && isset($this->profileData[$key])) {
            return $this->profileData[$key];
        }
        return $default;

    }

    /***
     * @return array|\Symfony\Component\Security\Core\Role\Role[]
     */
    public function getRoles()
    {
        $roles = array('ROLE_USER', 'ROLE_OAUTH_USER');

        if ($this->isAdmin) {
            array_push($roles, 'ROLE_ADMIN');
        }

        return $roles;
    }

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

    /**
     * @param bool $isAdmin
     */
    public function setIsAdmin(bool $isAdmin): void
    {
        $this->isAdmin = $isAdmin;
    }

    /**
     * @return Asset[]|array
     */
    public function getAssets(): array
    {
        return $this->assets;
    }

    /**
     * @param Asset[]|array $assets
     */
    public function setAssets(array $assets): void
    {
        $this->assets = $assets;
    }

    /**
     * @return array
     */
    public function getAssetRoles(): array
    {
        return $this->assetRoles;
    }

    /**
     * @param array $assetRoles
     */
    public function setAssetRoles(array $assetRoles): void
    {
        $this->assetRoles = $assetRoles;
    }

    /**
     * @return Position[]
     */
    public function getPositions(): array
    {
        return $this->positions;
    }

    /**
     * @param Position[] $positions
     */
    public function setPositions(array $positions): void
    {
        $this->positions = $positions;
    }


    /**
     * @param bool $onlyPositions If true, this function will omit the mapping information and only return Positions that the user has access to on ANY Asset
     * @return array|Position[]
     */
    public function getUserAssetPositions(bool $onlyPositions = false): array
    {
        $userAssetPositions = $this->userAssetPositions;

        if (!is_array($userAssetPositions)) {
            return [];
        }

        if ($onlyPositions) {
            $positions = [];

            foreach ($userAssetPositions as $assetPosition) {
                foreach ($assetPosition["positionIds"] as $positionId) {
                    // Check if this Position has already been added to the $positions array
                    // We don't want to return duplicates
                    $matchingPositions = array_filter($positions, function (Position $position) use ($positionId) {
                        return $position->getId() === $positionId;
                    });

                    // If the Position has not already been added, add it to the $positions array
                    if (count($matchingPositions) === 0) {
                        foreach ($this->getPositions() as $position) {
                            if ($position->getId() === $positionId) {
                                $positions[] = $position;
                                break;
                            }
                        }
                    }
                }
            }

            return $positions;
        }

        return $userAssetPositions;
    }

    /**
     * @param array $userAssetPositions
     */
    public function setUserAssetPositions(array $userAssetPositions): void
    {
        $this->userAssetPositions = $userAssetPositions;
    }
}
