<?php
namespace Phox\core\menu;

/**
 * Custom Walker Menu
 *
 * @package Phox
 * @author WHMCSdes
 * @link https://whmcsdes.com
 */


/**
 * Class Wdes_Walker_Nav_Menu
 * Core class used to implement an HTML list of nav menu items.
 *
 * @since 1.5.0
 */
class Wdes_Walker_Nav_Menu extends \Walker_Nav_Menu {

	protected $active_megamenu  = false;
	protected $megamenu_col_num = 1;
	protected $megamenu_type = 'normal';


	/**
	 * Menu Fallback
	 *
	 * If this function is assigned to the wp_nav_menu's fallback_cb variable
	 * and a menu has not been assigned to the theme location in the WordPress
	 * menu manager the function with display nothing to a non-logged in user,
	 * and will add a link to the WordPress menu manager if logged in as an admin.
	 *
	 * @param $args
	 * @return string
	 */
	public static function fallback( $args ) {
		if ( current_user_can( 'edit_theme_options' ) ) {

			/* Get Arguments. */
			$container       = $args['container'];
			$container_id    = $args['container_id'];
			$container_class = $args['container_class'];
			$menu_class      = $args['menu_class'];
			$menu_id         = $args['menu_id'];

			// initialize var to store fallback html.
			$fallback_output = '';

			if ( $container ) {
				$fallback_output .= '<' . esc_attr( $container );
				if ( $container_id ) {
					$fallback_output .= ' id="' . esc_attr( $container_id ) . '"';
				}
				if ( $container_class ) {
					$fallback_output .= ' class="' . esc_attr( $container_class ) . '"';
				}
				$fallback_output .= '>';
			}
			$fallback_output .= '<ul';
			if ( $menu_id ) {
				$fallback_output .= ' id="' . esc_attr( $menu_id ) . '"'; }
			if ( $menu_class ) {
				$fallback_output .= ' class="' . esc_attr( $menu_class ) . '"'; }
			$fallback_output .= '>';
			$fallback_output .= '<li><a href="' . esc_url( admin_url( 'nav-menus.php' ) ) . '" title="' . esc_attr__( 'Add a menu', 'phox' ) . '">' . esc_html__( 'Add a menu', 'phox' ) . '</a></li>';
			$fallback_output .= '</ul>';
			if ( $container ) {
				$fallback_output .= '</' . esc_attr( $container ) . '>';
			}

			// if $args has 'echo' key and it's true echo, otherwise return.
			if ( array_key_exists( 'echo', $args ) && $args['echo'] ) {
				x_wdes()->wdes_get_text ($fallback_output) ; // WPCS: XSS OK.
			} else {
				return $fallback_output;
			}
		}
	}

	/**
	 * Starts the list before the elements are added.
	 *
	 * @since WP 3.0.0
	 *
	 * @see Walker::start_lvl()
	 *
	 * @param string   $output Used to append additional content (passed by reference).
	 * @param int      $depth  Depth of menu item. Used for padding.
	 * @param stdClass $args   An object of wp_nav_menu() arguments.
	 */
	public function start_lvl( &$output, $depth = 0, $args = array() ) {
		if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
			$t = '';
			$n = '';
		} else {
			$t = "\t";
			$n = "\n";
		}
		$indent = str_repeat( $t, $depth );

		// Default class.
		$classes = array( 'dropdown-content wdes-global-style' );
		if( $this->active_megamenu  && 0 === $depth){
			$classes[] = 'mega-w';
		}


		if( $this->active_megamenu  && 0 >= $depth && $this->megamenu_type === 'template' ){
			$classes[] = 'd-none';
		}

		/**
		 * Filters the CSS class(es) applied to a menu list element.
		 *
		 * @since 4.8.0
		 *
		 * @param array    $classes The CSS classes that are applied to the menu `<ul>` element.
		 * @param stdClass $args    An object of `wp_nav_menu()` arguments.
		 * @param int      $depth   Depth of menu item. Used for padding.
		 */
		$class_names = join( ' ', apply_filters( 'nav_menu_submenu_css_class', $classes, $args, $depth ) );
		$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
		$output .= "{$n}{$indent}<ul$class_names>{$n}";

	}

	/**
     * Ends the list of after the elements are added.
     *
     * @since 3.0.0
     *
     * @see Walker::end_lvl()
     *
     * @param string   $output Used to append additional content (passed by reference).
     * @param int      $depth  Depth of menu item. Used for padding.
     * @param stdClass $args   An object of wp_nav_menu() arguments.
     */
	public function end_lvl( &$output, $depth = 0, $args = array() ) {
		if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
			$t = '';
			$n = '';
		} else {
			$t = "\t";
			$n = "\n";
		}
		$indent = str_repeat( $t, $depth );
		$output .= "$indent</ul>{$n}";
	}

	/**
     * Starts the element output.
     *
     * @since 3.0.0
     * @since 4.4.0 The {@see 'nav_menu_item_args'} filter was added.
     *
     * @see Walker::start_el()
     *
     * @param string   $output Used to append additional content (passed by reference).
     * @param WP_Post  $item   Menu item data object.
     * @param int      $depth  Depth of menu item. Used for padding.
     * @param stdClass $args   An object of wp_nav_menu() arguments.
     * @param int      $id     Current item ID.
     */
	public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {

		if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
			$t = '';
			$n = '';
		} else {
			$t = "\t";
			$n = "\n";
		}
		$indent = ( $depth ) ? str_repeat( $t, $depth ) : '';

		$classes = empty( $item->classes ) ? array() : (array) $item->classes;
		$classes[] = 'menu-item-' . $item->ID;

		//check if the root element is megamenu
		if( 0 === $depth){
			if($this->active_megamenu = get_post_meta( $item->ID, '_menu_item_mega', true ) ){
				$this->megamenu_col_num = get_post_meta( $item->ID, '_menu_item_col_num', true );
				$this->megamenu_type = get_post_meta( $item->ID, '_menu_item_mega_type', true );
				$classes[] ='mega';
			};
		}

		//check if item has children
		$has_children = $args->walker->has_children;

		if( $has_children || 'template' === $this->megamenu_type ){
			$classes[] ='wdes-dropdown';
		}

		if( $this->active_megamenu  && 1 === $depth){
			$classes[] = 'wdes-col';
			$classes[] = 'wdes-col-' . $this->megamenu_col_num;
			$classes[] = 'heading';
		}


		/**
		 * Filters the arguments for a single nav menu item.
		 *
		 * @since 4.4.0
		 *
		 * @param stdClass $args  An object of wp_nav_menu() arguments.
		 * @param WP_Post  $item  Menu item data object.
		 * @param int      $depth Depth of menu item. Used for padding.
		 */
		$args = apply_filters( 'nav_menu_item_args', $args, $item, $depth );

		/**
		 * Filters the CSS class(es) applied to a menu item's list item element.
		 *
		 * @since 3.0.0
		 * @since 4.1.0 The `$depth` parameter was added.
		 *
		 * @param array    $classes The CSS classes that are applied to the menu item's `<li>` element.
		 * @param WP_Post  $item    The current menu item.
		 * @param stdClass $args    An object of wp_nav_menu() arguments.
		 * @param int      $depth   Depth of menu item. Used for padding.
		 */
		$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) );
		$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';

		/**
		 * Filters the ID applied to a menu item's list item element.
		 *
		 * @since 3.0.1
		 * @since 4.1.0 The `$depth` parameter was added.
		 *
		 * @param string   $menu_id The ID that is applied to the menu item's `<li>` element.
		 * @param WP_Post  $item    The current menu item.
		 * @param stdClass $args    An object of wp_nav_menu() arguments.
		 * @param int      $depth   Depth of menu item. Used for padding.
		 */
		$custom_class    =  $this->get_field_value( $item->ID, 'css_class' );

		$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args, $depth );
		$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';

		$output .= $indent . '<li' . $id . $class_names .'>';

		$atts = array();
		$atts['title']  = ! empty( $item->attr_title ) ? $item->attr_title : '';
		$atts['target'] = ! empty( $item->target )     ? $item->target     : '';
		$atts['rel']    = ! empty( $item->xfn )        ? $item->xfn        : '';
		$atts['href']   = ! empty( $item->url )        ? $item->url        : '';

		$atts['class'] = ($custom_class) ? $custom_class .' ' : '';

		if( $has_children && $depth == 0 || 'template' === $this->megamenu_type){
			$atts['class'] .='drop-link';
		}elseif($has_children && $depth <= 1){
			$atts['class'] .='drop-link hor-dir';
		}

		/**
		 * Filters the HTML attributes applied to a menu item's anchor element.
		 *
		 * @since 3.6.0
		 * @since 4.1.0 The `$depth` parameter was added.
		 *
		 * @param array $atts {
		 *     The HTML attributes applied to the menu item's `<a>` element, empty strings are ignored.
		 *
		 *     @type string $title  Title attribute.
		 *     @type string $target Target attribute.
		 *     @type string $rel    The rel attribute.
		 *     @type string $href   The href attribute.
		 * }
		 * @param WP_Post  $item  The current menu item.
		 * @param stdClass $args  An object of wp_nav_menu() arguments.
		 * @param int      $depth Depth of menu item. Used for padding.
		 */

		$atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );

		$attributes = '';
		foreach ( $atts as $attr => $value ) {
			if ( ! empty( $value ) ) {
				$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
				$attributes .= ' ' . $attr . '="' . $value . '"';
			}
		}

		$icon_align     =  $this->get_field_value( $item->ID, 'icon_align' );
		$icon_name      =  $this->get_field_value( $item->ID, 'icon' );
		$sec_text       =  $this->get_field_value( $item->ID, 'sec_text' );
		$sidebar_name   = '';
		$icon_color     = $this->get_field_value( $item->ID, 'icon_color' );
		$label          = $this->get_field_value( $item->ID, 'item_label' );
		$label_color    = $this->get_field_value( $item->ID, 'label_color' );
		$label_bg_color = $this->get_field_value( $item->ID, 'label_bg_color' );

		if($this->megamenu_type){
			$sidebar_name = $this->get_field_value($item->ID, 'mega_widgets');
		}

		if($has_children && empty($icon_name) ){
			if( $depth >= 1){
				$icon_name = 'fas fa-chevron-right';
			}else{
				$icon_name = 'fas fa-chevron-down';
			}

		}

		/** This filter is documented in wp-includes/post-template.php */
		$title = apply_filters( 'the_title', $item->title, $item->ID );

		/**
		 * Filters a menu item's title.
		 *
		 * @since 4.4.0
		 *
		 * @param string   $title The menu item's title.
		 * @param WP_Post  $item  The current menu item.
		 * @param stdClass $args  An object of wp_nav_menu() arguments.
		 * @param int      $depth Depth of menu item. Used for padding.
		 */
		$title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );

		$item_output = $args->before;

		//The content that will use in all cases like icon and label and Secondary
		// Text this options is run in general

		/* Icon Color */
		$item_icon_color = ( ! empty($icon_color) ) ? 'style="color:'.$icon_color.'"' : '' ;
		$item_icon = $icon_name ? sprintf('<span class="wdes-menu-icon wdes-menu-align-%2$s %1$s" %3$s ></span>',$icon_name, $icon_align, $item_icon_color) : '';

		/* Label */
		$item_label_color = ( ! empty($label) ) ? 'color:'.$label_color.';' : '' ;
		$item_label_bg_color = ( ! empty($label) ) ? 'background:'.$label_bg_color.';' : '' ;
		$item_label = $label ? sprintf('<span class="wdes-menu-label" style="%2$s %3$s" >%1$s</span>',$label, $item_label_color,$item_label_bg_color) : '';

		/* Secondary Text */
		$item_content = '';
		if( !empty($sec_text) && 1 === $depth && $this->active_megamenu ){
			$item_content = sprintf( '<span class="wdes-menu-sec-text" >%s</span>', $sec_text );
		}


		if( $this->active_megamenu && 'with_widget' === $this->megamenu_type  && 1 === $depth){

			if (is_active_sidebar($sidebar_name) && $sidebar_name !== 'wp_inactive_widgets' ) {
				ob_start();
				dynamic_sidebar($sidebar_name);
				$item_output .= ob_get_contents();
				ob_end_clean();
			}
		}elseif ($this->active_megamenu && 'template' === $this->megamenu_type  && 0 === $depth){

			//get the value of the mega menu option from backend
			//use str_replace to remove the prefix and keep only id
			$template_id = str_replace('te-','',$this->get_field_value( $item->ID, 'mega_template'));

			//the menu item html element.this is the parent not the children
			$item_output .= '<a'. $attributes .'>';
			$item_output .= $args->link_before . $title . $args->link_after;


			$item_output .= $item_icon . $item_label ;

			$item_output .= '</a>';
			$item_output .= $item_content ;
			$item_output .= $args->after;

			//get the elementor template by id
			//the template will generate the full html element
			$item_output .= $this->get_megamenu_template($template_id);


		}else{

			//normal menu item
			$item_output .= '<a'. $attributes .'>';
			$item_output .= $args->link_before . $title . $args->link_after;

			$item_output .= $item_icon . $item_label ;

			$item_output .= '</a>';
			$item_output .= $item_content ;
			$item_output .= $args->after;

		}

		/**
		 * Filters a menu item's starting output.
		 *
		 * The menu item's starting output only includes `$args->before`, the opening `<a>`,
		 * the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is
		 * no filter for modifying the opening and closing `<li>` for a menu item.
		 *
		 * @since 3.0.0
		 *
		 * @param string   $item_output The menu item's starting HTML output.
		 * @param WP_Post  $item        Menu item data object.
		 * @param int      $depth       Depth of menu item. Used for padding.
		 * @param stdClass $args        An object of wp_nav_menu() arguments.
		 */
		$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
	}

	/**
     * Ends the element output, if needed.
     *
     * @since 3.0.0
     *
     * @see Walker::end_el()
     *
     * @param string   $output Used to append additional content (passed by reference).
     * @param WP_Post  $item   Page data object. Not used.
     * @param int      $depth  Depth of page. Not Used.
     * @param stdClass $args   An object of wp_nav_menu() arguments.
     */
	public function end_el( &$output, $item, $depth = 0, $args = array() ) {
		if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
			$t = '';
			$n = '';
		} else {
			$t = "\t";
			$n = "\n";
		}
		$output .= "</li>{$n}";
	}

	/**
	 * Get All Fields values
	 *
	 * get value option in menu backend
	 *
	 * @param $item_id
	 * @param $field_name
	 * @return string
	 */
	public function get_field_value( $item_id, $field_name ){
		return get_post_meta( $item_id, '_menu_item_' . $field_name, true );
	}


	/**
	 * Get mega menu from elementor template
	 *
	 * get the id then get the shortcode to get the full template and return the content
	 *
	 * @param $id integer template id
	 * @return string
	 */
	public function get_megamenu_template($id){

		$content = $this->elementor()->frontend->get_builder_content_for_display( $id );

		return '<ul class="dropdown-content mega-w wdes-template-style" ><li>'.$content.'</li></ul>';
	}

	/**
	 * Instance Elementor
	 *
	 * @return mixed
	 */
	protected function elementor(){
		return \Elementor\Plugin::$instance;
	}



}