<?php
/**
 * Copyright (c) 2016 Serhii Borodai <clarifying@gmail.com>.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 *
 */

namespace App\Action\Admin;


use App\Entity\Support;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Flash\Messages;
use Zend\Diactoros\Response\HtmlResponse;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\Response\RedirectResponse;
use Zend\Hydrator\DelegatingHydrator;

/**
 * Class Supports
 * @package App\Action\Admin
 */
class Supports extends Common
{
    const ACTION_DELETE = 'delete';
    const ACTION_CREATE = 'create';
    const ACTION_EDIT = 'edit';


    /**
     * @param ServerRequestInterface $request
     * @param ResponseInterface $response
     * @param callable|null $next
     * @return HtmlResponse
     */
    function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
    {
        if($request->getMethod() == 'POST') {
            try {
                switch ($request->getAttribute('action')) {
                    case self::ACTION_CREATE:                        
                        $response = $this->create($request);
                        break;
                    case self::ACTION_EDIT:
                        $response = $this->edit($request);
                        break;
                    case self::ACTION_DELETE:
                        $response = $this->delete($request);
                        break;
                    default:                    
                }
            } catch(\Exception $e) {
                $data = [
                    'result' => false,
                    'msg' => $e->getMessage(),                    
                ];
                $response = new JsonResponse($data);
            }                        
            return $response;            
        } elseif($request->getAttribute('action') == self::ACTION_CREATE || $request->getAttribute('action') == self::ACTION_EDIT) {
            $support = null;
            if($request->getAttribute('action') == self::ACTION_EDIT) {
                $supportModel = $this->container->get(\App\Model\Supports::class);                
                $support = $supportModel->findById($request->getAttribute('id'));
            }
            
            $response = new HtmlResponse($this->template->render('adm::supports/create', [
                'lang' => $request->getAttribute('layoutInfo')->getLang(),
                'support' => $support
            ]));
            return $response;
        } else {
            /** @var \App\Model\Supports $supportsModel */
            $supportsModel = $this->container->get(\App\Model\Supports::class);

            $supportUsers = $supportsModel->findAll(['role_id' => ['admin', 'manager_feed']]);

            $response =  new HtmlResponse($this->template->render('adm::supports', [
                'supports' => $supportUsers,
                'lang' => $request->getAttribute('layoutInfo')->getLang()
            ]));
            return $response;
        }     
    }

    /**
     * @param ServerRequestInterface $request
     * @return HtmlResponse|RedirectResponse
     */
    private function create(ServerRequestInterface $request) 
    {
        /** @var \App\Model\Supports $supportsModel */
        $supportsModel = $this->container->get(\App\Model\Supports::class);
        
        $data = $request->getParsedBody();       
        $data['password'] = $supportsModel->hashPassword($data['password']);               
            
        if($supportsModel->findOne(['email' => $data['email']])) {
            throw new \Exception(sprintf('Support with email &lt;%s&gt; already exists', $data['email']));
        }
        
        /** @var DelegatingHydrator $hydrator */
        $hydrator = $this->container->get(DelegatingHydrator::class);
        
        $support = $hydrator->hydrate($data, new Support());
        
        $validator = new \App\Validator\Support($hydrator);       
        if(!$validator->isValid($support)) {
            throw new \Exception($validator->getMessages()[0]);
        }               
        
        $result = $supportsModel->save($support);
        if(!$result) {
            throw new \Exception('DB error');
        }                 
            
        $response = new JsonResponse([
            'result' => true,
            'redirect' => $this->router->generateUri('adm.supports', ['lang' => $request->getAttribute('layoutInfo')->getLang()])
        ]);
        return $response;
    }
    
    private function edit(ServerRequestInterface $request)
    {
        /** @var \App\Model\Supports $supportsModel */
        $supportsModel = $this->container->get(\App\Model\Supports::class);
        
        /** @var DelegatingHydrator $hydrator */
        $hydrator = $this->container->get(DelegatingHydrator::class);
        
        $data = $request->getParsedBody();       
        
        $support = $supportsModel->findById($request->getAttribute('id'));
        if(!$support) {
            throw new Exception('User not found');
        }
        
        $support->setEmail(trim($data['email']));
        $support->setFullname(trim($data['fullname']));
        $support->setRole($data['role']);
        if($data['password']) {
                $support->setPassword($supportsModel->hashPassword(trim($data['password'])));
        }
        
        if(($existed = $supportsModel->findOne(['email' => $data['email']]))) {
            if($existed->getId() != $support->getId()) {
                throw new \Exception(sprintf('Support with email &lt;%s&gt; already exists', $data['email']));
            }
        }
                  
        $validator = new \App\Validator\Support($hydrator);       
        if(!$validator->isValid($support)) {
            throw new \Exception($validator->getMessages()[0]);
        }
            
        $result = $supportsModel->save($support);
        if(!$result) {
            throw new \Exception('DB error');
        }                 
            
        $response = new JsonResponse([
            'result' => true,
            'redirect' => $this->router->generateUri('adm.supports', ['lang' => $request->getAttribute('layoutInfo')->getLang()])
        ]);
        return $response;        
    }

    /**
     * @param ServerRequestInterface $request
     * @return JsonResponse
     */
    private function delete(ServerRequestInterface $request)
    {
        $id = $request->getAttribute('id');
        /** @var Messages $flash */
        $flash = $request->getAttribute('flash');

        /** @var \App\Model\Supports $supportsModel */
        $supportsModel = $this->container->get(\App\Model\Supports::class);
        $data['result'] = false;
        try {
            $data['result'] = $supportsModel->deleteById($id);
            $flash->addMessage('success', 'Support with ID: ' . $id . ' successfully deleted');

        } catch (\Exception $e) {
            $flash->addMessage('error', $e->getMessage());
            $data['msg'] = $e->getMessage();
        }
        return new JsonResponse($data);
    }
}