<?php
/*
 * Copyright (c) 2013, 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
 */

abstract class _WV_Filter_Multi implements WV_IFilter, WV_Filter_Interface_ChangeTable {
	protected $filters;
	protected $conjunction;
	protected $separate;

	public function __construct($filters, $conjunction, $separate = false) {
		$this->filters     = array();
		$this->conjunction = $conjunction;
		$this->separate    = $separate;

		foreach ($filters as $filter) {
			if ($filter instanceof WV_IFilter) {
				$this->filters[] = $filter;
			}
		}
	}

	public function useSeparateJoins($flag = true) {
		$this->separate = (boolean) $separate;
	}

	public function __toString() {
		return $this->toSQL();
	}

	abstract public function optimize(array $filters);

	public function toSQL() {
		$strings = array();

		foreach ($this->filters as $filter) {
			if ($filter->isValid()) {
				$strings[] = $filter->toSQL();
			}
		}

		if (empty($strings)) {
			throw new WV_Exception_Filter(t('devutils_filters_multi_error'));
		}

		$strings = $this->optimize($strings);

		if (empty($strings)) {
			return '1';
		}

		return count($strings) === 1 ? $strings[0] : '('.implode(' '.$this->conjunction.' ', $strings).')';
	}

	public function isValid() {
		foreach ($this->filters as $filter) {
			if ($filter->isValid()) return true;
		}

		return false;
	}

	public function getRequiredTables() {
		$tables = array();

		foreach ($this->filters as $filter) {
			if ($filter->isValid()) {
				$tables = array_merge($tables, $filter->getRequiredTables());
			}
		}

		return $tables;
	}

	public function getExtraColumns($tables) {
		$columns = array();

		foreach ($this->filters as $filter) {
			if (!in_array('getExtraColumns', get_class_methods($filter))) continue;
			$columns = array_unique(array_merge($columns, $filter->getExtraColumns($tables)));
		}

		return $columns;
	}

	public function getExtraTables($tables) {
		$orig = $tables;

		foreach ($this->filters as $filter) {
			if (!in_array('getExtraTables', get_class_methods($filter))) continue;

			$new    = $filter->getExtraTables($tables);
			$tables = array_unique(array_merge($tables, $new));
		}

		return array_values(array_diff($tables, $orig));
	}

	public function add(WV_IFilter $filter) {
		$this->filters[] = $filter;
	}

	protected function prefix() {
		return sly_Core::getTablePrefix();
	}

	public function changeTable($oldTable, $newTable) {
		foreach ($this->filters as $filter) {
			if (!$filter instanceof WV_Filter_Interface_ChangeTable)
				throw new sly_Exception('all filters must implement WV_Filter_Interface_ChangeTable when using changeTable');

			$filter->changeTable($oldTable, $newTable);
		}
	}

}
