<?php
namespace SabaiApps\Framework;

/**
 * Link class for representing HTML links and buttons.
 * Provides methods for setting attributes, labels, icons, and rendering the link or button as HTML.
 */
class Link {

	private $_url, $_label, $_attributes;
	protected $_options;

	/**
	 * Constructor.
	 *
	 * @param string $url URL of the link.
	 * @param string $label Label for the link.
	 * @param array  $options Additional options for rendering.
	 * @param array  $attributes HTML attributes for the link.
	 */
	public function __construct( $url, $label, array $options = array(), array $attributes = array() ) {
		$this->_url        = $url;
		$this->_label      = $label;
		$this->_options    = $options;
		$this->_attributes = $attributes;
	}

	/**
	 * Gets the URL of the link.
	 *
	 * @return string URL of the link.
	 */
	public function getUrl() {
		return $this->_url;
	}

	/**
	 * Sets the URL of the link.
	 *
	 * @param string $url URL to set.
	 * @return $this
	 */
	public function setUrl( $url ) {
		$this->_url = $url;
		return $this;
	}

	/**
	 * Gets the label of the link.
	 *
	 * @return string Label of the link.
	 */
	public function getLabel() {
		return $this->_label;
	}

	/**
	 * Sets the label of the link.
	 *
	 * @param string $label Label to set.
	 * @param bool   $escape Whether to escape the label (default: true).
	 * @return $this
	 */
	public function setLabel( $label, $escape = true ) {
		$this->_label                = $label;
		$this->_options['no_escape'] = ! $escape;
		return $this;
	}

	/**
	 * Checks if the label should not be escaped.
	 *
	 * @return bool True if no escape, false otherwise.
	 */
	public function isNoEscape() {
		return ! empty( $this->_options['no_escape'] );
	}

	/**
	 * Gets the icon associated with the link.
	 *
	 * @return string|null Icon class name or null if not set.
	 */
	public function getIcon() {
		return isset( $this->_options['icon'] ) ? $this->_options['icon'] : null;
	}

	/**
	 * Sets the icon for the link.
	 *
	 * @param string $icon Icon class name.
	 * @return $this
	 */
	public function setIcon( $icon ) {
		$this->_options['icon'] = $icon;
		return $this;
	}

	/**
	 * Gets a specific attribute of the link.
	 *
	 * @param string $key Attribute name.
	 * @return mixed Attribute value or null if not set.
	 */
	public function getAttribute( $key ) {
		return isset( $this->_attributes[ $key ] ) ? $this->_attributes[ $key ] : null;
	}

	/**
	 * Sets an attribute for the link.
	 *
	 * @param string $key Attribute name.
	 * @param mixed  $value Attribute value.
	 * @return $this
	 */
	public function setAttribute( $key, $value ) {
		$this->_attributes[ $key ] = $value;
		return $this;
	}

	/**
	 * Removes an attribute from the link.
	 *
	 * @param string $key Attribute name.
	 * @return $this
	 */
	public function removeAttribute( $key ) {
		unset( $this->_attributes[ $key ] );
		return $this;
	}

	/**
	 * Sets whether the link should be rendered as a button.
	 *
	 * @param bool $flag True to render as a button, false otherwise.
	 * @return $this
	 */
	public function setBtn( $flag ) {
		$this->_options['btn'] = (bool) $flag;
		return $this;
	}

	/**
	 * Checks if the link is set to be rendered as a button.
	 *
	 * @return bool|null True if button, false otherwise or null if not set.
	 */
	public function getBtn() {
		return isset( $this->_options['btn'] ) ? $this->_options['btn'] : null;
	}

	/**
	 * Renders the link or button as HTML.
	 *
	 * @return string HTML representation of the link or button.
	 */
	public function __toString() {
		// Render icon if set
		if ( ! empty( $this->_options['icon'] ) ) {
			$icon = htmlspecialchars( $this->_options['icon'], ENT_QUOTES, 'UTF-8', false );
			$icon = '<i class="' . $icon . '"></i>';
		}

		// Render label
		if ( strlen( $this->_label ) ) {
			$label = empty( $this->_options['no_escape'] ) ? htmlspecialchars( $this->_label, ENT_QUOTES, 'UTF-8', false ) : $this->_label;
			if ( isset( $icon ) ) {
				if ( empty( $this->_options['no_icon_space'] ) ) {
					$icon .= ' ';
				}
				if ( empty( $this->_options['no_wrap_label'] ) ) {
					$label = $icon . '<span>' . $label . '</span>';
				} else {
					$label = $icon . $label;
				}
			}
		} else {
			$label = isset( $icon ) ? $icon : '';
		}
		if ( ! empty( $this->_options['label_suffix_html'] ) ) {
			$label .= $this->_options['label_suffix_html'];
		}

		// Render attributes
		$attributes = array();
		foreach ( $this->_getAttributes() as $k => $v ) {
			if ( empty( $v ) ) {
				continue;
			}

			$attributes[ $k ] = $k . '="' . htmlspecialchars( $v, ENT_COMPAT, 'UTF-8', false ) . '"';
		}

		// Render as button or link
		if ( ! empty( $this->_options['btn'] ) ) {
			if ( ! array_key_exists( 'onclick', $this->_attributes ) && strlen( $this->_url ) && strpos( $this->_url, '#' ) !== 0 ) {
				if ( ! empty( $this->_attributes['target'] ) ) {
					$attributes['onclick'] = 'onclick="window.open(\'' . $this->_url . '\', \'' . htmlspecialchars( $this->_attributes['target'], ENT_COMPAT, 'UTF-8', false ) . '\'); return false;"';
					unset( $attributes['target'] );
				} else {
					$attributes['onclick'] = 'onclick="location.href=\'' . $this->_url . '\'; return false;"';
				}
			}
			$html = '<button ' . implode( ' ', $attributes ) . '>' . $label . '</button>';
		} else {
			if ( ! strlen( $this->_url ) ) {
				return $label;
			}

			$html = '<a href="' . $this->_url . '" ' . implode( ' ', $attributes ) . '>' . $label . '</a>';
		}

		// Append extra HTML if set
		if ( isset( $this->_options['extra_html'] ) ) {
			$html .= $this->_options['extra_html'];
		}

		return $html;
	}

	/**
	 * Gets all attributes of the link.
	 *
	 * @return array Array of attributes.
	 */
	protected function _getAttributes() {
		return $this->_attributes;
	}
}
