<?php

/**
 * @package JPageBuilder
 * @author Joomla! Extensions Store
 * @copyright (C) 2024 - Joomla! Extensions Store
 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
 */
// no direct access
defined ( '_JEXEC' ) or die ( 'Restricted access' );

use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Layout\FileLayout;
class JpagebuilderAddonFeature extends JpagebuilderAddons {
	/**
	 * The addon frontend render method.
	 * The returned HTML string will render to the frontend page.
	 *
	 * @return string The HTML string.
	 * @since 1.0.0
	 */
	public function render() {
		$settings = $this->addon->settings;
		$class = (isset ( $settings->class ) && $settings->class) ? $settings->class : '';
		$title = (isset ( $settings->title ) && $settings->title) ? $settings->title : '';
		$heading_selector = (isset ( $settings->heading_selector ) && $settings->heading_selector) ? $settings->heading_selector : 'h3';

		// Options
		list ( $link, $target ) = JpagebuilderAddonHelper::parseLink ( $settings, 'title_url', [ 
				'url' => 'title_url',
				'new_tab' => 'link_open_new_window'
		] );

		$url_appear = (isset ( $settings->url_appear ) && $settings->url_appear) ? $settings->url_appear : 'title';
		$title_position = (isset ( $settings->title_position ) && $settings->title_position) ? $settings->title_position : 'before';
		$feature_type = (isset ( $settings->feature_type ) && $settings->feature_type) ? $settings->feature_type : 'icon';
		$feature_image = (isset ( $settings->feature_image ) && $settings->feature_image) ? $settings->feature_image : '';
		$feature_image_src = isset ( $feature_image->src ) ? $feature_image->src : $feature_image;
		$feature_image_width = (isset ( $feature_image->width ) && $feature_image->width) ? $feature_image->width : '';
		$feature_image_height = (isset ( $feature_image->height ) && $feature_image->height) ? $feature_image->height : '';
		$icon_name = (isset ( $settings->icon_name ) && $settings->icon_name) ? $settings->icon_name : '';
		$text = (isset ( $settings->text ) && $settings->text) ? $settings->text : '';
		$feature_image_alt = (isset ( $settings->feature_image_alt ) && $settings->feature_image_alt) ? $settings->feature_image_alt : $title;

		// Button options
		$btn_text = (isset ( $settings->btn_text ) && trim ( $settings->btn_text )) ? $settings->btn_text : '';
		$btn_class = '';
		$btn_class .= (isset ( $settings->btn_type ) && $settings->btn_type) ? ' jpb-btn-' . $settings->btn_type : '';
		$btn_class .= (isset ( $settings->btn_size ) && $settings->btn_size) ? ' jpb-btn-' . $settings->btn_size : '';
		$btn_class .= (isset ( $settings->btn_shape ) && $settings->btn_shape) ? ' jpb-btn-' . $settings->btn_shape : ' jpb-btn-rounded';
		$btn_class .= (isset ( $settings->btn_appearance ) && $settings->btn_appearance) ? ' jpb-btn-' . $settings->btn_appearance : '';
		$btn_class .= (isset ( $settings->btn_block ) && $settings->btn_block) ? ' ' . $settings->btn_block : '';

		$btn_icon = (isset ( $settings->btn_icon ) && $settings->btn_icon) ? $settings->btn_icon : '';
		$btn_icon_position = (isset ( $settings->btn_icon_position ) && $settings->btn_icon_position) ? $settings->btn_icon_position : 'left';

		list ( $btn_link, $btn_link_target ) = JpagebuilderAddonHelper::parseLink ( $settings, 'btn_url', [ 
				'url' => 'btn_url',
				'new_tab' => 'btn_target'
		] );

		$attribs = (isset ( $btn_link_target ) && $btn_link_target) ? $btn_link_target : '';
		$attribs .= (! empty ( $btn_link )) ? ' href="' . $btn_link . '"' : '';
		$attribs .= ' id="btn-' . $this->addon->id . '"';

		$attribs .= ! empty ( $settings->btn_aria_label ) ? ' aria-label="' . $settings->btn_aria_label . '"' : '';

		$btn_aria_label = ! empty ( $settings->btn_aria_label ) ? $settings->btn_aria_label : '';

		$visually_hidden_text = $btn_aria_label ? '<span class="jpb-visually-hidden">' . $btn_aria_label . '' : '';

		$icon_arr = array_filter ( explode ( ' ', $btn_icon ) );

		if (count ( $icon_arr ) === 1) {
			$btn_icon = 'fas ' . $btn_icon;
		}

		if ($btn_icon_position === 'left') {
			$btn_text = ($btn_icon) ? '<i class="' . $btn_icon . '" aria-hidden="true"></i> ' . $btn_text : $btn_text;
		} else {
			$btn_text = ($btn_icon) ? $btn_text . ' <i class="' . $btn_icon . '" aria-hidden="true"></i>' : $btn_text;
		}

		if (strpos ( $feature_image_src, "http://" ) !== false || strpos ( $feature_image_src, "https://" ) !== false) {
			$feature_image_src = $feature_image_src;
		} elseif ($feature_image_src) {
			$feature_image_src = Uri::base ( true ) . '/' . $feature_image_src;
		}

		// Lazy image loading
		$placeholder = $feature_image_src === '' ? false : $this->get_image_placeholder ( $feature_image_src );

		// Image or icon position
		$icon_image_position = '';

		if ($title_position === 'before') {
			$icon_image_position = 'after';
		} else if ($title_position === 'after') {
			$icon_image_position = 'before';
		} else {
			$icon_image_position = $title_position;
		}

		// Reset Alignment for left and right style
		$alignment = '';

		if (($icon_image_position === 'left') || ($icon_image_position === 'right')) {
			$alignment = 'jpb-text-' . $icon_image_position;
		}

		// Icon or Image
		$media = '';

		if ($feature_type === 'icon') {
			if ($icon_name) {
				$media .= '<div class="jpb-icon">';

				if (($link && $url_appear == 'icon') || ($link && $url_appear == 'both')) {
					$media .= '<a href="' . $link . '" ' . $target . '>';
				}

				$media .= '<span class="jpb-icon-container" role="img" aria-label="' . strip_tags ( $title ) . '">';

				$icon_arr = array_filter ( explode ( ' ', $icon_name ) );

				if (count ( $icon_arr ) === 1) {
					$icon_name = 'fa ' . $icon_name;
				}

				$media .= '<i class="' . $icon_name . '" aria-hidden="true"></i>';
				$media .= '</span>';

				if (($link && $url_appear == 'icon') || ($link && $url_appear == 'both')) {
					$media .= '</a>';
				}

				$media .= '</div>';
			}
		} else {
			if ($feature_image_src) {
				$media .= '<span class="jpb-img-container">';

				if (($link && $url_appear == 'icon') || ($link && $url_appear == 'both')) {
					$media .= '<a href="' . $link . '" ' . $target . '>';
				}

				$media .= '<img class="jpb-img-responsive' . ($placeholder ? ' jpb-element-lazy' : '') . '" style="display: inline-block" src="' . ($placeholder ? $placeholder : $feature_image_src) . '" alt="' . strip_tags ( $feature_image_alt ) . '" ' . ($placeholder ? 'data-large="' . $feature_image_src . '"' : '') . ' ' . ($feature_image_width ? 'width="' . $feature_image_width . '"' : '') . ' ' . ($feature_image_height ? 'height="' . $feature_image_height . '"' : '') . ' loading="lazy">';

				if (($link && $url_appear == 'icon') || ($link && $url_appear == 'both')) {
					$media .= '</a>';
				}

				$media .= '</span>';
			}
		}

		if ($feature_type === "both" && $icon_name) {
			$media .= '<div class="jpb-icon">';

			if (($link && $url_appear == 'icon') || ($link && $url_appear == 'both')) {
				$media .= '<a href="' . $link . '" ' . $target . '>';
			}

			$media .= '<span class="jpb-icon-container" role="img" aria-label="' . strip_tags ( $title ) . '">';

			$icon_arr = array_filter ( explode ( ' ', $icon_name ) );

			if (count ( $icon_arr ) === 1) {
				$icon_name = 'fa ' . $icon_name;
			}

			$media .= '<i class="' . $icon_name . '" aria-hidden="true"></i>';
			$media .= '</span>';

			if (($link && $url_appear == 'icon') || ($link && $url_appear == 'both')) {
				$media .= '</a>';
			}

			$media .= '</div>';
		}

		// Title
		$feature_title = '';

		if ($title) {
			$heading_class = '';

			if (\in_array ( $icon_image_position, [ 
					'left',
					'right'
			] )) {
				$heading_class = ' jpb-media-heading';
			}

			$feature_title .= '<' . $heading_selector . ' class="jpb-addon-title jpb-feature-box-title' . $heading_class . '">';

			if (($link && $url_appear === 'title') || ($link && $url_appear === 'both')) {
				$feature_title .= '<a href="' . $link . '" ' . $target . '>';
			}

			$feature_title .= $title;

			if (($link && $url_appear === 'title') || ($link && $url_appear == 'both')) {
				$feature_title .= '</a>';
			}

			$feature_title .= '</' . $heading_selector . '>';
		}

		// Feature Text
		$feature_text = '';
		if (! empty ( $text )) {
			$feature_text = '<div class="jpb-addon-text">';
			$feature_text .= $text;
			$feature_text .= '</div>';
		}

		// Output
		$output = '<div class="jpb-addon jpb-addon-feature ' . $alignment . ' ' . $class . '">';
		$output .= '<div class="jpb-addon-content">';

		if ($icon_image_position === 'before') {
			$output .= ($media) ? $media : '';
			$output .= '<div class="jpb-media-content">';
			$output .= ($title) ? $feature_title : '';
			$output .= $feature_text;

			if ($btn_text) {
				$output .= '<a ' . $attribs . ' class="jpb-btn ' . $btn_class . '">' . $btn_text . $visually_hidden_text . '</a>';
			}

			$output .= '</div>';
		} else if ($icon_image_position === 'after') {
			$output .= ($title) ? $feature_title : '';
			$output .= ($media) ? $media : '';
			$output .= '<div class="jpb-media-content">';
			$output .= $feature_text;

			if ($btn_text) {
				$output .= '<a ' . $attribs . ' class="jpb-btn ' . $btn_class . '">' . $btn_text . $visually_hidden_text . '</a>';
			}

			$output .= '</div>';
		} else {
			$output .= '<div class="jpb-media">';
			$output .= '<div class="pull-' . $icon_image_position . '">';
			$output .= $media ?? '';
			$output .= '</div>';
			$output .= '<div class="jpb-media-body">';
			$output .= '<div class="jpb-media-content">';
			$output .= ($title) ? $feature_title : '';
			$output .= $feature_text;

			if ($btn_text) {
				$output .= '<a ' . $attribs . ' class="jpb-btn ' . $btn_class . '">' . $btn_text . $visually_hidden_text . '</a>';
			}

			$output .= '</div>'; // .jpb-media-content
			$output .= '</div>';
			$output .= '</div>';
		}

		$output .= '</div>';
		$output .= '</div>';

		return $output;
	}

	/**
	 * Generate the CSS string for the frontend page.
	 *
	 * @return string The CSS string for the page.
	 * @since 1.0.0
	 */
	public function css() {
		$settings = $this->addon->settings;
		$addon_id = '#jpb-addon-' . $this->addon->id;
		$cssHelper = new JpagebuilderCSSHelper ( $addon_id );

		$feature_type = (isset ( $settings->feature_type ) && $settings->feature_type) ? $settings->feature_type : 'icon';
		$feature_image = (isset ( $settings->feature_image ) && $settings->feature_image) ? $settings->feature_image : '';
		$feature_image_src = isset ( $feature_image->src ) ? $feature_image->src : $feature_image;
		$icon_name = (isset ( $settings->icon_name ) && $settings->icon_name) ? $settings->icon_name : '';
		$title_position = (isset ( $settings->title_position ) && $settings->title_position) ? $settings->title_position : '';

		// Css start
		$css = '';

		$addonProps = [ 
				'background_color' => 'background-color'
		];
		$addonBgStyle = $cssHelper->generateStyle ( ':self', $settings, $addonProps, "" );
		$css .= $addonBgStyle;

		$css .= $cssHelper->generateStyle ( '.jpb-addon-text', $settings, [ 
				'addon_color' => 'color'
		], false );

		$textProps = [ 
				'text_background' => 'background-color',
				'text_padding' => 'padding'
		];
		$textUnits = [ 
				'text_background' => false,
				'text_padding' => false
		];
		$textModifiers = [ 
				'text_padding' => 'spacing'
		];

		$textStyle = $cssHelper->generateStyle ( '.jpb-media-content', $settings, $textProps, $textUnits, $textModifiers );
		$css .= $textStyle;

		$contentFallbacks = [ 
				'font' => 'text_font_family',
				'size' => 'text_fontsize',
				'line_height' => 'text_lineheight',
				'weight' => 'text_fontweight'
		];

		$contentTypography = $cssHelper->typography ( '.jpb-addon-text', $settings, 'content_typography', $contentFallbacks );
		$css .= $contentTypography;

		$titleFallbacks = [ 
				'font' => 'title_font_family',
				'size' => 'title_fontsize',
				'line_height' => 'title_lineheight',
				'letter_spacing' => 'title_letterspace',
				'uppercase' => 'title_font_style.uppercase',
				'italic' => 'title_font_style.italic',
				'underline' => 'title_font_style.underline',
				'weight' => 'title_font_style.weight'
		];

		$textTitleTypography = $cssHelper->typography ( '.jpb-feature-box-title', $settings, 'title_typography', $titleFallbacks );
		$css .= $textTitleTypography;

		if ($feature_type === 'icon' || $feature_type === 'both') {
			if (! empty ( $icon_name )) {
				$settings->icon_boxshadow = JpagebuilderCSSHelper::parseBoxShadow ( $settings, 'icon_boxshadow' );

				$props = [ 
						'icon_boxshadow' => 'box-shadow',
						'icon_padding' => 'padding',
						'icon_color' => 'color',
						'icon_background' => 'background-color',
						'icon_border_color' => 'border-style: solid; border-color',
						'icon_border_width' => 'border-width',
						'icon_border_radius' => 'border-radius'
				];
				$units = [ 
						'icon_boxshadow' => false,
						'icon_padding' => false,
						'icon_color' => false,
						'icon_border_color' => false,
						'icon_background' => false
				];
				$modifiers = [ 
						'icon_padding' => 'spacing'
				];
				$iconStyle = $cssHelper->generateStyle ( '.jpb-icon .jpb-icon-container', $settings, $props, $units, $modifiers, null, false, 'display:inline-block;text-align:center;' );
				$iconMarginStyle = $cssHelper->generateStyle ( '.jpb-icon', $settings, [ 
						'icon_margin_top' => 'margin-top',
						'icon_margin_bottom' => 'margin-bottom'
				] );
				$iconSizeStyle = $cssHelper->generateStyle ( '.jpb-icon .jpb-icon-container > i', $settings, [ 
						'icon_size' => [ 
								'font-size',
								'width',
								'height',
								'line-height'
						]
				] );

				$css .= $iconStyle;
				$css .= $iconMarginStyle;
				$css .= $iconSizeStyle;
			}
		}

		$settings->text_alignment = $cssHelper->parseAlignment ( $settings, 'alignment' );
		$textAlignment = $cssHelper->generateStyle ( '.jpb-addon-content', $settings, [ 
				'text_alignment' => 'text-align'
		], false );
		$css .= $textAlignment;

		if ($feature_image_src && ($feature_type === 'image' || $feature_type === 'both')) {
			$imageMarginSelector = '';
			$isContainer = false;
			$imageProps = [ 
					'feature_image_margin' => 'margin'
			];
			$imageUnits = [ 
					'feature_image_margin' => false
			];

			if (\in_array ( $title_position, [ 
					'left',
					'right'
			] )) {
				$imageMarginSelector = '.jpb-media .pull-left, .jpb-media .pull-right';
				$css .= $cssHelper->generateStyle ( $imageMarginSelector, $settings, [ 
						'feature_image_width' => 'width'
				], [ 
						'feature_image_width' => '%'
				] );
			} elseif (\in_array ( $title_position, [ 
					'before',
					'after'
			] )) {
				$imageMarginSelector = '.jpb-img-container';
				$isContainer = true;
			}

			if (! empty ( $imageMarginSelector )) {
				$featureImageStyle = $cssHelper->generateStyle ( $imageMarginSelector, $settings, $imageProps, $imageUnits, [ 
						'feature_image_margin' => 'spacing'
				], null, false, $isContainer ? 'display: block;' : '' );
			}

			$device = JpagebuilderBase::$defaultDevice;

			if (! empty ( $settings->feature_image_width->$device ) && $settings->feature_image_width->$device === '100') {
				$mediaBodyStyle = $cssHelper->generateStyle ( '.jpb-media .jpb-media-body', $settings, [ 
						'feature_image_width' => 'width'
				], '%' );
			}

			$css .= ! empty ( $featureImageStyle ) ? $featureImageStyle : '';
			$css .= ! empty ( $mediaBodyStyle ) ? $mediaBodyStyle : '';
		}

		// Button style
		$layout_path = JPATH_ROOT . '/components/com_jpagebuilder/layouts';
		$css_path = new FileLayout ( 'addon.css.button', $layout_path );
		$options = new stdClass ();
		$options->button_type = (isset ( $settings->btn_type ) && $settings->btn_type) ? $settings->btn_type : '';
		$options->button_appearance = (isset ( $settings->btn_appearance ) && $settings->btn_appearance) ? $settings->btn_appearance : '';
		$options->button_color = (isset ( $settings->btn_color ) && $settings->btn_color) ? $settings->btn_color : '';
		$options->button_color_hover = (isset ( $settings->btn_color_hover ) && $settings->btn_color_hover) ? $settings->btn_color_hover : '';
		$options->button_background_color = (isset ( $settings->btn_background_color ) && $settings->btn_background_color) ? $settings->btn_background_color : '';
		$options->button_background_color_hover = (isset ( $settings->btn_background_color_hover ) && $settings->btn_background_color_hover) ? $settings->btn_background_color_hover : '';
		$options->button_font_style = (isset ( $settings->btn_font_style ) && $settings->btn_font_style) ? $settings->btn_font_style : '';
		if (isset ( $settings->button_padding_original )) {
			$options->button_padding = $settings->button_padding_original;
		} elseif (isset ( $settings->button_padding )) {
			$options->button_padding = $settings->button_padding;
		}
		$options->fontsize = (isset ( $settings->btn_fontsize ) && $settings->btn_fontsize) ? $settings->btn_fontsize : '';
		$options->button_background_gradient = (isset ( $settings->btn_background_gradient ) && $settings->btn_background_gradient) ? $settings->btn_background_gradient : new stdClass ();
		$options->button_background_gradient_hover = (isset ( $settings->btn_background_gradient_hover ) && $settings->btn_background_gradient_hover) ? $settings->btn_background_gradient_hover : new stdClass ();
		$options->button_size = ! empty ( $settings->btn_size ) ? $settings->btn_size : null;
		$options->button_typography = ! empty ( $settings->btn_typography ) ? $settings->btn_typography : null;

		$buttonMarginStyle = $cssHelper->generateStyle ( '.jpb-media-content .jpb-btn', $settings, [ 
				'button_margin' => 'margin'
		], false, [ 
				'button_margin' => 'spacing'
		] );
		$css .= $buttonMarginStyle;

		$css .= $css_path->render ( array (
				'addon_id' => $addon_id,
				'options' => $options,
				'id' => 'btn-' . $this->addon->id
		) );

		$settings->addon_hover_boxshadow = JpagebuilderCSSHelper::parseBoxShadow ( $settings, 'addon_hover_boxshadow' );
		$settings->addon_mock_transition = '.3s';

		$hoverProps = [ 
				'addon_hover_bg' => 'background-color',
				'addon_hover_color' => 'color',
				'addon_hover_boxshadow' => 'box-shadow'
		];
		$addonTransitionStyle = $cssHelper->generateStyle ( ':self', $settings, [ 
				'addon_mock_transition' => 'transition'
		], false );
		$addonHoverStyle = $cssHelper->generateStyle ( '&:hover', $settings, $hoverProps, false );

		if (empty ( $settings->text )) {
			$css .= $addon_id . ' .jpb-addon-title.jpb-feature-box-title {display: block;}';
		}
		$css .= $cssHelper->generateStyle ( '.jpb-feature-box-title, .jpb-feature-box-title a', $settings, [ 
				'title_text_color' => 'color'
		], false );
		$css .= $cssHelper->generateStyle ( '&:hover .jpb-feature-box-title, &:hover .jpb-feature-box-title a', $settings, [ 
				'title_hover_color' => 'color'
		], false );
		$css .= $cssHelper->generateStyle ( '&:hover .jpb-addon-text', $settings, [ 
				'addon_hover_color' => 'color'
		], false );
		$css .= $cssHelper->generateStyle ( '&:hover .jpb-icon-container', $settings, [ 
				'icon_hover_color' => 'color',
				'icon_hover_bg' => 'background-color'
		], false );
		$transformCss = $cssHelper->generateTransformStyle ( ':self', $settings, 'transform' );

		$css .= $addonTransitionStyle;
		$css .= $addonHoverStyle;
		$css .= $transformCss;

		return $css;
	}

	/**
	 * Generate the lodash template string for the frontend editor.
	 *
	 * @return string The lodash template string.
	 * @since 1.0.0
	 */
	public static function getFrontendEditor() {
		$lodash = new JpagebuilderLodashlib ( '#jpb-addon-{{ data.id }}' );
		$output = '
		<#
			let classList = " jpb-btn-" + data.btn_type;
			classList += " jpb-btn-" + data.btn_size;
			classList += " jpb-btn-" + data.btn_shape;

			if (!_.isEmpty(data.btn_appearance)) {
				classList += " jpb-btn-"+data.btn_appearance;
			}

			let icon_arr = (typeof data.icon_name !== "undefined" && data.icon_name) ? data.icon_name.split(" ") : "";
			let icon_name = icon_arr.length === 1 ? "fa "+data.icon_name : data.icon_name;

			let icon_image_position = "";
			if (data.title_position == "before") {
				icon_image_position = "after";
			} else if(data.title_position == "after") {
				icon_image_position = "before";
			} else {
				icon_image_position = data.title_position;
			}

            let alignment = "";
			if( ( icon_image_position == "left" ) || ( icon_image_position == "right" ) ) {
				alignment = "jpb-text-" + icon_image_position;
			}

			let media = "";
			const isMenu = _.isString(data.title_url?.menu) && data.title_url.type === "menu" && data.title_url?.menu;
			const isPage = _.isString(data.title_url?.page) && data.title_url.type === "page" && data.title_url?.page;

			const isObject = _.isObject(data.title_url) && ((data.title_url.type === "url" && data.title_url?.url !== "") ||  isMenu || isPage);
			const isString = _.isString(data.title_url) && data.title_url !== "";
			
			let urlObj = {};
			let url = "";
			let target = "";
			let rel = "";
			
			
			if(isObject || isString) {
				urlObj = _.isObject(data.title_url) ? data.title_url : window.getSiteUrl(data.title_url, data.link_open_new_window === 1 ? "_blank": "");
				if(urlObj.type === "url") {	
					url = urlObj.url;
				} else if(urlObj.type === "menu") {
					url = urlObj.menu;
				} else if(urlObj.type === "page") {
					url = `index.php?option=com_jpagebuilder&view=page&id=${urlObj.page}`
				}
				target = urlObj.new_tab ? "_blank": "";
				rel += urlObj.nofollow ? "nofollow": "";
				rel += urlObj.noopener ? " noopener": "";
				rel += urlObj.noreferrer ? " noreferrer": "";

			}

			if (data.feature_type == "icon") {
				if (data.icon_name) {
					media += \'<div class="jpb-icon">\';
						if( ((isObject || isString) && data.url_appear == "icon") || ((isObject || isString) && data.url_appear == "both" ) ){
							media += \'<a href="\'+ url +\'" target="\' + target + \'" rel="\' + rel + \'" >\';
						}
						media  += \'<span class="jpb-icon-container">\';
							media  += \'<i class="\'+icon_name+\'"></i>\';
						media  += \'</span>\';
						if( ((isObject || isString) && data.url_appear == "icon") || ((isObject || isString) && data.url_appear == "both" ) ){
							media += \'</a>\';
						}
					media += \'</div>\';
				}
			} else {
				var feature_image = {}
				if (typeof data.feature_image !== "undefined" && typeof data.feature_image.src !== "undefined") {
					feature_image = data.feature_image
				} else {
					feature_image = {src: data.feature_image}
				}

				if (feature_image.src) {
					media  += \'<span class="jpb-img-container">\';
					if ( ((isObject || isString) && data.url_appear == "icon") || ((isObject || isString) && data.url_appear == "both" ) ) {
						media += \'<a href="\'+ url +\'" target="\' + target + \'" rel="\' + rel + \'">\';
					}

					if (feature_image.src.indexOf("http://") != -1 || feature_image.src.indexOf("https://") != -1) {
						media  += \'<img class="jpb-img-responsive" style="display: inline-block" src="\'+feature_image.src+\'" alt="\'+data.title+\'">\';
					} else {
						media  += \'<img class="jpb-img-responsive" style="display: inline-block" src="\'+pagebuilder_base+feature_image.src+\'" alt="\'+data.title+\'">\';
					}

					if ( ((isObject || isString) && data.url_appear == "icon") || ((isObject || isString) && data.url_appear == "both" ) ) {
						media += \'</a>\';
					}

					media  += \'</span>\';
				}
            } 
				

			if (data.feature_type == "both" && data.icon_name) {
				media += \'<div class="jpb-icon">\';
						if( ((isObject || isString) && data.url_appear == "icon") || ((isObject || isString) && data.url_appear == "both" ) ){
							media += \'<a href="\'+ url +\'" target="\' + target + \'" rel="\' + rel + \'" >\';
						}
						media  += \'<span class="jpb-icon-container">\';
							media  += \'<i class="\'+icon_name+\'"></i>\';
						media  += \'</span>\';
						if( ((isObject || isString) && data.url_appear == "icon") || ((isObject || isString) && data.url_appear == "both" ) ){
							media += \'</a>\';
						}
					media += \'</div>\';
			}

			let feature_title = "";
			if (data.title) {
				var heading_class = "";
				if ( ( icon_image_position == "left" ) || ( icon_image_position == "right" ) ) {
					heading_class = " jpb-media-heading";
				}

				let heading_selector = data.heading_selector || "h3";

				feature_title += \'<\'+heading_selector+\' class="jpb-addon-title jpb-feature-box-title  \'+heading_class+\'">\';
				if (((isObject || isString) && data.url_appear == "title") || ((isObject || isString) && data.url_appear == "both" )) {
					feature_title += \'<a href="\'+ url +\'" target="\' + target + \'" rel="\' + rel + \'" class="jp-inline-editable-element" data-id="\'+data.id+\'" data-fieldName="title" contenteditable="true">\';
				}

				if (_.isEmpty(data.title_url)) {
					feature_title += \'<span class="jp-inline-editable-element" data-id="\'+data.id+\'" data-fieldName="title" contenteditable="true">\';
				}

				feature_title += data.title;

				if (_.isEmpty(data.title_url)) {
					feature_title += \'</span>\';
				}

				if (((isObject || isString) && data.url_appear == "title") || ((isObject || isString) && data.url_appear == "both")) {
					feature_title += \'</a>\';
				}

				feature_title += \'</\'+heading_selector+\'>\';
			}

			let feature_text = "";
			if(data.text) {
				feature_text  = \'<div id="addon-text-\'+data.id+\'" class="jpb-addon-text jp-editable-content" data-id="\'+data.id+\'" data-fieldName="text">\';
				feature_text += data.text;
				feature_text += \'</div>\';	
			}
		#>

		<style type="text/css">';

		// button start
		$buttonTypographyFallbacks = [ 
				'font' => 'data.btn_font_family',
				'size' => 'data.btn_fontsize',
				'letter_spacing' => 'data.btn_letterspace',
				'uppercase' => 'data.btn_font_style?.uppercase',
				'italic' => 'data.btn_font_style?.italic',
				'underline' => 'data.btn_font_style?.underline',
				'weight' => 'data.btn_font_style?.weight'
		];
		$output .= $lodash->typography ( '.jpb-btn', 'data.btn_typography', $buttonTypographyFallbacks );
		$output .= '<# if (data.btn_size == "custom") { #>';
		$output .= $lodash->spacing ( 'padding', '.jpb-btn', 'data.button_padding' );
		$output .= '<# } #>';
		$output .= $lodash->spacing ( 'margin', '.jpb-btn', 'data.button_margin' );
		$output .= '<# if (data.btn_block == "jpb-btn-block") { #>';
		$output .= '#jpb-addon-{{ data.id }} .jpb-btn {display: block;}';
		$output .= '<# } #>';

		$output .= $lodash->unit ( 'margin-top', '.jpb-addon-title', 'data.title_margin_top', 'px' );
		$output .= $lodash->unit ( 'margin-bottom', '.jpb-addon-title', 'data.title_margin_bottom', 'px' );

		// custom style
		$output .= '<# if (data.btn_type == "custom") { #>';
		$output .= $lodash->color ( 'color', '.jpb-btn', 'data.btn_color' );
		$output .= $lodash->color ( 'color', '.jpb-btn:hover', 'data.btn_color_hover' );

		$output .= '<# if (data.btn_appearance == "outline") { #>';
		$output .= '#jpb-addon-{{ data.id }} .jpb-btn {background-color: transparent;}';
		$output .= $lodash->unit ( 'border-color', '.jpb-btn', 'data.btn_background_color', '', false );
		$output .= $lodash->unit ( 'border-color', '.jpb-btn:hover', 'data.btn_background_color_hover', '', false );
		$output .= $lodash->unit ( 'background-color', '.jpb-btn:hover', 'data.btn_background_color_hover', '', false );
		$output .= '<# } else if (data.btn_appearance == "gradient") { #>';
		$output .= '#jpb-addon-{{ data.id }} .jpb-btn {border: none;}';
		$output .= $lodash->color ( 'background-color', '.jpb-btn', 'data.btn_background_gradient' );
		$output .= $lodash->color ( 'background-color', '.jpb-btn:hover', 'data.btn_background_gradient_hover' );
		$output .= '<# } else { #>';
		$output .= $lodash->color ( 'background-color', '.jpb-btn', 'data.btn_background_color' );
		$output .= $lodash->color ( 'background-color', '.jpb-btn:hover', 'data.btn_background_color_hover' );
		$output .= '<# } #>';
		$output .= '<# } #>';

		// link
		$output .= '<# if (data.btn_type == "link") { #>';
		$output .= '#jpb-addon-{{ data.id }} .jpb-btn {padding: 0; border-width: 0; text-decoration: none; border-radius: 0;}';
		$output .= $lodash->color ( 'color', '.jpb-btn', 'data.link_btn_color' );
		$output .= $lodash->unit ( 'border-color', '.jpb-btn', 'data.link_btn_border_color', '', false );
		$output .= $lodash->unit ( 'border-bottom-width', '.jpb-btn', 'data.link_btn_border_width', 'px' );
		$output .= $lodash->unit ( 'padding-bottom', '.jpb-btn', 'data.link_btn_padding_bottom', 'px' );
		$output .= $lodash->color ( 'color', '.jpb-btn:hover, .jpb-btn:focus', 'data.link_btn_hover_color' );
		$output .= $lodash->unit ( 'border-color', '.jpb-btn:hover, .jpb-btn:focus', 'data.link_btn_border_hover_color', '', false );
		$output .= '<# } #>';
		// button end

		// icon
		$output .= '#jpb-addon-{{ data.id }} .jpb-icon .jpb-icon-container {display: inline-block; text-align: center; transition: 300ms;}';
		$output .= $lodash->color ( 'color', '.jpb-icon .jpb-icon-container', 'data.icon_color' );
		$output .= $lodash->spacing ( 'padding', '.jpb-icon .jpb-icon-container', 'data.icon_padding' );
		$output .= $lodash->color ( 'background-color', '.jpb-icon .jpb-icon-container', 'data.icon_background' );
		$output .= '<# if (data.icon_border_color) { #>';
		$output .= '#jpb-addon-{{ data.id }} .jpb-icon .jpb-icon-container {border-style: solid;}';
		$output .= $lodash->unit ( 'border-color', '.jpb-icon .jpb-icon-container', 'data.icon_border_color', '', false );
		$output .= $lodash->unit ( 'border-width', '.jpb-icon .jpb-icon-container', 'data.icon_border_width', 'px' );
		$output .= '<# } #>';
		$output .= $lodash->unit ( 'border-radius', '.jpb-icon .jpb-icon-container', 'data.icon_border_radius', 'px' );
		$output .= $lodash->boxShadow ( '.jpb-icon .jpb-icon-container', 'data.icon_boxshadow' );

		$output .= $lodash->unit ( 'margin-top', '.jpb-icon', 'data.icon_margin_top', 'px' );
		$output .= $lodash->unit ( 'margin-bottom', '.jpb-icon', 'data.icon_margin_bottom', 'px' );

		$output .= $lodash->unit ( 'font-size', '.jpb-icon .jpb-icon-container > i', 'data.icon_size', 'px' );
		$output .= $lodash->unit ( 'width', '.jpb-icon .jpb-icon-container > i', 'data.icon_size', 'px' );
		$output .= $lodash->unit ( 'height', '.jpb-icon .jpb-icon-container > i', 'data.icon_size', 'px' );
		$output .= $lodash->unit ( 'line-height', '.jpb-icon .jpb-icon-container > i', 'data.icon_size', 'px' );

		$output .= $lodash->color ( 'color', '&:hover .jpb-icon .jpb-icon-container', 'data.icon_hover_color' );
		$output .= $lodash->color ( 'background-color', '&:hover .jpb-icon .jpb-icon-container', 'data.icon_hover_bg' );

		// image
		$output .= '#jpb-addon-{{ data.id }} .jpb-img-container {display: block;}';
		$output .= '<# if (!_.isEmpty(data.feature_image_margin) && (data.title_position == "left" || data.title_position == "right")) { #>';
		$output .= $lodash->spacing ( 'margin', '.jpb-media .pull-left, .jpb-media .pull-right', 'data.feature_image_margin' );
		$output .= '<# } #>';

		$output .= '<# if (!_.isEmpty(data.feature_image_margin) && (data.title_position == "after" || data.title_position == "before")) { #>';
		$output .= $lodash->spacing ( 'margin', '.jpb-img-container', 'data.feature_image_margin' );
		$output .= '<# } #>';
		$output .= '<# if (data.feature_type !== "icon") { #>';
		$output .= $lodash->unit ( 'width', '.jpb-media .pull-left, .jpb-media .pull-right', 'data.feature_image_width', '%' );
		$output .= '<# } #>';

		$output .= '#jpb-addon-{{ data.id }} {transition: 300ms;}';
		$output .= '#jpb-addon-{{ data.id }} .jpb-feature-box-title {transition: 300ms;}';

		// title
		$titleTypographyFallbacks = [ 
				'font' => 'data.title_font_family',
				'size' => 'data.title_fontsize',
				'line_height' => 'data.title_lineheight',
				'letter_spacing' => 'data.title_letterspace',
				'uppercase' => 'data.title_font_style?.uppercase',
				'italic' => 'data.title_font_style?.italic',
				'underline' => 'data.title_font_style?.underline',
				'weight' => 'data.title_font_style?.weight'
		];
		$output .= $lodash->typography ( '.jpb-feature-box-title', 'data.title_typography', $titleTypographyFallbacks );

		$output .= '<# if (!data.text) { #>';
		$output .= '#jpb-addon-{{ data.id }} .jpb-addon-title.jpb-feature-box-title {display: block;}';
		$output .= '<# } #>';

		$output .= $lodash->color ( 'color', '.jpb-feature-box-title, .jpb-feature-box-title a', 'data.title_text_color' );
		$output .= $lodash->color ( 'color', '.jpb-addon-text', 'data.addon_color' );

		// content
		$textTypographyFallbacks = [ 
				'font' => 'data.text_font_family',
				'size' => 'data.text_fontsize',
				'line_height' => 'data.text_lineheight',
				'weight' => 'data.text_fontweight'
		];
		$output .= $lodash->typography ( '.jpb-addon-text', 'data.content_typography', $textTypographyFallbacks );
		$output .= $lodash->spacing ( 'padding', '.jpb-media-content', 'data.text_padding' );
		$output .= $lodash->color ( 'background-color', '.jpb-media-content', 'data.text_background' );
		$output .= $lodash->alignment ( 'text-align', '.jpb-addon-content', 'data.alignment' );

		// Addon Background Color
		$output .= $lodash->color ( 'background-color', ':self', 'data.background_color' );

		// Hover
		$output .= $lodash->color ( 'color', '&:hover .jp-editable-content', 'data.addon_hover_color' );
		$output .= $lodash->color ( 'background-color', '&:hover', 'data.addon_hover_bg' );
		$output .= $lodash->boxShadow ( '&:hover', 'data.addon_hover_boxshadow' );
		$output .= $lodash->color ( 'color', '&:hover .jpb-feature-box-title, &:hover .jpb-feature-box-title a', 'data.title_hover_color' );
		$output .= $lodash->generateTransformCss ( '', 'data.transform' );

		$output .= '
		</style>
		<div class="jpb-addon jpb-addon-feature {{ data.class }} {{ alignment }}">
			<div class="jpb-addon-content">
			<# 
			const isMenuBtn = _.isString(data.btn_url?.menu) && data.btn_url.type === "menu" && data.btn_url?.menu;
			const isPageBtn = _.isString(data.btn_url?.page) && data.btn_url.type === "page" && data.btn_url?.page;

			const isObjectBtn = _.isObject(data.btn_url) && ((data.btn_url.type === "url" && data.btn_url?.url !== "") ||  isMenu || isPage);
			
			let urlObjBtn = {};
			let urlBtn = "";
			let targetBtn= "";
			let relBtn = "";
			let ariaLabel = data.btn_aria_label || "";
			const visuallyHiddenText = ariaLabel ? "<span class=\'jpb-visually-hidden\'>" + ariaLabel + "</span>" : "";
			
				urlObjBtn = isObjectBtn ? data.btn_url : window.getSiteUrl(data.btn_url, data.btn_target);

				if(urlObjBtn.type === "url") {	
					urlBtn = urlObjBtn.url;
				}

				if(urlObjBtn.type === "menu") {
					urlBtn = urlObjBtn.menu || "";
				}
				
				if(urlObjBtn.type === "page") {
					urlBtn = urlObjBtn.page ? `index.php?option=com_jpagebuilder&view=page&id=${urlObjBtn.page}` : "";
				}
				targetBtn = urlObjBtn.new_tab ? "_blank": "";
				relBtn += urlObjBtn.nofollow ? "nofollow": "";
				relBtn += urlObjBtn.noopener ? " noopener": "";
				relBtn += urlObjBtn.noreferrer ? " noreferrer": "";
			
			#>
				<# if (icon_image_position == "before") { #>
					<# if(media){ #>
						{{{ media }}}
					<# } #>
                    <div class="jpb-media-content">
                        <# if(data.title){ #>
                            {{{ feature_title }}}
                        <# } #>
						{{{ feature_text }}}
						<# if(data.btn_text && _.trim(data.btn_text)){
							let icon_arr = (typeof data.btn_icon !== "undefined" && data.btn_icon) ? data.btn_icon.split(" ") : "";
							let icon_name = icon_arr.length === 1 ? "fa "+data.btn_icon : data.btn_icon;
						#>
							<a href=\'{{ urlBtn }}\' target=\'{{ targetBtn }}\' rel=\'{{ relBtn }}\' id="btn-{{ data.id }}" aria-label="{{ ariaLabel }}" class="jpb-btn {{ classList }}"><# if(data.btn_icon_position == "left" && !_.isEmpty(data.btn_icon)) { #><i class="{{ icon_name }}"></i> <# } #>{{ data.btn_text }}<# if(data.btn_icon_position == "right" && !_.isEmpty(data.btn_icon)) { #> <i class="{{ icon_name }}"></i><# } #>{{{ visuallyHiddenText }}}</a>
						<# } #>
                    </div>
				<# } else if (icon_image_position == "after") { #>
					<# if(data.title){ #>
						{{{ feature_title }}}
					<# } #>
					<# if(media){ #>
						{{{ media }}}
					<# } #>
                    <div class="jpb-media-content">
					{{{ feature_text }}}
					<# if(data.btn_text && _.trim(data.btn_text)){
						let icon_arr = (typeof data.btn_icon !== "undefined" && data.btn_icon) ? data.btn_icon.split(" ") : "";
						let icon_name = icon_arr.length === 1 ? "fa "+data.btn_icon : data.btn_icon;
					#>
						<a href=\'{{ urlBtn }}\' target=\'{{ targetBtn }}\' rel=\'{{ relBtn }}\' class="jpb-btn {{ classList }}"><# if(data.btn_icon_position == "left" && !_.isEmpty(data.btn_icon)) { #><i class="{{ icon_name }}"></i> <# } #>{{ data.btn_text }}<# if(data.btn_icon_position == "right" && !_.isEmpty(data.btn_icon)) { #> <i class="{{ icon_name }}"></i><# } #>{{{ visuallyHiddenText }}}</a>
					<# } #>
                    </div>
				<# } else { #>
					<# if(media) { #>
						<div class="jpb-media">
							<div class="pull-{{ icon_image_position }}">{{{ media }}}</div>
							<div class="jpb-media-body">
                                <div class="jpb-media-content">
                                    
                                    <# if(data.title){ #>
                                        {{{ feature_title }}}
                                    <# } #>
									{{{ feature_text }}}
									<# if(data.btn_text && _.trim(data.btn_text)){
										let icon_arr = (typeof data.btn_icon !== "undefined" && data.btn_icon) ? data.btn_icon.split(" ") : "";
										let icon_name = icon_arr.length === 1 ? "fa "+data.btn_icon : data.btn_icon;
									#>
										<a href=\'{{ urlBtn }}\' target=\'{{ targetBtn }}\' rel=\'{{ relBtn }}\' id="btn-{{ data.id }}" aria-label="{{ ariaLabel }}" class="jpb-btn {{ classList }}"><# if(data.btn_icon_position == "left" && !_.isEmpty(data.btn_icon)) { #><i class="{{ icon_name }}"></i> <# } #>{{ data.btn_text }}<# if(data.btn_icon_position == "right" && !_.isEmpty(data.btn_icon)) { #> <i class="{{ icon_name }}"></i><# } #>{{{ visuallyHiddenText }}}</a>
									<# } #>
                                </div>
							</div>
						</div>
					<# } else { #>
						<div class="jpb-media">
							<div class="jpb-media-body">
                                <div class="jpb-media-content">
                                  
                                    <# if(data.title){ #>
                                        {{{ feature_title }}}
                                    <# } #>
									{{{ feature_text }}}
									<# if(data.btn_text && _.trim(data.btn_text)){
										let icon_arr = (typeof data.btn_icon !== "undefined" && data.btn_icon) ? data.btn_icon.split(" ") : "";
										let icon_name = icon_arr.length === 1 ? "fa "+data.btn_icon : data.btn_icon;
									#>
										<a href=\'{{ urlBtn }}\' target=\'{{ targetBtn }}\' rel=\'{{ relBtn }}\' id="btn-{{ data.id }}" aria-label="{{ ariaLabel }}" class="jpb-btn {{ classList }}"><# if(data.btn_icon_position == "left" && !_.isEmpty(data.btn_icon)) { #><i class="{{ icon_name }}"></i> <# } #>{{ data.btn_text }}<# if(data.btn_icon_position == "right" && !_.isEmpty(data.btn_icon)) { #> <i class="{{ icon_name }}"></i><# } #>{{ visuallyHiddenText }}</a>
									<# } #>
                                </div>
							</div>
						</div>
					<# } #>
				<# } #>
			</div>
		</div>';

		return $output;
	}
}
