<?php

namespace App\Service;

use App\Tool\Utils;
use Pimcore\Model\Document;
use Pimcore\Model\DataObject\ClassDefinition;
use Pimcore\Model\Site;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

class FeedManager
{
	/**
	 * @var Request
	 */
	protected $request;

	/**
	 * @var string
	 */
	protected $language;

	/**
	 * @param RequestStack $requestStack
	 */
	public function __construct(RequestStack $requestStack)
	{
		$this->request = $requestStack->getCurrentRequest();

		$this->language = substr($this->request->getLocale(), 0, 2);
		if (!$this->language) {
			$this->language = Utils::getDefaultLanguage();
		}
	}

	/**
	 * @return string XML
	 */
	public function generateSitemapXml(array $languages = [])
	{
		// save different sitemap for each site
		$documentRoot = (Site::isSiteRequest()) ? Site::getCurrentSite()->getRootDocument() : Document\Page::getById(1);
		$sitemapPath = sprintf(
			PIMCORE_PRIVATE_VAR.'/tmp/sitemap%s.xml',
			($documentRoot instanceof Document) ? sprintf('-%d', $documentRoot->getId()) : ''
		);
		// invalidate sitemap file each day
		$timestamp = (file_exists($sitemapPath)) ? filemtime($sitemapPath) : 0;
		if ((time() - $timestamp) < 86400) {
			$xml = file_get_contents($sitemapPath);
		} else {
			$xml = null;
		}

		if (!$xml) {
			$schemeAndHost = $this->request->getSchemeAndHttpHost();

			$xml = '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';

			// add documents
			$validLanguages = !empty($languages) ? $languages : Utils::getValidFrontendLanguages();
			$documentList = new Document\Listing();
			$documentList->setCondition(
				'type = ? AND path like ?',
				['page', $documentRoot->getRealFullPath().'%']
			);
			$documentIdList = $documentList->loadIdList();
			foreach ($documentIdList as $documentId) {
				$document = Document\Page::getById($documentId);
				$language = $document->getProperty('language');
				if (!$document || !in_array($language, $validLanguages)
						|| $document->getProperty('sitemap_xml_exclude')) {
					continue;
				}
				$url = $document->getFullPath();
				if ('http' != substr($url, 0, 4)) {
					$url = $schemeAndHost.$url;
				}
				$xml .= sprintf(
					'<url><loc>%s</loc><lastmod>%s</lastmod><changefreq>monthly</changefreq></url>',
					htmlspecialchars($url, ENT_XML1, 'UTF-8'),
					date('Y-m-d', $document->getModificationDate())
				);
			}

			// add objects with getUrl method
			$classList = new ClassDefinition\Listing();
			$classList->load();
			foreach ($classList->getClasses() as $class) {
				$objectClass = '\\App\\Model\\'.$class->getName();
				if (!class_exists($objectClass, false)) {
					$objectClass = '\\Pimcore\\Model\\DataObject\\'.$class->getName();
				}
				$tmpObject = new $objectClass();
				if (method_exists($tmpObject, 'getUrl')) {
					$listClass = '\\App\\Model\\'.$class->getName().'\\Listing';
					if (!class_exists($listClass, false)) {
						$listClass = '\\Pimcore\\Model\\DataObject\\'.$class->getName().'\\Listing';
					}
					$list = new $listClass();
					$list->load();
					foreach ($list->getData() as $object) {
						if ($object->getProperty('sitemap_xml_exclude')) {
							continue;
						}
						foreach($validLanguages as $language) {
							$url = $object->getUrl($language);

							// Pimcore generated relative object URL
							if (0 === strpos($url, '/')) {
								$url = $schemeAndHost . $url;
							} else {
								// Skip external url
								if (0 !== strpos($url, $schemeAndHost)) {
									continue;
								}
							}

							$xml .= sprintf(
								'<url><loc>%s</loc><lastmod>%s</lastmod><changefreq>monthly</changefreq></url>',
								htmlspecialchars($url, ENT_XML1, 'UTF-8'),
								date('Y-m-d', $object->getModificationDate())
							);
						}
					}
				}
			}

			$xml .= sprintf('</urlset>');

			$handle = fopen($sitemapPath, 'w');
			fwrite($handle, $xml);
			fclose($handle);
		}

		return $xml;
	}
}
