<?php

class SimpleTags_Client_PostTags {

	/**
	 * SimpleTags_Client_PostTags constructor.
	 */
	public function __construct() {

	}


	/**
	 * Generate current post tags
	 *
	 * @param string $args
	 * @param bool $copyright
	 *
	 * @return string|array|boolean
	 */
	public static function extendedPostTags( $args = '', $copyright = true ) {
		// Get options
		$options = SimpleTags_Plugin::get_option();
		$enable_hidden_terms = SimpleTags_Plugin::get_option_value('enable_hidden_terms');

		// Default values
		$defaults = array(
			'before'    => __( 'Tags: ', 'simple-tags' ),
			'separator' => ', ',
			'after'     => '<br />',
			'post_id'   => 0,
			'inc_cats'  => 0,
			'xformat'   => __( '<a href="%tag_link%" title="%tag_name%" class="st-post-tags t%tag_scale%" style="%tag_size% %tag_color%" %tag_rel%>%tag_name%</a>', 'simple-tags' ),
			'notagtext' => __( 'No tag for this post.', 'simple-tags' ),
			'number'    => 0,
			'format'    => 'flat',
			'ID'        => false,
			'taxonomy'  => false,
			'embedded'  => false,
			'feed'      => false,
			'hide_output' => 0,
			'wrap_class'  => '',
			'link_class'  => '',
			'hide_terms' => 0,
			'smallest'   => 12,
			'largest'    => 12,
			'unit'       => 'pt',
			'color'      => true,
			'mincolor'   => '#353535',
			'maxcolor'   => '#000000',
			'selectionby' => 'count',
			'selection'   => 'desc',
			'orderby'     => 'random',
			'order'       => 'asc',
			'limit_days'  => 0,
		);

		// Get values in DB
		$defaults['before']    = $options['tt_before'];
		$defaults['separator'] = $options['tt_separator'];
		$defaults['after']     = $options['tt_after'];
		$defaults['inc_cats']  = $options['tt_inc_cats'];
		$defaults['xformat']   = $options['tt_xformat'];
		$defaults['format']    = $options['tt_format'];
		$defaults['notagtext'] = $options['tt_notagstext'];
		$defaults['number']    = (int) $options['tt_number'];
		$defaults['smallest']  = isset($options['tt_min_size']) ? (int)$options['tt_min_size'] : 12;
		$defaults['largest']   = isset($options['tt_max_size']) ? (int)$options['tt_max_size'] : 12;
		$defaults['unit']      = isset($options['tt_unit']) ? $options['tt_unit'] : 'pt';
		$defaults['color']     = isset($options['tt_color']) ? $options['tt_color'] : 1;
		$defaults['mincolor']  = isset($options['tt_min_color']) ? $options['tt_min_color'] : '#353535';
		$defaults['maxcolor']  = isset($options['tt_max_color']) ? $options['tt_max_color'] : '#000000';
		$defaults['selectionby'] = isset($options['tt_selectionby']) ? $options['tt_selectionby'] : 'count';
		$defaults['selection']   = isset($options['tt_selection']) ? $options['tt_selection'] : 'desc';
		$defaults['orderby']     = isset($options['tt_orderby']) ? $options['tt_orderby'] : 'random';
		$defaults['order']       = isset($options['tt_order']) ? $options['tt_order'] : 'asc';
		$defaults['limit_days']  = isset($options['tt_limit_days']) ? (int)$options['tt_limit_days'] : 0;
		if ( empty( $args ) ) {
			$args = $options['tt_adv_usage'];
		}

		// Extract data in variables
		$args = wp_parse_args( $args, $defaults );
		extract( $args );

		// If empty use default xformat !
		if ( empty( $xformat ) ) {
			$xformat = $defaults['xformat'];
		}

		$xformat = taxopress_sanitize_text_field($xformat);

		// Choose post ID
		$object_id = (int) $post_id;
		if ( 0 === $object_id ) {
			global $post;
			if ( ! isset( $post->ID ) || 0 === (int) $post->ID ) {
				return false;
			}

			$object_id = (int) $post->ID;
		}

		// Get categories ?
        if($ID){
		    $taxonomies = $taxonomy;
        }else{
		    $taxonomies = ( 0 === (int) $inc_cats ) ? 'post_tag' : array( 'post_tag', 'category' );
        }

		$hidden_terms = [];
		if (!empty($enable_hidden_terms) && !empty($args['hide_terms']) && !empty($args['taxonomy'])) {
			$hidden_terms = get_transient('taxopress_hidden_terms_' . $args['taxonomy']);
			if (!empty($hidden_terms) && is_array($hidden_terms)) {
				$args['exclude'] = implode(',', $hidden_terms);
			}
		}
		
		// Get terms
		// According to codex https://developer.wordpress.org/reference/functions/get_object_term_cache/, $taxonomy must be a string
		$terms = array();
		foreach ( (array) $taxonomies as $taxonomy ) {
			$taxterms = get_object_term_cache( $object_id, $taxonomy );

			if ( false === $taxterms ) {
				$taxterms = wp_get_object_terms( $object_id, $taxonomy );
				$to_cache = array();
				foreach ( $taxterms as $key => $term ) {
					$to_cache[ $key ] = $term->data;
				}
				wp_cache_add( $object_id, $to_cache, $taxonomy . '_relationships' );
			}
			if ($taxterms && !is_wp_error($taxterms)) {
				$terms = array_map('get_term', $taxterms);
			}
		}

		// Hook
		if (!empty($enable_hidden_terms) && !empty($hidden_terms)) {
			$terms = array_filter($terms, function ($term) use ($hidden_terms) {
				return !in_array($term->term_id, $hidden_terms);
			});
		} else {
			$terms = apply_filters('get_the_tags', $terms);
		}

		// Limit to max quantity if set
		$number = (int) $number;
		if ( 0 !== $number ) {
			shuffle( $terms ); // Randomize terms
			$terms = array_slice( $terms, 0, $number );
		}

		// Return for object format
		if ( 'object' === $format ) {
			return $terms;
		}

		// If no terms, return text nothing.
		if ( empty( $terms ) ) {
            if((int)$hide_output === 0){
				$notagtext_html = '<div class="taxopress-no-tags-message">' . esc_html($notagtext) . '</div>';
                return SimpleTags_Client::output_content( 'st-post-tags', $format, '', $notagtext_html, $copyright, $separator, '', '', $before, $after );
            }else{
                return '';
            }
		}

		// HTML Rel
		$rel = SimpleTags_Client::get_rel_attribut();

		//update xformat with class link class
		if(!empty(trim($link_class))){
			$link_class = taxopress_format_class($link_class);
			$xformat = taxopress_add_class_to_format($xformat, $link_class);
		}

		// Filter by timeframe if set
		if (!empty($limit_days) && $limit_days > 0) {
			$min_time = strtotime("-{$limit_days} days");
			$terms = array_filter($terms, function($term) use ($min_time) {
				return strtotime($term->term_group) >= $min_time; // You may need to adjust this if you store term assignment time elsewhere
			});
		}

		// Sort terms from the database before display
		if (!empty($selectionby)) {
			if ($selectionby === 'name') {
				usort($terms, function($a, $b) { return strcmp($a->name, $b->name); });
			} elseif ($selectionby === 'slug') {
				usort($terms, function($a, $b) { return strcmp($a->slug, $b->slug); });
			} elseif ($selectionby === 'count') {
				usort($terms, function($a, $b) { return $a->count <=> $b->count; });
			} elseif ($selectionby === 'random') {
				shuffle($terms);
			}
		}

		// Apply ordering for choosing term from the database
		if (!empty($selection)) {
			if ($selection === 'desc') {
				$terms = array_reverse($terms);
			}
			// 'asc' is default, so do nothing
		}

		// Now, for display order (after slicing/limiting)
		if (!empty($orderby) && $orderby === 'taxopress_term_order') {
			$custom_order = get_option('taxopress_term_order_' . $taxonomy, []);
			if (!empty($custom_order)) {
				$terms_by_id = [];
				foreach ($terms as $term) {
					if (is_object($term) && isset($term->term_id)) {
						$terms_by_id[$term->term_id] = $term;
					}
				}
				$ordered_terms = [];
				foreach ($custom_order as $term_id) {
					if (isset($terms_by_id[$term_id])) {
						$ordered_terms[] = $terms_by_id[$term_id];
						unset($terms_by_id[$term_id]);
					}
				}
				// Add any terms not in custom order at the end
				foreach ($terms_by_id as $term) {
					$ordered_terms[] = $term;
				}
				if ($order === 'desc') {
					$ordered_terms = array_reverse($ordered_terms, true);
				}
				$terms = $ordered_terms;
			}
		} elseif (!empty($orderby)) {
			if ($orderby === 'name') {
				usort($terms, function($a, $b) { return strcmp($a->name, $b->name); });
			} elseif ($orderby === 'count') {
				usort($terms, function($a, $b) { return $a->count <=> $b->count; });
			} elseif ($orderby === 'random') {
				shuffle($terms);
			}
			if (!empty($order) && $order === 'desc' && $orderby !== 'random' && $orderby !== 'taxopress_term_order') {
				$terms = array_reverse($terms);
			}
		}

		// Prepare output
		$output = array();

		// Calculate scaling for font size and color if enabled
		$counts = array();
		foreach ( (array) $terms as $term ) {
			if ( is_object( $term ) ) {
				$counts[ $term->term_id ] = $term->count;
			}
		}

		// Use full RBG code
		if ( strlen( $maxcolor ) == 4 ) {
			$maxcolor = $maxcolor . substr( $maxcolor, 1, strlen( $maxcolor ) );
		}
		if ( strlen( $mincolor ) == 4 ) {
			$mincolor = $mincolor . substr( $mincolor, 1, strlen( $mincolor ) );
		}

		// Check as smallest inferior or equal to largest
		if ( $smallest > $largest ) {
			$smallest = $largest;
		}

		// Scaling - Hard value for the moment
		$scale_min = 0;
		$scale_max = 10;

		if (!empty($counts)) {
			$minval = min( $counts );
			$maxval = max( $counts );
		} else {
			$minval = $maxval = 0;
		}

		$minout = max( $scale_min, 0 );
		$maxout = max( $scale_max, $minout );

		$scale = ( $maxval > $minval ) ? ( ( $maxout - $minout ) / ( $maxval - $minval ) ) : 0;

		foreach ( (array) $terms as $term ) {
			if ( ! is_object( $term ) ) {
				continue;
			}

			// Calculate scale_result for this term
			$scale_result = null;
			if ($scale !== 0 && isset($counts[$term->term_id])) {
				$scale_result = (int) ( ( $term->count - $minval ) * $scale + $minout );
			} else {
				$scale_result = ( $scale_max - $scale_min ) / 2;
			}

			// Remove color/size markers if disabled
			if ( $color == '0' || $color === false || $color === 'false' ) {
				$xformat = str_replace( '%tag_color%', '', $xformat );
			}
			if ( $smallest == $largest ) {
				$xformat = str_replace( '%tag_size%', '', $xformat );
			}

			$output[] = SimpleTags_Client::format_internal_tag( $xformat, $term, $rel, $scale_result, $scale_max, $scale_min, $largest, $smallest, $unit, $maxcolor, $mincolor
			);
		}

		return SimpleTags_Client::output_content( 'st-post-tags '.taxopress_format_class($wrap_class).'', $format, '', $output, $copyright, $separator, '', '', $before, $after );
	}
}
