<?php

// Register Helpers
$this->helpers['pages'] = 'Pages\\Helper\\Pages';

include(__DIR__.'/events.php');

// load admin related code
$this->on('app.admin.init', function() {
    include(__DIR__.'/admin.php');
});

// load api request related code
$this->on('app.api.request', function() {
    include(__DIR__.'/api.php');
});


// pages api
$this->module('pages')->extend([

    '_settings' => null,

    'pageTypes' => function(?string $type = null) {

        static $types;

        if (!$types) {

            $types = new ArrayObject([
                'layout' => include(__DIR__.'/PageTypes/layout/config.php'),
            ]);

            if ($this->app->module('content')) {
                $types['collection'] = include(__DIR__.'/PageTypes/collection/config.php');
                $types['singleton'] = include(__DIR__.'/PageTypes/singleton/config.php');
            }

            $this->app->trigger('pages.pagetype', [$types]);
        }

        return $type ? ($types[$type] ?? null) : $types;
    },

    'menus' => function(array $options = [], $process = []) {

        $options = array_merge([
            'sort' => ['name' => 1],
            'fields' => ['data' => 0, '_meta' => 0]
        ], $options);

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

        if (count($menus)) {

            // filter out inactive menu items
            if ($process['filterInactiveLinks'] ?? false) {

                foreach ($menus as &$menu) {
                    $menu['links'] = $this->app->helper('pages')->filterInactiveMenuLinks($menu['links']);
                }
            }

            // resolve pages://...
            if ($process['resolveLinks'] ?? false) {

                foreach ($menus as &$menu) {
                    $menu = $this->app->helper('pages')->resolveNestedPageUrls($menu);
                }
            }

            if ($process['locale'] ?? false) {
                $menus = $this->app->helper('locales')->applyLocales($menus, $process['locale']);
            }
        }

        return $menus;
    },

    'settings' => function(bool $cached = true) {

        if ($cached && isset($this->props['_settings'])) {
            return $this->props['_settings'];
        }

        $settings = [
            'revisions' => false,
            'meta' => [],
            'preview' => [],
            'images' => [
                'logo' => null,
                'small' => null,
                'favicon' => null,
            ],
            'scripts' => [
                'header' => null,
                'footer' => null,
            ],
            'seo' => [
                'title' => null,
                'keywords' => null,
                'description' => null,
                'noindex' => false,
                'nofollow' => false,
            ],
            'locales' => [],
            'globalDataFields' => [],
        ];

        $locales = $this->app->helper('locales')->locales();
        $opts = $this->app->dataStorage->getKey('pages/options', 'settings', []);
        $settings = array_replace_recursive($settings, $opts);

        if (isset($settings['meta']) && is_array($settings['meta'])) {
            $settings['meta'] = new ArrayObject($settings['meta']);
        }

        $localesSettings = [];

        foreach ($locales as $locale) {

            if ($locale['i18n'] === 'default') continue;

            if (!isset($settings['seo_'.$locale['i18n']])) {
                $settings['seo_'.$locale['i18n']] = $settings['seo'];
            }

            $localesSettings[$locale['i18n']] = $settings['locales'][$locale['i18n']] ?? true;
        }

        $settings['locales'] = $localesSettings;

        $this->props['_settings'] = $settings;

        return $settings;

    },

    'pageByRoute' => function(string $route, array $options = []) {

        // is route directly related to a page
        $filter = [
            '_state' => 1
        ];

        $locale = $options['locale'] ?? 'default';
        $settings = $this->settings();
        $locales = $this->app->helper('locales')->locales(true);
        $routeKey = '_r';

        if ($locale && $locale != 'default') {

            // is locale disabled globally?
            if (isset($settings['locales'][$locale]) && $settings['locales'][$locale] === false) {
                return null;
            }

            if (isset($locales[$locale])) {
                $routeKey = "_r_{$locale}";
            } else {
                $locale = 'default';
            }
        }

        $filter[$routeKey] = $route;

        if ($route == '/') {
            $filter = ['_pid' => null, '_state' => 1, '_o' => 0];
        }

        $page = $this->app->dataStorage->findOne('pages', $filter);

        if (!$page) {
            $this->app->trigger('pages.resolve.path', [$route, &$page, $locale, $options]);
        }

        // is route handled by page type?
        if (!$page && $route != '/') {
            $page = $this->app->helper('pages')->resolveRouteByPageType($route, $locale, $options);
        }

        // is locale disabled for this page?
        if ($locale && $locale != 'default' && isset($page['_locales'][$locale]) && $page['_locales'][$locale] === false) {
            return null;
        }

        if ($page) {

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

            if ($route === '/' && isset($page['_routes'])) {

                foreach ($page['_routes'] as $l => $r) {
                    $page['_routes'][$l] = '/';
                }
            }
        }

        return $page ? $page : null;
    },

    // deprecated in favor for sitemap
    'routes' => function(?string $locale = null, array $filter = []) {

        $settings = $this->settings();
        $routes = [];

        $filter = array_merge($filter, ['_state' => 1]);

        $pages = $this->app->dataStorage->find('pages', [
            'filter' => $filter,
            'sort' => ['_o' => 1]
        ])->toArray();

        $locales = array_keys($this->app->helper('locales')->locales(true));

        foreach ($locales as $l) {
            $routes[$l] = [];
        }

        if (!count($pages)) {
            return $routes;
        }

        $startPage = $this->app->dataStorage->findOne('pages', ['_pid' => null, '_state' => 1, '_o' => 0], ['_id' => 1]);

        foreach ($pages as $idx => $page) {

            foreach ($locales as $l) {

                if ($l !== 'default' && (
                    (isset($settings['locales'][$l]) && $settings['locales'][$l] === false) || // is locale disabled globally?
                    (isset($page['_locales'][$l]) && $page['_locales'][$l] === false) // is locale disabled for this page?
                )) {
                    continue;
                }

                // check if noindex is set for this locale
                $seoKey = $l == 'default' ? 'seo' : "seo_{$l}";
                if (isset($page[$seoKey]['noindex']) && $page[$seoKey]['noindex'] === true) {
                    continue;
                }

                $routeKey = $l == 'default' ? '_r' : "_r_{$l}";
                $slugKey = $l == 'default' ? 'slug' : "slug_{$l}";

                if (!isset($page[$routeKey]) || !$page[$routeKey]) continue;

                $route = isset($startPage) && $startPage['_id'] == $page['_id'] ? '/' : ($page[$routeKey] ?? null);
                $slug  = isset($page[$slugKey]) && $page[$slugKey] ? $page[$slugKey] : $page['slug'];

                $routes[$l][] = [
                    'route' => $route,
                    'slug' => $slug,
                    'type' => $page['type'],
                    'lastmod' => date('c', $page['_modified'])
                ];
            }
        }

        return $locale && isset($routes[$locale]) ? $routes[$locale] : $routes;
    },

    'sitemap' => function(bool $deep = false, bool $inclNoIndex = false ) {

        $settings = $this->settings();
        $urls = [];

        $pages = $this->app->dataStorage->find('pages', [
            'filter' => ['_state' => 1],
            'fields' => ['data' => 0]
        ])->toArray();

        if (!count($pages)) {
            return $urls;
        }

        $locales = $this->app->helper('locales')->locales(true);
        $startPage = $this->app->dataStorage->findOne('pages', ['_pid' => null, '_state' => 1, '_o' => 0], ['_id' => 1]);

        foreach ($pages as $page) {

            // alternative locale routes
            $routes = [];
            $noindex = [];
            $nofollow = [];

            foreach ($locales as $l => $meta) {


                if ($l !== 'default' && (
                    (isset($settings['locales'][$l]) && $settings['locales'][$l] === false) || // is locale disabled globally?
                    (isset($page['_locales'][$l]) && $page['_locales'][$l] === false) // is locale disabled for this page?
                )) {
                    continue;
                }

                // check if noindex/nofollow is set for this locale
                $seoKey = $l == 'default' ? 'seo' : "seo_{$l}";
                $isNoIndex = isset($page[$seoKey]['noindex']) && $page[$seoKey]['noindex'] === true;
                $isNoFollow = isset($page[$seoKey]['nofollow']) && $page[$seoKey]['nofollow'] === true;

                if ($isNoIndex) $noindex[] = $l;
                if ($isNoFollow) $nofollow[] = $l;

                if ($isNoIndex && !$inclNoIndex) {
                    continue;
                }

                $rKey = $l == 'default' ? '_r' : "_r_{$l}";
                if (!isset($page[$rKey]) || !$page[$rKey]) continue;
                $routes[$l] = $page[$rKey];
            }

            if (!count($routes)) continue;

            if (isset($startPage) && $page['_id'] == $startPage['_id']) {
                foreach ($routes as $l => $r) {
                    $routes[$l] = '/';
                }
            }

            $urls[] = [
                'routes' => $routes,
                'type' => $page['type'],
                'lastmod' => date('c', $page['_modified']),
                'noindex' => $noindex,
                'nofollow' => $nofollow
            ];

            if (!$deep) continue;

            $params = [];

            if ($page['type'] == 'collection') {
                $params['limit'] = 100;
            }

            $page = $this->pageByRoute($page['_id'] == $startPage['_id'] ? '/' : $page['_r'], $params);

            if (isset($page['data']['items']) && is_array($page['data']['items'])) {

                foreach ($page['data']['items'] as $item) {

                    if (!isset($item['route'])) continue;

                    $item = $this->pageByRoute($item['route']);

                    if (!$item) continue;

                    // build noindex/nofollow arrays and filter routes per locale
                    $itemRoutes = [];
                    $itemNoindex = [];
                    $itemNofollow = [];
                    foreach ($item['_routes'] ?? [] as $l => $route) {
                        $seoKey = $l == 'default' ? 'seo' : "seo_{$l}";
                        $isNoIndex = isset($item[$seoKey]['noindex']) && $item[$seoKey]['noindex'] === true;
                        $isNoFollow = isset($item[$seoKey]['nofollow']) && $item[$seoKey]['nofollow'] === true;

                        if ($isNoIndex) $itemNoindex[] = $l;
                        if ($isNoFollow) $itemNofollow[] = $l;

                        if ($isNoIndex && !$inclNoIndex) {
                            continue;
                        }

                        $itemRoutes[$l] = $route;
                    }

                    if (!count($itemRoutes)) continue;

                    $urls[] = [
                        'routes' => $itemRoutes,
                        'type' => $item['type'] ?? "{$page['type']}-item",
                        'lastmod' => date('c', $item['_modified'] ?? $page['_modified']),
                        'noindex' => $itemNoindex,
                        'nofollow' => $itemNofollow
                    ];
                }
            }
        }

        return $urls;
    },

    'updateRefs' => function(string $refId, mixed $value = null) {

        $update = function(&$items) use($value, $refId, &$update) {

            if (!is_array($items)) return $items;

            foreach ($items as $k => &$v) {
                if (!is_array($v)) continue;
                if (is_array($items[$k])) $items[$k] = $update($items[$k]);
                if (isset($v['_id']) && $v['_id'] == $refId) {

                    $data = ($value && isset($v['_data'])) ? $v['_data'] : null;
                    $items[$k] = $value;

                    if ($data) {
                        $items[$k]['_data'] = $data;
                    }
                }
            }
            return $items;
        };

        // update options
        $items = $this->app->dataStorage->findTerm('pages/options', $refId)->toArray();
        $items = count($items) ? $update($items) : [];

        foreach ($items as $item) $this->app->dataStorage->save('pages/options', $item);

        // update pages
        $items = $this->app->dataStorage->findTerm('pages', $refId)->toArray();
        $items = count($items) ? $update($items) : [];

        foreach ($items as $item) $this->app->dataStorage->save('pages', $item);
    }

]);
