<?php

/**
 * Class Thz_Array_Flatten
 *
 * Flattens a multidimensional array by creating unique keys that are generated by concatenating
 * parent and child keys. For example:
 *
 * array( 'key1' => array( 'key2' => 'value' ) ) is translated into array( 'key1/key2' => 'value' )
 *
 */
class Thz_Array_Flatten{
	/**
	 * Store flattened array
	 * Defaults to array
	 * @var array
	 */
	private $options = array();
	/**
	 * Store raw options
	 * @var array
	 */
	private $raw_options;

	/**
	 * Array_Flatten constructor.
	 *
	 * @param array $options
	 */
	public function __construct( /*Array*/ $options ) {
		$this->raw_options = $options;
		if( is_array( $options ) ) {
			$this->flatten_array( $options );
		}
	}

	/**
	 * Recurrent method, populates $this->options with the option found into the multidimensional array.
	 * Keys will be constructed as option/child_array_key/child_array_key
	 *
	 * @param $raw_options
	 * @param string $current_key
	 */
	private function flatten_array( $raw_options, $current_key = '' ){
		foreach( $raw_options as $key => $option ){
			$separator = empty( $current_key ) ? '' : '/';
			if( ( !is_array( $option ) || ( is_array( $option ) && !$option ) ) && !is_object( $option ) ){
				$this->options[ $current_key . $separator . $key ] = $option;
			}else{
				if( is_object( $option ) ){
					$option = (array) $option;
				}
				$this->flatten_array( $option, $current_key . $separator . $key );
			}
		}
	}

	/**
	 * Getter, returns the flattened array of options
	 * @return array
	 */
	public function get_flattened_options(){
		return $this->options;
	}

	/**
	 * @param $option_id
	 * @param null $default
	 *
	 * @return mixed|null
	 */
	public function get_option( $option_id, $default = null ){
		// first look in flattened options array
		if( array_key_exists( $option_id, $this->options ) ){
			return $this->options[ $option_id ];
		}else{
			// option might not be set at all, return the default if that's the case
			$keys = explode( '/', $option_id );
			if( !isset( $this->raw_options[ $keys[0] ] ) ){
				return new WP_Error( 'not_found' );
			}else {
				/**
				 * Check if looking for an array of options, try getting that
				 */
				$option = $this->find_array_option( $option_id );
				return $option;
			}
		}
	}

	/**
	 * Searches the raw options for a given key and returns the result it finds
	 * @param $option_id
	 * @param bool $options
	 *
	 * @return array|bool|WP_Error
	 */
	public function find_array_option( $option_id, $options = false ){
		if( false === $options ){
			$options = $this->raw_options;
		}

		if( !$option_id ){
			return $options;
		}

		if( is_object( $options ) ){
			$options = (array) $options;
		}

		if( !is_array( $option_id ) ){
			$option_id = explode( '/', $option_id );
		}

		if( array_key_exists( $option_id[0], $options ) ){
			$key = array_shift( $option_id );
			return $this->find_array_option( $option_id, $options[ $key ] );
		}else{
			return new WP_Error( 'not_found' );
		}
	}
}
