<?php
declare( strict_types=1 );

namespace FiboFilters\Filters;

use FiboFilters\FilterCreationException;
use FiboFilters\Filters\Types\Category;
use FiboFilters\Filters\Types\CategoryHierarchical;
use FiboFilters\Filters\Types\Checkboxes;
use FiboFilters\Filters\Types\Buttons;
use FiboFilters\Filters\Types\Filter;
use FiboFilters\Filters\Types\Radio;
use FiboFilters\Filters\Types\Range;
use FiboFilters\Filters\Types\Search;
use FiboFilters\Filters\Types\Select;
use FiboFilters\Filters\Types\Toggle;
use FiboFilters\Filters\Types\Color;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class FilterFactory
 */
class FilterFactory {
	/** @var FilterSources */
	private $filter_sources;

	/** @var StoreFilters */
	private $store_filters;

	public function __construct( FilterSources $filter_sources, StoreFilters $store_filters ) {
		$this->filter_sources = $filter_sources;
		$this->store_filters  = $store_filters;
	}

	// TODO metoda jako return powinna miec jakiś abstrakt (może interfejs?)

	/**
	 * @param string $id Filter ID.
	 * @param bool   $skip_source_obj Skip getting source object.
	 *
	 * @throws FilterCreationException
	 */
	public function create_filter_instance( string $id = '', bool $skip_source_obj = true ): Filter {
		if ( empty( $id ) ) {
			throw new FilterCreationException( 'Empty filter ID' );
		}

		$filter_type = $this->store_filters->get_filter_type( $id );
		if ( ! $filter_type ) {
			throw new FilterCreationException( 'Invalid filter type' );
		}

		// TODO Typy filtrow mozna wyciągnać do osobnej klasy tak jak tutaj: https://koddlo.pl/simple-factory-prosta-fabryka/.
		switch ( $filter_type ) {
			case 'category':
				$filter = new Category( $id );
				break;
			case 'category-hierarchical':
				$filter = new CategoryHierarchical( $id );
				break;
			case 'checkboxes':
				$filter = new Checkboxes( $id );
				break;
			case 'buttons':
				$filter = new Buttons( $id );
				break;
			case 'radio':
				$filter = new Radio( $id );
				break;
			case 'range':
				$filter = new Range( $id );
				break;
			case 'select':
				$filter = new Select( $id );
				break;
			case 'toggle':
				$filter = new Toggle( $id );
				break;
			case 'color':
				$filter = new Color( $id );
				break;
			case 'search':
				$filter = new Search( $id );
				break;
			default:
				throw new FilterCreationException( 'Invalid filter type' );
		}

		$props = $this->store_filters->get_filter_props( $id );
		if ( $props ) {
			$filter->set_props( $props );
		}

		if ( ! $skip_source_obj ) {
			$source     = $filter->get_source();
			$source_obj = $this->filter_sources->get_source( $source );
			$filter->set_source_obj( $source_obj );
		}

		return $filter;
	}

	public function get_filter_types(): array {
		$types = [
			[
				'label' => _x( 'Category links – flat', '[admin]', 'fibofilters' ),
				'value' => 'category',
			],
			[
				'label' => _x( 'Category links – tree', '[admin]', 'fibofilters' ),
				'value' => 'category-hierarchical',
			],
			[
				'label' => _x( 'Checkboxes', '[admin]', 'fibofilters' ),
				'value' => 'checkboxes',
			],
			[
				'label' => _x( 'Buttons', '[admin]', 'fibofilters' ),
				'value' => 'buttons',
			],
			[
				'label' => _x( 'Radio', '[admin]', 'fibofilters' ),
				'value' => 'radio',
			],
			[
				'label' => _x( 'Range', '[admin]', 'fibofilters' ),
				'value' => 'range',
			],
			[
				'label' => _x( 'Toggle', '[admin]', 'fibofilters' ),
				'value' => 'toggle',
			],
			[
				'label' => _x( 'Search', '[admin]', 'fibofilters' ),
				'value' => 'search',
			],
			[
				'label' => _x( 'Select', '[admin]', 'fibofilters' ),
				'value' => 'select',
			],
			[
				'label' => _x( 'Color', '[admin]', 'fibofilters' ),
				'value' => 'color',
			],
		];

		return $types;
	}
}
