<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonPickwareCommon\Subscribers\Backend;

use Shopware\Models\Attribute\User as UserAttribute;
use Shopware\Models\User\User;
use Shopware\Plugins\ViisonCommon\Classes\Subscribers\Base;

class UserManager extends Base
{
    /**
     * @see \Shopware\Plugins\ViisonCommon\Classes\Subscribers\Base::getSubscribedEvents()
     */
    public static function getSubscribedEvents()
    {
        return [
            'Enlight_Controller_Action_PostDispatchSecure_Backend_UserManager' => 'onPostDispatchSecure',
            'Shopware_Controllers_Backend_UserManager::getUserDetailsAction::after' => 'onAfterGetUserDetailsAction',
            'Shopware_Controllers_Backend_UserManager::updateUserAction::after' => 'onAfterUpdateUserAction',
        ];
    }

    /**
     * Adds custom extensions to the loaded sub application, which cannot be loaded using
     * ViisonCommon's sub application loader.
     *
     * @param \Enlight_Event_EventArgs $args
     */
    public function onPostDispatchSecure(\Enlight_Event_EventArgs $args)
    {
        if ($args->getRequest()->getActionName() === 'load') {
            $view = $args->getSubject()->View();
            $view->extendsTemplate('backend/viison_pickware_common/user_manager/model/user_detail.js');
        }
    }

    /**
     * Adds the Pickware PIN as a top-level element to the response data.
     *
     * @param \Enlight_Hook_HookArgs $args
     */
    public function onAfterGetUserDetailsAction(\Enlight_Hook_HookArgs $args)
    {
        $view = $args->getSubject()->View();
        if ($view->success !== true) {
            return;
        }

        // Add the Pickware PIN to the top-level data
        $data = $view->data;
        $data['attribute']['viisonPickwarePin'] = 'dummyPin';
        $data['viisonPickwarePin'] = $data['attribute']['viisonPickwarePin'];
        $view->data = $data;
    }

    /**
     * Checks the request parameters for a Pickware PIN and, if its not empty, encodes the
     * PIN using the default encoder of the PasswordEncoder services and the hash as well
     * as the encoder name are saved in the user's attributes. Otherwise the PIN and encoder
     * are set to NULL respectively.
     *
     * @param \Enlight_Hook_HookArgs $args
     */
    public function onAfterUpdateUserAction(\Enlight_Hook_HookArgs $args)
    {
        $view = $args->getSubject()->View();
        if ($view->success !== true) {
            return;
        }

        $pin = $args->getSubject()->Request()->getParam('viisonPickwarePin');
        if (empty($pin) || $pin === 'dummyPin') {
            return;
        }

        // Make sure the user has attributes
        $user = $this->get('models')->find(User::class, $view->data['id']);
        $attributes = $user->getAttribute();
        if (!$attributes) {
            $attributes = new UserAttribute();
            $user->setAttribute($attributes);
            $this->get('models')->persist($attributes);
        }

        // Save the hashed PIN and encoder
        $encoderName = $this->get('PasswordEncoder')->getDefaultPasswordEncoderName();
        $encodedPin = $this->get('PasswordEncoder')->encodePassword($pin, $encoderName);
        $attributes->setViisonPickwarePin($encodedPin);
        $attributes->setViisonPickwarePinEncoder($encoderName);

        // Save the hash of the first 4 characters/digits of the PIN in the user attributes. This fixed length PIN will
        // be used by future versions of the apps.
        $fixedLengthPin = mb_substr($pin, 0, 4);
        $encodedFixedLengthPin = $this->get('PasswordEncoder')->encodePassword($fixedLengthPin, $encoderName);
        $attributes->setPickwareFixedLengthAppPin($encodedFixedLengthPin);

        $this->get('models')->flush($attributes);
    }
}
