<?php

// bind storefront js lib
$this->bind('/api/pages/storefront.js', function() {

    $this->response->mime = 'js';

    $code = $this->render('pages:assets/storefront/storefront.js');

    return $code;
});

/**
 *
 * @OA\Tag(
 *   name="pages",
 *   description="Pages module",
 * )
 */

$this->on('restApi.config', function($restApi) {

    /**
     * @OA\Get(
     *     path="/pages/settings",
     *     tags={"pages"},
     *     @OA\Parameter(
     *         description="Return settings for specified locale",
     *         in="query",
     *         name="locale",
     *         required=false,
     *         @OA\Schema(type="string")
     *     ),
     *     @OA\Response(response="200", description="General pages settings as JSON", @OA\JsonContent())
     * )
     */

    $restApi->addEndPoint('/pages/settings', [
        'GET' => function($params, $app) {

            if (!$app->helper('acl')->isAllowed('pages/api/read', $app->helper('auth')->getUser('role'))) {
                $app->response->status = 403;
                return ['error' => 'Permission denied'];
            }

            $locale = $app->param('locale:string', 'default');
            $settings = $app->module('pages')->settings();

            return $app->helper('locales')->applyLocales($settings, $locale);
        }
    ]);

    /**
     * @OA\Get(
     *     path="/pages/menus",
     *     tags={"pages"},
     *    @OA\Parameter(
     *         description="Return links for specified locale",
     *         in="query",
     *         name="locale",
     *         required=false,
     *         @OA\Schema(type="string")
     *     ),
     *    @OA\Parameter(
     *         description="Return inactive links",
     *         in="query",
     *         name="inactive",
     *         required=false,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(response="200", description="List of all menus", @OA\JsonContent(type="array", @OA\Items(type="object", additionalProperties=true)))
     * )
    */

    $restApi->addEndPoint('/pages/menus', [
        'GET' => function($params, $app) {

            if (!$app->helper('acl')->isAllowed('pages/api/read', $app->helper('auth')->getUser('role'))) {
                $app->response->status = 403;
                return ['error' => 'Permission denied'];
            }

            $locale = $app->param('locale:string', 'default');
            $filterInactiveLinks = $app->param('inactive:int', 0) ? false : true;

            return $app->module('pages')->menus(process: ['resolveLinks' => true, 'filterInactiveLinks' => $filterInactiveLinks, 'locale' => $locale]);
        }
    ]);

    /**
     * @OA\Get(
     *     path="/pages/menu/{name}",
     *     tags={"pages"},
     *     @OA\Parameter(
     *         description="Menu name",
     *         in="path",
     *         name="name",
     *         required=true,
     *         @OA\Schema(type="string")
     *     ),
     *    @OA\Parameter(
     *         description="Return links for specified locale",
     *         in="query",
     *         name="locale",
     *         required=false,
     *         @OA\Schema(type="string")
     *     ),
     *    @OA\Parameter(
     *         description="Return inactive links",
     *         in="query",
     *         name="inactive",
     *         required=false,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(response="200", description="Menu object", @OA\JsonContent()),
     *     @OA\Response(response="404", description="Menu not found")
     * )
    */

    $restApi->addEndPoint('/pages/menu/{name}', [

        'GET' => function($params, $app) {

            if (!$app->helper('acl')->isAllowed('pages/api/read', $app->helper('auth')->getUser('role'))) {
                $app->response->status = 403;
                return ['error' => 'Permission denied'];
            }

            $locale = $app->param('locale:string', 'default');
            $filterInactiveLinks = $app->param('inactive:int', 0) ? false : true;

            $menus = $app->module('pages')->menus([
                'filter'=> ['name' => $params['name']],
                'limit' => 1
            ], ['resolveLinks' => true, 'filterInactiveLinks' => $filterInactiveLinks, 'locale' => $locale]);

            return $menus[0] ?? false;
        }
    ]);

    /**
     * @OA\Get(
     *     path="/pages/pages",
     *     tags={"pages"},
     *    @OA\Parameter(
     *         description="Return pages for specified locale",
     *         in="query",
     *         name="locale",
     *         required=false,
     *         @OA\Schema(type="string")
     *     ),
     *     @OA\Parameter(
     *         description="Url encoded filter json",
     *         in="query",
     *         name="filter",
     *         required=false,
     *         @OA\Schema(type="json")
     *     ),
     *     @OA\Parameter(
     *         description="Url encoded sort json",
     *         in="query",
     *         name="sort",
     *         required=false,
     *         @OA\Schema(type="json")
     *     ),
     *     @OA\Parameter(
     *         description="Url encoded fields projection as json",
     *         in="query",
     *         name="fields",
     *         required=false,
     *         @OA\Schema(type="json")
     *     ),
     *     @OA\Parameter(
     *         description="Max amount of items to return",
     *         in="query",
     *         name="limit",
     *         required=false,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Parameter(
     *         description="Amount of items to skip",
     *         in="query",
     *         name="skip",
     *         required=false,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(response="200", description="List of all published pages", @OA\JsonContent(type="array", @OA\Items(type="object", additionalProperties=true)))
     * )
    */

    $restApi->addEndPoint('/pages/pages', [
        'GET' => function($params, $app) {

            if (!$app->helper('acl')->isAllowed('pages/api/read', $app->helper('auth')->getUser('role'))) {
                $app->response->status = 403;
                return ['error' => 'Permission denied'];
            }

            $options = [];

            $locale = $app->param('locale:string', 'default');
            $limit = $app->param('limit:int', null);
            $skip = $app->param('skip:int', null);
            $filter = $app->param('filter:string', null);
            $sort = $app->param('sort:string', null);
            $fields = $app->param('fields:string', null);

            if (!is_null($filter)) $options['filter'] = $filter;
            if (!is_null($sort)) $options['sort'] = $sort;
            if (!is_null($fields)) $options['fields'] = $fields;
            if (!is_null($limit)) $options['limit'] = $limit;
            if (!is_null($skip)) $options['skip'] = $skip;

            foreach (['filter', 'fields', 'sort'] as $prop) {
                if (isset($options[$prop])) {
                    try {
                        $options[$prop] = json5_decode($options[$prop], true);
                    } catch(\Throwable $e) {
                        $app->response->status = 400;
                        return ['error' => "<{$prop}> is not valid json"];
                    }
                }
            }

            if (!isset($options['sort']) || !is_array($options['sort'])) {
                $options['sort'] = ['_o' => 1];
            }

            if (!isset($options['filter']) || !is_array($options['filter'])) {
                $options['filter'] = [];
            }

            $options['filter']['_state'] = 1;

            $pages = $app->dataStorage->find('pages', $options)->toArray();

            return $app->helper('locales')->applyLocales($pages, $locale);
        }
    ]);

    /**
     * @OA\Get(
     *     path="/pages/page/{id}",
     *     tags={"pages"},
     *     @OA\Parameter(
     *         description="Page ID",
     *         in="path",
     *         name="id",
     *         required=true,
     *         @OA\Schema(type="string")
     *     ),
     *     @OA\Parameter(
     *         description="Return pages for specified locale",
     *         in="query",
     *         name="locale",
     *         required=false,
     *         @OA\Schema(type="string")
     *     ),
     *     @OA\Parameter(
     *         description="Populate items with linked content items.",
     *         in="query",
     *         name="populate",
     *         required=false,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(response="200", description="Page object", @OA\JsonContent()),
     *     @OA\Response(response="404", description="Page not found")
     * )
    */

    $restApi->addEndPoint('/pages/page/{id}', [
        'GET' => function($params, $app) {

            if (!$app->helper('acl')->isAllowed('pages/api/read', $app->helper('auth')->getUser('role'))) {
                $app->response->status = 403;
                return ['error' => 'Permission denied'];
            }

            $options = $app->request->request;
            $page = $app->dataStorage->findOne('pages', ['_id' => $params['id'], '_state' => 1]);

            if (!$page) {
                $app->response->status = 404;
                return ["error" => "Page not found!"];
            }

            $page = $app->helper('pages')->processPage($page, $options);

            if ($page) {
                $app->trigger('pages.api.page', [&$page]);
            }

            return $page;
        }
    ]);

    /**
     * @OA\Get(
     *     path="/pages/page",
     *     tags={"pages"},
     *     @OA\Parameter(
     *         description="Page route",
     *         in="query",
     *         name="route",
     *         required=true,
     *         @OA\Schema(type="string")
     *     ),
     *     @OA\Parameter(
     *         description="Return pages for specified locale",
     *         in="query",
     *         name="locale",
     *         required=false,
     *         @OA\Schema(type="string")
     *     ),
     *     @OA\Parameter(
     *         description="Populate items with linked content items.",
     *         in="query",
     *         name="populate",
     *         required=false,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(response="200", description="Page object", @OA\JsonContent()),
     *     @OA\Response(response="404", description="Page not found")
     * )
    */

    $restApi->addEndPoint('/pages/page', [

        '*' => function($params, $app) {

            if (!$app->helper('acl')->isAllowed('pages/api/read', $app->helper('auth')->getUser('role'))) {
                $app->response->status = 403;
                return ['error' => 'Permission denied'];
            }

            $route = $app->param('route');

            if (!$route) {
                $app->response->status = 404;
                return ["error" => "Parameter <route> is missing"];
            }

            $options = $app->request->request;
            $page = $app->module('pages')->pageByRoute($route, $options);

            if (!$page || $page['_state'] != 1) {
                $app->response->status = 404;
                return ["error" => "Page not found!"];
            }

            if ($page) {
                $app->trigger('pages.api.page', [&$page]);
            }

            return $page;
        }
    ]);

    /**
     * @OA\Get(
     *     path="/pages/routes",
     *     tags={"pages"},
     *     @OA\Parameter(
     *         description="Return pages for specified locale",
     *         in="query",
     *         name="locale",
     *         required=false,
     *         @OA\Schema(type="string")
     *     ),
     *     @OA\Parameter(
     *         description="Comma separated list of page types",
     *         in="query",
     *         name="type",
     *         required=false,
     *         @OA\Schema(type="string")
     *     ),
     *     @OA\Response(response="200", description="Page object", @OA\JsonContent())
     * )
    */
    $restApi->addEndPoint('/pages/routes', [
        'GET' => function($params, $app) {

            if (!$app->helper('acl')->isAllowed('pages/api/read', $app->helper('auth')->getUser('role'))) {
                $app->response->status = 403;
                return ['error' => 'Permission denied'];
            }

            $filter = [];
            $locale = $app->param('locale:string', null);
            $type = $app->param('type');

            if (is_string($type)) {
                $filter['type'] = ['$in' => array_map('trim', explode(',', $type))];
            }

            return $app->module('pages')->routes($locale, $filter);
        }
    ]);

    /**
     * @OA\Get(
     *     path="/pages/sitemap",
     *     tags={"pages"},
     *     @OA\Parameter(
     *         description="Level of site tree depth",
     *         in="query",
     *         name="deep",
     *         required=false,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Parameter(
     *         description="Include pages with noindex set",
     *         in="query",
     *         name="inclNoIndex",
     *         required=false,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(response="200", description="List of routes", @OA\JsonContent(type="array", @OA\Items(type="object", additionalProperties=true)))
     * )
    */
    $restApi->addEndPoint('/pages/sitemap', [
        'GET' => function($params, $app) {

            if (!$app->helper('acl')->isAllowed('pages/api/read', $app->helper('auth')->getUser('role'))) {
                $app->response->status = 403;
                return ['error' => 'Permission denied'];
            }

            $deep = $app->param('deep:int', 0);
            $inclNoIndex = $app->param('inclNoIndex:int', 0);

            return $app->module('pages')->sitemap($deep ? true : false, $inclNoIndex ? true : false);
        }
    ]);

});


$this->on('graphql.config', function($gql) {
    $app = $this;
    include(__DIR__.'/graphql/pagesSettings.php');
    include(__DIR__.'/graphql/menu.php');
    include(__DIR__.'/graphql/menus.php');
    include(__DIR__.'/graphql/page.php');
    include(__DIR__.'/graphql/pages.php');
});
