<?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  2019 Lifestyle Webconsulting GmbH
 * @link       https://www.life-style.de
 */

namespace SimpleSAML\Module\lifestyle\Webservice;

use SimpleSAML\Logger;
use SimpleSAML\Module\lifestyle\UserApplication\Application;
use SimpleSAML\Module\lifestyle\UserApplication\Attribute;
use SimpleSAML\Module\lifestyle\UserApplication\Role;
use SimpleSAML\Module\lifestyle\Webservice\Api\Manager;
use SimpleSAML\Module\lifestyle\Webservice\Model\Response\IdP\PostLogin\Response;

/**
 * Class Handler
 *
 * @copyright  2019 Lifestyle Webconsulting GmbH
 * @link       https://www.life-style.de
 * @package SimpleSAML\Module\lifestyle\Webservice
 */
class Handler
{
    /**
     * @var Manager
     */
    private static $apiM;

    /**
     * @var Response[]
     */
    private static $cache = array();

    /**
     * @var array
     */
    private static $loginStatus = array();

    /**
     * Get auth source id for user from user-webservice
     *
     * @param string $username
     * @param string $password
     * @return Response
     */
    public static function getUser($username, $password)
    {
        $key = md5($username . '###' . $password);

        // User already pulled from webservice
        if (isset(static::$cache[$key])) {
            return static::$cache[$key];
        }

        return static::$cache[$key] = static::apiM()->handler()->postLogin()->handle($username, $password);
    }

    /**
     * Validate users credentials against user-webservice
     *
     * @param string $username
     * @param string $mfaToken
     * @return bool
     */
    public static function validateMfaToken($username, $mfaToken)
    {
        return static::apiM()->handler()->postMfaValidate()->handle($username, $mfaToken);
    }

    /**
     * Set login status
     *
     * @param string $username
     * @param boolean $success True: login success, false: login failure
     */
    public static function setLoginStatus($username, $success)
    {
        $key = md5($username);

        // Status already sent
        if (isset(static::$loginStatus[$key]) && static::$loginStatus[$key] === $success) {
            return;
        }

        if ($success) {
            static::apiM()->handler()->postLoginSuccess()->handle($username);
        } else {
            static::apiM()->handler()->postLoginFailed()->handle($username);
        }

        static::$loginStatus[$key] = $success;
    }

    /**
     * Get user application attributes and roles from user-webservice
     *
     * @param string $username
     * @param array $applications
     * @return Application[]
     */
    public static function getUserApplicationAttributes($username, $applications)
    {
        $response = static::apiM()->handler()->postUser()->handle($username, $applications);
        if ($response->getErrors()) {
            foreach ($response->getErrors() as $error) {
                Logger::error(sprintf('Error while pulling user-application-attributes: %s', $error->toString()));
            }
            return array();
        }
        $userApplications = array();
        foreach ($response->getApplications() as $application) {
            $applicationModel = Application::fromString($application->getName());
            foreach ($application->getAttributes() as $attribute) {
                $applicationModel->addAttribute(Attribute::fromString($attribute->getName(), $attribute->getValue()));
            }
            foreach ($application->getRoles() as $role) {
                $applicationModel->addRole(Role::fromString($role->getName()));
            }
            $userApplications[$application->getName()] = $applicationModel;
        }
        return $userApplications;
    }

    /**
     * @return Manager
     */
    private static function apiM()
    {
        return null !== static::$apiM ? static::$apiM : (static::$apiM = new Manager());
    }
}
