<?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\FAQ\Category;
use App\Entity\FAQ\Item;
use App\Model\FAQ\Categories;
use App\Model\FAQ\Items;
use App\Model\HideableInterface;
use Monolog\Logger;
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 FAQ
 * @package App\Action\Admin
 */
class FAQ extends Common
{
    const ACTION_ITEM_EDIT = 'item-edit';
    const ACTION_ITEM_HIDE = 'item-hide';
    const ACTION_ITEM_ACTIVATE = 'item-activate';
    const ACTION_CATEGORY_EDIT = 'category-edit';
    const ACTION_ITEM_CREATE = 'item-create';
    const ACTION_ITEM_SAVE_AND_CONTINUE = 'save-and-continue';
    const ACTION_ITEM_SAVE_AND_TRANSLATE = 'save-and-translate';
    const ACTION_CATEGORY_HIDE = 'category-hide';
    const ACTION_CATEGORY_ACTIVATE = 'category-activate';

    /**
     * @param ServerRequestInterface $request
     * @param ResponseInterface $response
     * @param callable|null $next
     * @return HtmlResponse
     */
    function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
    {

        switch ($request->getAttribute('action')) {
            case self::ACTION_ITEM_ACTIVATE:
                $response = $this->updateHiddenItem($request->getAttribute('id'), Item::IS_NOT_HIDDEN);
                break;
            case self::ACTION_ITEM_HIDE:
                $response = $this->updateHiddenItem($request->getAttribute('id'), Item::HIDDEN);
                break;
            case self::ACTION_ITEM_EDIT:
                $response = $this->itemEdit($request, self::ACTION_ITEM_EDIT);
                break;
            case self::ACTION_ITEM_CREATE:
                $response = $this->itemEdit($request, self::ACTION_ITEM_CREATE);
                break;
            case self::ACTION_CATEGORY_EDIT:
                $response = $this->categoryEdit($request);
                break;
            case self::ACTION_CATEGORY_HIDE:
                $response = $this->updateHiddenCategory($request->getAttribute('id'), Category::HIDDEN);
                break;
            case self::ACTION_CATEGORY_ACTIVATE:
                $response = $this->updateHiddenCategory($request->getAttribute('id'), Category::IS_NOT_HIDDEN);
                break;
            default:

                /** @var Categories $categoriesModel */
                $categoriesModel = $this->container->get(Categories::class);

                /** @var Items $itemsModel */
                $itemsModel = $this->container->get(Items::class);

                /** @var Category[] $categories */
                $categories = $categoriesModel->findAll([HideableInterface::COLUMN_NAME_HIDDEN => HideableInterface::ANY]);

                $items = $itemsModel->findAll([HideableInterface::COLUMN_NAME_HIDDEN => HideableInterface::ANY], 'faq_categories_id ASC, id ASC');

                $itemsGrouped = $itemsModel->makeGrouped($items);

                $data = [
                    'categories' => $categories,
                    'items' => $itemsGrouped,
                    'lang' => $request->getAttribute('layoutInfo')->getLang(),
                ];

                $response = new HtmlResponse($this->template->render('adm::faq', $data));
                break;
        }
        return $response;
    }

    /**
     * @param ServerRequestInterface $request
     * @return null|HtmlResponse|RedirectResponse
     * @throws \Exception
     */
    private function categoryEdit(ServerRequestInterface $request)
    {
        $id = $request->getAttribute('id');
        $method = $request->getMethod();

        $response = null;

        /** @var Categories $categoriesModel */
        $categoriesModel = $this->container->get(Categories::class);

        /** @var Category $category */
        $category = $categoriesModel->findByIdWithHidden($id);
        if (!$category) {
            throw new \Exception(_t('FAQ category not found'));
        }

        $data = $request->getParsedBody();
        $data += [
            'lang' =>  $request->getAttribute('layoutInfo')->getLang(),
            'category' => $category,
            'flash' => $request->getAttribute('flash'),
        ];

        if ($method == 'POST') {
            /** @var DelegatingHydrator $hydrator */
            $hydrator = $this->container->get(DelegatingHydrator::class);

            $category = $hydrator->hydrate($data, $category);
            try {
                $categoriesModel->save($category);
                //$response = new RedirectResponse($this->router->generateUri('adm.translations', ['part' => 'faq', 'action' => Translation::ACTION_GENERATE]));
            } catch (\Exception $e){
                /** @var Messages $flash */
                $flash = $request->getAttribute('flash');
                $flash->addMessage('error', $e->getMessage());

                /** @var Logger $log */
                $log = $this->container->get(Logger::class);
                $log->error($e->getMessage(), ['trace' => $e->getTraceAsString()]);

                $response = new RedirectResponse($request->getUri());
            }
        }

        if (!$response) {
            $response = new HtmlResponse($this->template->render('adm::faq/edit/category', $data));
        }
        return $response;
    }

    /**
     * @param $id
     * @param $hidden
     * @return JsonResponse
     */
    private function updateHiddenItem($id, $hidden)
    {
        /** @var Items $itemsModel */
        $itemsModel = $this->container->get(Items::class);

        $item = $itemsModel->findByIdWithHidden($id);
        $data = [];
        if ($item) {
            /** @var DelegatingHydrator $hydrator */
            $hydrator = $this->container->get(DelegatingHydrator::class);
            $item = $hydrator->hydrate(['hidden' => $hidden], $item);

            try {
                /** @noinspection PhpParamsInspection */
                $itemsModel->save($item);
                $data['result'] = true;
            } catch (\Exception $e) {
                $data['result'] = false;
                $data['msg'] = $e->getMessage();
            }
        } else {
            $data['result'] = false;
            $data['msg'] = 'Not found';
        }
        $response = new JsonResponse($data);
        return $response;
    }

    /**
     * @param ServerRequestInterface $request
     * @param $action
     * @return HtmlResponse|RedirectResponse
     * @throws \Exception
     */
    private function itemEdit(ServerRequestInterface $request, $action)
    {
        /** @var Items $itemsModel */
        $itemsModel = $this->container->get(Items::class);

        $lang = $request->getAttribute('lang');
        $method = $request->getMethod();

        if ($action == self::ACTION_ITEM_EDIT) {
            /** @var Items $item */
            $item = $itemsModel->findByIdWithHidden($request->getAttribute('id'));
            if (!$item) {
                throw new \Exception(_t('FAQ question not found'));
            }
        } elseif ($action == self::ACTION_ITEM_CREATE) {
            $item = new Item();
            $item->setFaqCategoriesId($request->getAttribute('categoriesId'));
        } else {
            throw new \Exception('Unknown action');
        }


        $data = $request->getParsedBody();
        $data += [
            'lang' => $lang,
            'item' => $item,
            'flash' => $request->getAttribute('flash'),
        ];

        if ($method == 'POST') {
            /** @var DelegatingHydrator $hydrator */
            $hydrator = $this->container->get(DelegatingHydrator::class);

            $item = $hydrator->hydrate($data, $item);
            try {
                /** @noinspection PhpParamsInspection */
                $itemId = $itemsModel->save($item);
                if (isset($data[FAQ::ACTION_ITEM_SAVE_AND_CONTINUE])) {
                    $response = new RedirectResponse($this->router->generateUri('adm.faq.item.edit', $data + ['id' => $itemId]));
                } elseif(isset($data[FAQ::ACTION_ITEM_SAVE_AND_TRANSLATE])) {
                    //$response = new RedirectResponse($this->router->generateUri('adm.translations', ['part' => 'faq', 'action' => Translation::ACTION_GENERATE]));
                }
            } catch (\Exception $e){
                /** @var Messages $flash */
                $flash = $request->getAttribute('flash');
                $flash->addMessage('error', $e->getMessage());

                /** @var Logger $log */
                $log = $this->container->get(Logger::class);
                $log->error($e->getMessage(), ['trace' => $e->getTraceAsString()]);

                $response = new RedirectResponse($request->getUri());
            }
        } else {
//            var_dump('here');
        }

        if (!isset($response)) {
            $response = new HtmlResponse($this->template->render('adm::faq/edit/item', $data));
        }
        return $response;
    }

    /**
     * @param $id
     * @param $hidden
     * @return JsonResponse
     */
    private function updateHiddenCategory($id, $hidden)
    {
        /** @var Categories $categoriesModel */
        $categoriesModel = $this->container->get(Categories::class);

        $category = $categoriesModel->findByIdWithHidden($id);
        $data = [];
        if ($category) {
            /** @var DelegatingHydrator $hydrator */
            $hydrator = $this->container->get(DelegatingHydrator::class);
            $category = $hydrator->hydrate(['hidden' => $hidden], $category);

            try {
                /** @noinspection PhpParamsInspection */
                $categoriesModel->save($category);
                $data['result'] = true;
            } catch (\Exception $e) {
                $data['result'] = false;
                $data['msg'] = $e->getMessage();
            }
        } else {
            $data['result'] = false;
            $data['msg'] = _t('Not found');
        }
        $response = new JsonResponse($data);
        return $response;
    }

}