<?php
declare( strict_types=1 );

namespace FiboFilters\Filters\SourceTypes;

use FiboFilters\WooCommerce\Helper as WooCommerceHelper;

/**
 * Class SourceType
 */
class SourceType implements SourceTypeInterface {
	const ARTIFICIAL_NO_VALUE = - 1;

	/** @var WooCommerceHelper */
	protected $woocommerce_helper;

	/** @var array */
	protected $data = [];

	/** @var bool */
	protected $calculate_percentage_share;

	/** @var bool */
	protected $analyse_source_values;

	public function __construct(
		WooCommerceHelper $woocommerce_helper,
		array $data,
		bool $calculate_percentage_share = true,
		bool $analyse_source_values = true
	) {
		$this->woocommerce_helper         = $woocommerce_helper;
		$this->calculate_percentage_share = $calculate_percentage_share;
		$this->analyse_source_values      = $analyse_source_values;

		if ( ! empty( $data ) ) {
			$this->set_data( array_merge( $this->get_default_data_structure(), $data ) );
		}
	}

	public function set_data( array $data ): void {
		$this->data = $data;
	}

	public function get_data(): array {
		return $this->data;
	}

	/**
	 * @param string $attr Attribute name.
	 *
	 * @return mixed|null
	 */
	public function get_data_attr( string $attr ) {
		return $this->data[ $attr ] ?? null;
	}

	/**
	 * @param string $attr Attribute name.
	 * @param mixed  $value Attribute value.
	 */
	public function set_data_attr( string $attr, $value ): void {
		$this->data[ $attr ] = $value;
	}

	public function analyse_source_values(): void {
	}

	public function validate_user_input( string $user_input, string $filter_type = '' ): array {
		if ( $filter_type === 'range' ) {
			$values = explode( '-', $user_input );

			if ( count( $values ) === 2 ) {
				$from = is_numeric( $values[0] ) ? floatval( $values[0] ) : self::ARTIFICIAL_NO_VALUE;
				$to   = is_numeric( $values[1] ) ? floatval( $values[1] ) : self::ARTIFICIAL_NO_VALUE;

				if ( $to >= 0 && $from > $to ) {
					$from = $to;
				}

				return [
					$from,
					$to,
				];
			}

			return [ self::ARTIFICIAL_NO_VALUE, self::ARTIFICIAL_NO_VALUE ];
		}

		return array_map( 'strval', explode( ',', $user_input ) );
	}

	public function get_calculate_percentage_share(): float {
		return 0.0;
	}

	public function is_calculate_percentage_share(): bool {
		return $this->calculate_percentage_share;
	}

	public function is_analyse_source_values(): bool {
		return $this->analyse_source_values;
	}

	protected function get_total_products_count(): int {
		return $this->woocommerce_helper->get_total_products_count();
	}

	protected function get_percentage( int $count, int $total ): float {
		if ( $total <= 0 ) {
			return 0.0;
		}

		return round( ( $count / $total ) * 100, 1 );
	}

	protected function get_default_data_structure(): array {
		return [
			'label'                 => '',
			'value'                 => '',
			'sourceType'            => '',
			'rawValue'              => '',
			'userInputType'         => 'default',
			'orderByTermOrder'      => false,
			'orderNumerically'      => false,
			'allowedTypes'          => [],
			'overwrittenAttributes' => [],
			'overwrittenMeta'       => [],
			'nonEditableAttributes' => [],
			'analyseData'           => [],
			'hidden'                => false,
		];
	}

	public function set_value_analyse_data( array $data ): void {
		$this->set_data_attr( 'analyseData', $data );

		if ( $data['type'] === 'number' ) {
			$this->add_allowed_type( 'range' );
			$this->set_data_attr( 'orderNumerically', true );
			if ( ! empty( $data['hasMultivalues'] ) ) {
				$this->remove_non_editable_attribute( 'multivalue_range_logic' );
			}
		} elseif ( $data['type'] === 'number_extended' ) {
			$this->add_allowed_type( 'range' );
			$this->set_data_attr( 'orderNumerically', true );
			if ( ! empty( $data['hasMultivalues'] ) ) {
				$this->remove_non_editable_attribute( 'multivalue_range_logic' );
			}
		} elseif ( $data['type'] === 'bool_two_values' ) {
			$this->add_allowed_type( 'toggle' );
			$this->remove_allowed_type( 'checkboxes' );
			$this->remove_allowed_type( 'buttons' );
		} elseif ( $data['type'] === 'bool_one_value' ) {
			$this->add_allowed_type( 'toggle' );
			$this->remove_allowed_type( 'radio' );
			$this->remove_allowed_type( 'select' );
		} elseif ( $data['type'] === 'string' ) {
			$this->add_allowed_type( 'buttons' );
		}
	}

	public function format_price( string $price ): float {
		return (float) wc_format_decimal( $price );
	}

	private function add_allowed_type( string $type ): void {
		$allowed_types = $this->get_data_attr( 'allowedTypes' );
		$allowed_types = array_unique( array_merge( $allowed_types, [ $type ] ) );
		$this->set_data_attr( 'allowedTypes', $allowed_types );
	}

	private function remove_allowed_type( string $type ): void {
		$allowed_types = $this->get_data_attr( 'allowedTypes' );
		$allowed_types = array_filter(
			$allowed_types,
			function ( string $allowed_type ) use ( $type ): bool {
				return $allowed_type !== $type;
			}
		);
		$this->set_data_attr( 'allowedTypes', array_values( $allowed_types ) );
	}

	private function remove_non_editable_attribute( string $attribute ): void {
		$non_editable_attributes = $this->get_data_attr( 'nonEditableAttributes' );
		$non_editable_attributes = array_filter(
			$non_editable_attributes,
			function ( string $current_attribute ) use ( $attribute ): bool {
				return $current_attribute !== $attribute;
			}
		);
		$this->set_data_attr( 'nonEditableAttributes', array_values( $non_editable_attributes ) );
	}
}
