<?php

namespace Limb_Chatbot\Includes\Widgets\Items;

use Limb_Chatbot\Includes\Services\Helper;
use Limb_Chatbot\Includes\Traits\Json_Serializable_Trait;
use ReflectionClass;

/**
 * Class Widget_Item
 *
 * Base class for widget items.
 *
 * @since 1.0.0
 */
class Widget_Item {
	use Json_Serializable_Trait;

	/**
	 * Widget item unique identifier.
	 *
	 * @var string
	 * @since 1.0.0
	 */
	public string $id;

	/**
	 * Widget item title.
	 *
	 * @var string
	 * @since 1.0.0
	 */
	public string $title = '';

	/**
	 * Widget item type.
	 *
	 * @var string
	 * @since 1.0.0
	 */
	public string $type;

	/**
	 * Whether the widget item is published.
	 *
	 * @var bool
	 * @since 1.0.0
	 */
	public bool $published = false;

	/**
	 * Arbitrary data associated with the widget item.
	 *
	 * @var array
	 * @since 1.0.0
	 */
	public array $data;

	/**
	 * Array of page or block locations where the item is shown.
	 *
	 * @var array
	 * @since 1.0.11
	 */
	public array $locations = [];

	public bool $notify = false;

	/**
	 * Widget_Item constructor.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
	}

	/**
	 * Populate class properties from an associative array.
	 *
	 * @param array $array Associative array with property values.
	 * @since 1.0.0
	 */
	public function populate_properties( array $array ): void {
		$reflection = new ReflectionClass( $this );
		$properties = $reflection->getProperties();
		foreach ( $properties as $property ) {
			if ( $property->getDeclaringClass()->getName() !== $reflection->getName() && ! $reflection->isSubclassOf( self::class ) ) {
				// If not own property, pass it. Except if reflection is the children of current one !
				continue;
			}
			if ( ! $property->getType() || ! $property->getType()->isBuiltin() ) {
				// If not built in property type, pass it.
				continue;
			}
			$value = $array[ $property->getName() ] ?? null;
			// Otherwise leave as it is
			if ( isset( $value ) ) {
				$this->{$property->getName()} = Helper::cast_value( $property->getType()->getName(), $value );
			}
			unset( $value );
		}
	}

	/**
	 * Set the widget item ID.
	 *
	 * @param string $id
	 * @return $this
	 * @since 1.0.0
	 */
	public function set_id( string $id ) {
		$this->id = $id;

		return $this;
	}

	/**
	 * Set the widget item title.
	 *
	 * @param string $title
	 * @return $this
	 * @since 1.0.0
	 */
	public function set_title( string $title ) {
		$this->title = $title;

		return $this;
	}

	/**
	 * Set the widget item type.
	 *
	 * @param string $type
	 * @return $this
	 * @since 1.0.0
	 */
	public function set_type( string $type ) {
		$this->type = $type;

		return $this;
	}

	/**
	 * Set the published status of the widget item.
	 *
	 * @param bool $published
	 * @return $this
	 * @since 1.0.0
	 */
	public function set_published( bool $published ) {
		$this->published = $published;

		return $this;
	}

	/**
	 * Set the widget item data array.
	 *
	 * @param array $data
	 * @return $this
	 * @since 1.0.0
	 */
	public function set_data( array $data ) {
		$this->data = $data;

		return $this;
	}

	/**
	 * Check if the widget item is published.
	 *
	 * @return bool
	 * @since 1.0.0
	 */
	public function is_published(): bool {
		return $this->published;
	}

	/**
	 * Set widget item locations.
	 *
	 * @param array $locations
	 * @return $this
	 * @since 1.0.11
	 */
	public function set_locations( array $locations ) {
		$this->locations = $locations;

		return $this;
	}

	/**
	 * Set the notify status of the widget item.
	 *
	 * @param bool $notify
	 * @return $this
	 * @since 1.0.11
	 */
	public function set_notify( bool $notify ) {
		$this->notify = $notify;

		return $this;
	}
}