<?php 
namespace PortalPeople\oauth2;

use Yii;
use yii\base\Event;
use PortalPeople\oauth2\models\OauthUser;
use PortalPeople\oauth2\models\OauthClients;
use PortalPeople\oauth2\models\OauthAccessTokens;
use PortalPeople\oauth2\models\OauthRefreshTokens;
use PortalPeople\oauth2\behaviors\RelationBehavior;
use OAuth2\Storage\Pdo;
use OAuth2\Server;
use OAuth2\GrantType\{AuthorizationCode, ClientCredentials, RefreshToken, UserCredentials};

use yii\helpers\Html;

class Oauth2Module extends \yii\base\Module implements \yii\base\BootstrapInterface
{
    public $controllerNamespace = 'PortalPeople\\oauth2\\controllers';
    /**
     * @var array Model's map
     */
    public $modelMap = [];
    
    /**
     * @var array Storage's map
     */
    public $storageMap = [];
    
    /**
     * @var array GrantTypes collection
     */
    public $grantTypes = [];
    
    /**
     * @var array server options
     */
    public $options = [];

    /**
     * @var string name of access token parameter
     */
    public $tokenParamName;
    /**
     * @var type max access lifetime
     */
    public $tokenAccessLifetime;
    /**
     * @var whether to use JWT tokens
     */
    public $useJwtToken = false;
    public function bootstrap($app)
    {    
        $app->setModule('oauth2', [
            'class' => 'PortalPeople\oauth2\Oauth2Module',
            'tokenParamName' => 'accessToken',
            'tokenAccessLifetime' => 3600 * 24,
            'storageMap' => [
                'user_credentials' => 'PortalPeople\oauth2\models\OauthUser',
            ],
            'grantTypes' => [
                'code' => [
                    'class' => 'OAuth2\GrantType\AuthorizationCode',
                ],
                'user_credentials' => [
                    'class' => 'OAuth2\GrantType\UserCredentials',
                    'allow_public_clients' => true,
                ],
                'client_credentials' => [
                    'class' => 'OAuth2\GrantType\ClientCredentials',
                    'allow_credentials_in_request_body' => true
                ],
                'refresh_token' => [
                    'class' => 'OAuth2\GrantType\RefreshToken',
                    'always_issue_new_refresh_token' => true,
                    'refresh_token_lifetime'         => 2419200, /** 14Days */
                ]
            ]
        ]);

        // Attach behavior to User model instances as they're initialized
        Event::on(
            \yii\base\View::class,
            'user.update.after.buttons',
            function($event) {
                $model = $event->sender;
                echo Html::tag('li', 
                    Html::A('Create Excel Token', ['user/create-excel-token', 'id' => $model->id], ['class' => 'btn bg-primary text-white nav-item w-100 mt-2']),
                    ['class'=>"nav-item"]);
                echo Html::tag('li', 
                    Html::Button('Reset OAuth', ['class' => 'btn bg-danger text-white nav-item w-100 mt-2', 'onClick' => '']),
                    ['class'=>"nav-item"]);
        });
        Event::on(
            \yii\base\View::class,
            'user.update.after.tabs',
            function($event) {    
                Yii::warning('triggered');
                $items = $event->customData['items'];        
                $form = $event->customData['form'];
                $model = $event->sender;
                $items[] = [
                    'label' => Yii::t('app', 'API Details'), 
                    'content'=> Yii::$app->view->render('@PortalPeople/oauth2/views/user/formtabs/_oauth2', ['model' => $model, 'form' => $form]), 
                    'active' => false
                ];
                $event->result = $items;
            }
        );
        Event::on(
            \backend\models\User::class,
            'init',
            function($event) {
                if (!$event->sender->getBehavior('relations')) {
                    $event->sender->attachBehavior('relations', [
                        'class' => RelationBehavior::class,
                        'relations' => [
                            'oauthSecrets' => [
                                'class' => OauthClients::class,
                                'foreignKey' => ['user_id' => 'id'],
                                'type' => 'hasMany',
                            ],
                            'oauthRefreshTokens' => [
                                'class' => OauthRefreshTokens::class,
                                'foreignKey' => ['user_id' => 'id'],
                                'type' => 'hasMany',
                            ],
                            'oauthAccessTokens' => [
                                'class' => OauthAccessTokens::class,
                                'foreignKey' => ['user_id' => 'id'],
                                'type' => 'hasMany',
                            ],
                        ],
                    ]);
                }
            }
        );
        Event::on(
            common\models\User::class,
            'user.afterSave',
            function($event) {
                $model = $event->sender;
                if($event->sender->model->api == 1 && !$model->oauthSecrets){
                    $oauth = new \modules\oauth2\models\OauthClients();
                    $oauth->client_id = str_replace('-','', $model->id);
                    $oauth->user_id = $model->user_id;
                    $oauth->redirect_uri = '/';
                    $oauth->grant_types = 'client_credentials authorization_code password implicit refresh_token';
                    $oauth->save();
                }
            }
        );
    }
    public function getServer(){
        $db = Yii::$app->db;
        $storage = new Pdo(['dsn' => $db->dsn, 'username' => $db->username, 'password' =>  $db->password, 'options' => []]);
        
        // Pass a storage object or array of storage objects to the OAuth2 server class
        $server =  new Server($storage, [
            'allow_implicit' => true,
            'access_lifetime' => 3600 * 24,
            'allow_public_clients' => true,
        ], [
            'password' => new UserCredentials(new OauthUser()),
            'client_credentials' => new ClientCredentials($storage),
            'authorization_code' => new AuthorizationCode($storage),
            'refresh_token' => new RefreshToken($storage),
        ]);    


        return $server;
    }
    /**
     * @inheritdoc
     */
    public function init()
    {
        parent::init();
        Yii::$app->urlManager->addRules([
            'admin/<controller:\w+>/<action:\w+>' => 'oauth2/<controller>/<action>',
        ]);
    }
}
