<?php namespace App\Libs\Support;

use App\Libs\Facades\ContentTypes;
use App\Libs\Facades\Localization;
use Entry;
use Website;
use Illuminate\Support\Facades\Storage;

/**
 * Transforms values based on array on transformation rules
 */

class SitemapGenerator
{
    private $website;
    private $languages;
    private $defaultLanguage;
    private $currentLanguage;

    private function _generateSitemapUrl($object, $parentSlug = false, $prio = "0.8")
    {
        $sitemapUrl = array();
        $wo = $object->websites->findByWebsite($this->website->id);
        $woLang = $wo->languages->findByLocale($this->currentLanguage);

        if ($woLang->lang_status != 'published') {
            return false;
        }

        $langPrefix = ($this->currentLanguage != $this->defaultLanguage ? $this->currentLanguage : "");

        $sitemapUrl['language'] = $this->currentLanguage;
        $sitemapUrl['loc'] = url($langPrefix.($parentSlug ? $parentSlug.'/'.$woLang->lang_slug : $woLang->lang_uri));
        $sitemapUrl['lastmod'] = date("Y-m-d", strtotime($object->updated_at));
        $sitemapUrl['priority'] = $prio;
        return $sitemapUrl;
    }

    public function buildSitemap()
    {
        $website = Localization::getWebsite();
        $this->website = $website;
        $languages = $website->languages()->where('is_active', 1)->get();

        $this->languages = $languages;
        $this->defaultLanguage = Localization::getDefaultLocale();
        $pages = Entry::full()
            ->where('status', 'published')
            ->where('no_sitemap', 0)
            ->orderBy('position', 'asc')
            ->get();

        $langsUrls = array();
        foreach ($languages as $language) {
            $this->currentLanguage = $language->id;
            $langsUrls[$this->currentLanguage] = array();
            foreach ($pages as $page) {
                $pageIndex = 'page_' . $page->id;
                $templateId = $page->template;
                $template = config('backoffice.generic.page.templates.'.$website->id.'.'.$templateId);

                if ($page->uri == '/') {
                    $pagePrio = 1;
                } else {
                    $pagePrio = 1 - (sizeof(explode('/', $page->uri)) - 1) / 10;
                }

                if (isset($template['view']) && $template['view']) {
                    $langUrl = $this->_generateSitemapUrl($page, null, $pagePrio);
                    if (!$langUrl) {
                        continue;
                    }
                    $langsUrls[$this->currentLanguage][$pageIndex] = $langUrl;
                }

                $templateCfg = false;
                if (isset($template['contentType'])) {
                    $templateCfgContentType = ContentTypes::find($template['contentType']);
                    $modelClass = $templateCfgContentType->getModelType();
                    $templateCfg = $modelClass::full()
                        ->where('entry_id', $page->id)
                        ->first();
                }

                if (isset($template['detailContentType']) && $template['detailContentType']) {
                    $detailType = $template['detailContentType'];
                    $contentType = ContentTypes::find($detailType);
                    $modelClass = $contentType->getModelType();
                    $q = $modelClass::full()
                        ->where('status', 'published')
                        ->orderBy('position', 'asc');

                    $filterField = false;
                    if ($contentType->getTypeFilterField()) {
                        $filterField = $contentType->getTypeFilterField();
                    }

                    if (isset($template['detailTypeFilter']) && $template['detailTypeFilter']) {
                        $q->whereIn('type', $template['detailTypeFilter']);
                    }


                    $pageWo = $page->websites->findByWebsite($this->website->id);
                    $pageWoLang = $pageWo->languages->findByLocale($this->currentLanguage);

                    $objects = $q->get();

                    $prio = isset($template['sitemapPrio']) ? $template['sitemapPrio'] : '0.6';
                    foreach ($objects as $object) {
                        $objectIndex = $object->object_type . '_' . $object->id;
                        $parentUri = $pageWoLang->lang_uri;

                        if (isset($template['typeFilterField']) && $templateCfg) {
                            if ($templateCfg->$template['typeFilterField'] !== $object->$filterField) {
                                continue;
                            }
                        }

                        if ($filterField) {
                            $baseUris = $contentType->getBaseUri($website->id);
                            $parentUri = $baseUris[$object->$filterField];
                        }

                        /** Ulgy exception to prevent non hero projects from being indexed */
                        if ($object->content_type === 'project' && !$object->is_hero) {
                            continue;
                        }
                        /** Ulgy exception to prevent non listed publications from being indexed */
                        if ($object->content_type === 'publication' && !$object->list_on_publications) {
                            continue;
                        }
                        $objectLangUrl = $this->_generateSitemapUrl($object, $parentUri, $prio);
                        if (!$objectLangUrl) {
                            continue;
                        }
                        // don't include if page has canonical url set
                        if (!empty($object->canonical_url)) {
                            continue;
                        }
                        $langsUrls[$this->currentLanguage][$objectIndex] = $objectLangUrl;

                    }
                }
            }
        }

        /* Build XML */

        $out = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
        $out .= "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">\n";
        foreach ($langsUrls as $lang => $langUrls) {
            foreach ($langUrls as $i => $url) {
                $out .= "\t<url>\n";
                $out .= "\t\t<loc>".$url['loc']."</loc>\n";
                if ($languages->count() > 1) {
                    foreach ($languages as $language) {
                        if (empty($langsUrls[$language->id][$i]['loc'])) {
                            continue;
                        }
                        $out .= "\t\t<xhtml:link rel=\"alternate\" hreflang=\"{$language->id}\" href=\""
                            .$langsUrls[$language->id][$i]['loc']."\" />\n";
                    }
                }
                $out .= "\t\t<lastmod>".$url['lastmod']."</lastmod>\n";
                $out .= "\t\t<changefreq>weekly</changefreq>\n";
                $out .= "\t\t<priority>".$url['priority']."</priority>\n";
                $out .= "\t</url>\n";
            }
        }

        $out .= "</urlset>";
        Storage::put('sitemap_'.$website->id.'.xml', $out);
    }

    public function exportPublishedContents()
    {
        $website = Website::find(1);
        $this->website = $website;
        $languages = $website->languages()->where('is_active', 1)->get();

        $this->languages = $languages;
        $this->defaultLanguage = Localization::getDefaultLocale();
        $pages = Entry::full()
            ->where('status', 'published')
            ->orderBy('position', 'asc')
            ->get();

        $contents = array();

        foreach ($pages as $page) {
            $templateId = $page->template;
            $template = config('backoffice.generic.page.templates.'.$website->id.'.'.$templateId);
            $basePagePublished = [];

            if (isset($template['view']) && $template['view']) {
                foreach ($languages as $language) {
                    $this->currentLanguage = $language->id;
                    $sitemapUrl = $this->_generateSitemapUrl($page, null, 0);
                    if (!$sitemapUrl) {
                        continue;
                    }
                    $basePagePublished[$language->id] = true;
                    $pageLang = $page->languages->findByLocale($this->currentLanguage);
                    $contents[] = [
                        'object_id' => $page->website_object_id,
                        'url' => $sitemapUrl['loc'],
                        'lang' => $this->currentLanguage,
                        'title' => $pageLang->title,
                        'template' => $templateId
                    ];
                }
            }

            $templateCfg = false;
            if (isset($template['contentType'])) {
                $templateCfgContentType = ContentTypes::find($template['contentType']);
                $modelClass = $templateCfgContentType->getModelType();
                $templateCfg = $modelClass::full()
                    ->where('entry_id', $page->id)
                    ->first();
            }

            if (isset($template['detailContentType']) && $template['detailContentType']) {
                $detailType = $template['detailContentType'];
                $contentType = ContentTypes::find($detailType);
                $modelClass = $contentType->getModelType();
                $q = $modelClass::full()
                    ->where('status', 'published')
                    ->orderBy('position', 'asc');

                $filterField = false;
                if ($contentType->getTypeFilterField()) {
                    $filterField = $contentType->getTypeFilterField();
                }

                if (isset($template['detailTypeFilter']) && $template['detailTypeFilter']) {
                    $q->whereIn('type', $template['detailTypeFilter']);
                }

                $pageWo = $page->websites->findByWebsite($this->website->id);

                $objects = $q->get();

                foreach ($objects as $object) {
                    foreach ($languages as $language) {
                        if (empty($basePagePublished[$language->id])) {
                            continue;
                        }
                        $this->currentLanguage = $language->id;
                        $pageWoLang = $pageWo->languages->findByLocale($this->currentLanguage);
                        $parentUri = $pageWoLang->lang_uri;

                        if (isset($template['typeFilterField']) && $templateCfg) {
                            if ($templateCfg->$template['typeFilterField'] !== $object->$filterField) {
                                continue;
                            }
                        }

                        if ($filterField) {
                            $baseUris = $contentType->getBaseUri($website->id);
                            $parentUri = $baseUris[$object->$filterField];
                        }


                        $sitemapUrl = $this->_generateSitemapUrl($object, $parentUri, 0);
                        if (!$sitemapUrl) {
                            continue;
                        }
                        $contents[] = [
                            'object_id' => $object->website_object_id,
                            'url' => $sitemapUrl['loc'],
                            'lang' => $this->currentLanguage,
                            'title' => $object->title,
                            'template' => $templateId
                        ];
                    }
                }
            }
        }

        /* Build csv */

        $out = "Object ID,Lang,Template,Title,URL\n";
        foreach ($contents as $content) {
            $out .= $content['object_id'] . ',' . $content['lang'] . ',' . $content['template'] . ',"' . str_replace('"', '""', $content['title']) . '",' . $content['url'] . "\n";
        }

        Storage::put('sitecontent'.$website->id.'.csv', $out);
    }
}
