<?php
/*
 * Copyright (c) 2012, webvariants GbR, http://www.webvariants.de
 *
 * This file is released under the terms of the MIT license. You can find the
 * complete text in the attached LICENSE file or online at:
 *
 * http://www.opensource.org/licenses/mit-license.php
 */

/**
 * @since  v4.0
 * @author Christoph
 */
class _WV24_RuntimeCache {
	protected $articleData = array();
	protected $settings    = array();
	protected $urls        = array();

	public function prewarmAll($clang = null) {
		$this->prewarmArticleData($clang);
		$this->prewarmSettings($clang);
	}

	public function prewarmForArticle($id, $clang, $path = null) {
		$this->prewarmSettings($clang);
		$this->prewarmForSiteStartArticle($clang);
		$this->prewarmForArticlePath($clang, $path, $id);
	}

	public function prewarmForArticlePath($clang, $path, $articleID = null) {
		$path = WV24_Util::decodePath($path);

		if ($articleID !== null) {
			$path[] = $articleID;
		}

		if (!empty($path)) {
			$this->prewarmArticleData($clang, $path);
		}
	}

	public function prewarmForSiteStartArticle($clang) {
		$articles = array(sly_Core::getSiteStartArticleId());
		$this->prewarmArticleData($clang, $articles);
	}

	public function prewarmArticleData($clang, array $articles = null) {
		$db     = sly_DB_Persistence::getInstance();
		$prefix = sly_Core::getTablePrefix();
		$where  = $clang === null ? array() : array('a.clang' => $clang);
		$select = 'a.id, a.clang, a.wv24_fragment, a.wv24_skip, a.re_id, a.startpage, a.name, a.catname, a.path, u.url';
		$joins  = 'LEFT JOIN '.$prefix.'wv24_urls u ON a.id = u.article_id AND a.clang = u.clang AND u.namespace = '.$db->quote(WV24_RealURL2::URL_NAMESPACE);

		if ($articles !== null) {
			$where['a.id'] = $articles;
		}

		$db->select('article a', $select, $where, null, null, null, null, null, $joins);

		foreach ($db->all() as $row) {
			$clang = (int) $row['clang'];
			$id    = (int) $row['id'];
			$isCat = (boolean) $row['startpage'];
			$path  = WV24_Util::decodePath($row['path']);

			$this->articleData[$clang][$id] = array(
				'id'       => (int) $row['id'],
				'clang'    => (int) $row['clang'],
				'name'     => $row[$isCat ? 'catname' : 'name'],
				're_id'    => (int) $row['re_id'],
				'is_cat'   => $isCat,
				'path'     => $path,
				'fragment' => $row['wv24_fragment'],
				'skipped'  => (boolean) $row['wv24_skip'],
				'url'      => $row['url']
			);
		}
	}

	public function prewarmSettings($clang) {
		if ($clang === null) {
			$data = WV8_Settings::getValues('realurl2', WV_Sally::CLANG_ALL);

			foreach ($data as $name => $settings) {
				foreach ($settings as $clang => $value) {
					$this->settings[$clang][$name] = $value;
				}
			}
		}
		else {
			$clang = (int) $clang;
			$data  = WV8_Settings::getValues('realurl2', $clang);

			foreach ($data as $name => $value) {
				$this->settings[$clang][$name] = $value;
			}
		}
	}

	public function getSetting($key, $clang) {
		if (!isset($this->settings[$clang])) {
			$this->prewarmSettings($clang);
		}

		$settings = $this->settings[$clang];

		// be careful with NULL values
		if (!array_key_exists($key, $settings)) {
			throw new Exception('Unknown setting name "'.$key.'" given.');
		}

		return $settings[$key];
	}

	public function getDefaultFragment($clang) {
		return $this->getSetting('default_fragment', $clang);
	}

	public function getArticleData($articleID, $clang, $key = null) {
		if (!isset($this->articleData[$clang])) {
			$this->prewarmArticleData($clang);
		}

		if (!isset($this->articleData[$clang][$articleID])) {
			throw new Exception('Unknown article '.$articleID.'/'.$clang.' given.');
		}

		$data = $this->articleData[$clang][$articleID];

		if ($key !== null) {
			if (!array_key_exists($key, $data)) {
				throw new Exception('Invalid key "'.$key.'" given.');
			}

			return $data[$key];
		}

		return $data;
	}

	public function getArticleFragment($articleID, $clang) {
		return $this->getArticleData($articleID, $clang, 'fragment');
	}

	public function isArticleSkipped($articleID, $clang) {
		return $this->getArticleData($articleID, $clang, 'skipped');
	}

	public function addUrl($articleID, $clang, $url) {
		if (!isset($this->articleData[$clang])) {
			$this->prewarmArticleData($clang);
		}

		if (!isset($this->articleData[$clang][$articleID])) {
			throw new Exception('Unknown article '.$articleID.'/'.$clang.' given.');
		}

		$this->articleData[$clang][$articleID]['url'] = $url;
	}

	public function hasUrl($articleID, $clang) {
		if (!isset($this->articleData[$clang])) {
			$this->prewarmArticleData($clang);
		}

		return isset($this->articleData[$clang][$articleID]['url']);
	}

	public function getUrl($articleID, $clang) {
		return $this->getArticleData($articleID, $clang, 'url');
	}

	public function forgetUrl($articleID, $clang) {
		if (isset($this->articleData[$clang][$articleID])) {
			$this->articleData[$clang][$articleID]['url'] = null;
		}
	}

	public function getPathInfo(array $path, $clang) {
		$result = array();

		foreach ($path as $articleID) {
			$result[$articleID] = $this->getArticleData($articleID, $clang);
		}

		return $result;
	}
}
