<?php
/**
 * AnWP Football Leagues :: League.
 *
 * @since   0.1.0
 * @package AnWP_Football_Leagues
 */

require_once dirname( __FILE__ ) . '/../vendor/taxonomy-core/Taxonomy_Core.php';

/**
 * AnWP Football Leagues :: League taxonomy.
 *
 * @since 0.1.0
 * @see   https://github.com/WebDevStudios/Taxonomy_Core
 */
class AnWPFL_League extends Taxonomy_Core {

	/**
	 * Parent plugin class.
	 *
	 * @var    AnWP_Football_Leagues
	 * @since  0.1.0
	 */
	protected $plugin = null;

	/**
	 * Constructor.
	 * Register Taxonomy.
	 *
	 * See documentation in Taxonomy_Core, and in wp-includes/taxonomy.php.
	 *
	 * @since  0.1.0
	 * @param  AnWP_Football_Leagues $plugin Main plugin object.
	 */
	public function __construct( $plugin ) {

		$this->plugin = $plugin;
		$this->hooks();

		parent::__construct(
			[ // Should be an array with Singular, Plural, and Registered name.
				esc_html__( 'League', 'anwp-football-leagues' ),
				esc_html__( 'Leagues', 'anwp-football-leagues' ),
				'anwp_league',
			],
			[ // Register taxonomy arguments.
				'hierarchical'      => false,
				'show_in_nav_menus' => false,
				'rewrite'           => [ 'slug' => 'league' ],
				'show_in_menu'      => false,
				'labels'            => [
					'search_items'  => esc_html__( 'Search Leagues', 'anwp-football-leagues' ),
					'all_items'     => esc_html__( 'All Leagues', 'anwp-football-leagues' ),
					'edit_item'     => esc_html__( 'Edit League', 'anwp-football-leagues' ),
					'view_item'     => esc_html__( 'View League', 'anwp-football-leagues' ),
					'update_item'   => esc_html__( 'Update League', 'anwp-football-leagues' ),
					'add_new_item'  => esc_html__( 'Add New League', 'anwp-football-leagues' ),
					'new_item_name' => esc_html__( 'New League Title', 'anwp-football-leagues' ),
				],
			],
			[ // Post types to attach to.
				'anwp_competition',
			]
		);

		add_action( 'cmb2_admin_init', [ $this, 'init_cmb2_metaboxes' ] );
	}

	/**
	 * Create CMB2 metabox
	 *
	 * @since 0.10.0 (2019-02-22)
	 */
	public function init_cmb2_metaboxes() {

		// Start with an underscore to hide fields from custom fields list
		$prefix = '_anwpfl_';

		/**
		 * Initiate the metabox
		 */
		$cmb = new_cmb2_box(
			[
				'id'           => 'anwp_league_metabox',
				'title'        => esc_html__( 'League Info', 'anwp-football-leagues' ),
				'object_types' => [ 'term' ],
				'context'      => 'normal',
				'priority'     => 'high',
				'classes'      => 'anwp-b-wrap',
				'show_names'   => true,
				'taxonomies'   => [ 'anwp_league' ],
			]
		);

		$cmb->add_field(
			[
				'name'             => esc_html__( 'Country', 'anwp-football-leagues' ),
				'id'               => $prefix . 'country',
				'type'             => 'select',
				'show_option_none' => '- ' . esc_html__( 'select country', 'anwp-football-leagues' ) . ' -',
				'default'          => '',
				'options_cb'       => [ $this->plugin->data, 'cb_get_countries' ],
				'column'           => [
					'position' => 4,
				],
				'display_cb'       => [ $this, 'render_league_country_column' ],
			]
		);

		$cmb->add_field(
			[
				'name'             => esc_html__( 'Classification', 'anwp-football-leagues' ),
				'id'               => $prefix . 'classification',
				'type'             => 'select',
				'show_option_none' => '- ' . esc_html__( 'select classification', 'anwp-football-leagues' ) . ' -',
				'default'          => '',
				'options_cb'       => [ $this, 'get_classification_options' ],
				'column'           => [
					'position' => 5,
				],
				'display_cb'       => [ $this, 'render_league_classification_column' ],
			]
		);

		$cmb->add_field(
			[
				'name'        => esc_html__( 'Priority', 'anwp-football-leagues' ),
				'id'          => $prefix . 'priority',
				'type'        => 'text_small',
				'default'     => '',
				'description' => esc_html__( 'from 1 to 20, default: 10', 'anwp-football-leagues' ),
				'column'      => [
					'position' => 6,
				],
				'attributes'  => [
					'type' => 'number',
					'min'  => '1',
					'max'  => '20',
				],
			]
		);
	}

	/**
	 * Rendering Country Column content.
	 *
	 * @param            $field_args
	 * @param CMB2_Field $field
	 *
	 * @since 0.10.0
	 */
	public function render_league_country_column( $field_args, $field ) {

		$options = $field->options();

		if ( isset( $options[ $field->value ] ) ) {
			echo esc_html( $options[ $field->value ] );
		} else {
			echo esc_attr( $field->value );
		}
	}

	/**
	 * Rendering Classification Column content.
	 *
	 * @param            $field_args
	 * @param CMB2_Field $field
	 *
	 * @since 0.17.2
	 */
	public function render_league_classification_column( $field_args, $field ) {

		$options = $this->get_classification_options();

		if ( isset( $options[ $field->value ] ) ) {
			echo esc_html( $options[ $field->value ] );
		} else {
			echo esc_attr( $field->value );
		}
	}

	/**
	 * Get classification options for leagues.
	 *
	 * @since 0.17.2
	 * @return array
	 */
	public function get_classification_options(): array {

		$options = [
			'national_d1'         => __( 'National - Top Division', 'anwp-football-leagues' ),
			'national_d2'         => __( 'National - 2nd Division', 'anwp-football-leagues' ),
			'national_d3'         => __( 'National - 3rd Division', 'anwp-football-leagues' ),
			'national_d4'         => __( 'National - 4th Division+', 'anwp-football-leagues' ),
			'national_cup'        => __( 'National Cup', 'anwp-football-leagues' ),
			'league_cup'          => __( 'League Cup', 'anwp-football-leagues' ),
			'super_cup'           => __( 'Super Cup', 'anwp-football-leagues' ),
			'continental_club'    => __( 'Continental - Club', 'anwp-football-leagues' ),
			'world_club'          => __( 'World - Club', 'anwp-football-leagues' ),
			'continental_nations' => __( 'Continental - Nations', 'anwp-football-leagues' ),
			'world_nations'       => __( 'World - Nations', 'anwp-football-leagues' ),
			'friendly'            => __( 'Friendly', 'anwp-football-leagues' ),
			'youth'               => __( 'Youth', 'anwp-football-leagues' ),
		];

		/**
		 * Filter classification options.
		 *
		 * @since 0.17.2
		 *
		 * @param array $options Classification options.
		 */
		return apply_filters( 'anwpfl/league/classification_options', $options );
	}

	/**
	 * Get classification weights for sorting.
	 *
	 * @since 0.17.2
	 * @return array
	 */
	public function get_classification_weights(): array {

		$weights = [
			'national_d1'         => 10,
			'national_d2'         => 20,
			'national_d3'         => 30,
			'national_d4'         => 40,
			'national_cup'        => 50,
			'league_cup'          => 60,
			'super_cup'           => 70,
			'continental_club'    => 80,
			'world_club'          => 90,
			'continental_nations' => 100,
			'world_nations'       => 110,
			'friendly'            => 120,
			'youth'               => 130,
		];

		/**
		 * Filter classification weights for sorting.
		 *
		 * @since 0.17.2
		 *
		 * @param array $weights Classification weights.
		 */
		return apply_filters( 'anwpfl/league/classification_weights', $weights );
	}

	/**
	 * Initiate our hooks.
	 *
	 * @since 0.1.0
	 */
	public function hooks() {
		add_filter( 'manage_anwp_league_custom_column', [ $this, 'columns_display' ], 10, 3 );
		add_filter( 'manage_edit-anwp_league_columns', [ $this, 'columns' ], 10, 1 );
	}

	/**
	 * Registers admin columns to display.
	 *
	 * @param  array $columns Array of registered column names/labels.
	 *
	 * @return array          Modified array.
	 * @since  0.5.1 (2018-03-23)
	 */
	public function columns( $columns ) {

		// Add new columns
		$new_columns = [
			'anwpfl_league_id' => esc_html__( 'ID', 'anwp-football-leagues' ),
		];

		return array_merge( $columns, $new_columns );
	}

	/**
	 * Handles admin column display.
	 *
	 * @param string $string      Blank string.
	 * @param string $column_name Name of the column.
	 * @param int    $term_id     Term ID.
	 *
	 * @since  0.5.1 (2018-03-23)
	 */
	public function columns_display( $string, $column_name, $term_id ) {
		switch ( $column_name ) {
			case 'anwpfl_league_id':
				echo (int) $term_id;
				break;
		}
	}

	/**
	 * Helper function, returns leagues with id and title.
	 * Can be used as cmb2 callback options.
	 *
	 * @since 0.5.1 (2018-03-22)
	 * @return array $output_data - Array <league_id> => <league_title>.
	 */
	public function get_league_options(): array {

		$cache_key   = 'FL-LEAGUE-OPTIONS';
		$cached_data = anwp_fl()->cache->get( $cache_key );

		if ( $cached_data ) {
			return $cached_data;
		}

		static $term_data = null;

		if ( null === $term_data ) {
			global $wpdb;

			$term_data = $wpdb->get_results(
				"
				SELECT t.term_id, t.name
				FROM $wpdb->terms AS t
				INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id
				WHERE tt.taxonomy = 'anwp_league'
			",
				OBJECT_K
			); // phpcs:ignore WordPress.DB.PreparedSQL

			$term_data = array_map(
				function ( $term ) {
					return $term->name;
				},
				$term_data
			);
		}

		/*
		|--------------------------------------------------------------------
		| Save transient
		|--------------------------------------------------------------------
		*/
		if ( ! empty( $term_data ) ) {
			anwp_fl()->cache->set( $cache_key, $term_data );
		}

		return $term_data ?? [];
	}

	/**
	 * Helper function, returns leagues objects.
	 * Used in Vue multiselect
	 *
	 * @since 0.10.0
	 * @return array $output_data
	 */
	public function get_leagues_list() {

		static $output_data = null;

		if ( null === $output_data ) {

			$output_data = [];

			$all_leagues = get_terms(
				[
					'taxonomy'   => 'anwp_league',
					'hide_empty' => false,
					'orderby'    => 'name',
					'order'      => 'ASC',
				]
			);

			/** @var WP_Term $league */
			foreach ( $all_leagues as $league ) {

				$country_code   = get_term_meta( $league->term_id, '_anwpfl_country', true );
				$classification = get_term_meta( $league->term_id, '_anwpfl_classification', true );
				$priority       = get_term_meta( $league->term_id, '_anwpfl_priority', true );

				$output_data[] = (object) [
					'id'             => $league->term_id,
					'name'           => $league->name,
					'country_code'   => $country_code ?: '',
					'country'        => anwp_football_leagues()->data->get_value_by_key( $country_code, 'country' ),
					'classification' => $classification ?: '',
					'priority'       => $priority ?: 10,
				];
			}
		}

		return $output_data;
	}

	/**
	 * Get league Country code by league ID
	 *
	 * @param $league_id
	 *
	 * @since 0.13.0
	 * @return string
	 */
	public function get_league_country_code( $league_id ): string {

		static $output_data = null;

		if ( null === $output_data ) {
			global $wpdb;

			$codes = $wpdb->get_results(
				"
				SELECT term_id, meta_value
				FROM $wpdb->termmeta
				WHERE meta_key = '_anwpfl_country' AND meta_value != ''
				"
			);

			foreach ( $codes as $code ) {
				$output_data[ $code->term_id ] = $code->meta_value;
			}
		}

		return $output_data[ $league_id ] ?? '';
	}

	/**
	 * Get league classification by league ID.
	 *
	 * @param int $league_id
	 *
	 * @since 0.17.2
	 * @return string
	 */
	public function get_league_classification( $league_id ): string {

		return $this->get_all_league_classification()[ $league_id ] ?? '';
	}

	/**
	 * Get all league classifications.
	 *
	 * @since 0.17.2
	 * @return array
	 */
	public function get_all_league_classification(): array {

		static $output_data = null;

		if ( null === $output_data ) {
			global $wpdb;

			$output_data = [];

			$rows = $wpdb->get_results(
				"
				SELECT term_id, meta_value
				FROM $wpdb->termmeta
				WHERE meta_key = '_anwpfl_classification' AND meta_value != ''
				"
			);

			foreach ( $rows as $row ) {
				$output_data[ $row->term_id ] = $row->meta_value;
			}
		}

		return $output_data;
	}

	/**
	 * Get league priority by league ID.
	 *
	 * @param int $league_id
	 *
	 * @since 0.17.2
	 * @return int
	 */
	public function get_league_priority( $league_id ): int {

		$priority = $this->get_all_league_priority()[ $league_id ] ?? '';

		return '' === $priority ? 10 : (int) $priority;
	}

	/**
	 * Get all league priorities.
	 *
	 * @since 0.17.2
	 * @return array
	 */
	private function get_all_league_priority(): array {

		static $output_data = null;

		if ( null === $output_data ) {
			global $wpdb;

			$output_data = [];

			$rows = $wpdb->get_results(
				"
				SELECT term_id, meta_value
				FROM $wpdb->termmeta
				WHERE meta_key = '_anwpfl_priority' AND meta_value != ''
				"
			);

			foreach ( $rows as $row ) {
				$output_data[ $row->term_id ] = $row->meta_value;
			}
		}

		return $output_data;
	}

	/**
	 * Sort games by league priority.
	 *
	 * @param array $games
	 *
	 * @since 0.17.2
	 * @return array
	 */
	public function sort_games_by_league_priority( array $games ): array {

		if ( empty( $games ) ) {
			return $games;
		}

		foreach ( $games as $game_index => $game ) {
			$game->league_priority = $this->get_league_priority( $game->league_id );
			$game->pre_sort_index  = $game_index;
		}

		return wp_list_sort(
			$games,
			[
				'league_priority' => 'ASC',
				'pre_sort_index'  => 'ASC',
			]
		);
	}

	/**
	 * Generate a unique slug for a league.
	 *
	 * @param string $base_slug The base slug to generate a unique version from.
	 *
	 * @return string The generated unique slug.
	 */
	public function generate_unique_league_slug( string $base_slug ): string {
		$existing_slugs = get_terms(
			[
				'taxonomy'   => 'anwp_league',
				'fields'     => 'slugs',
				'hide_empty' => false,
			]
		);

		$base_slug = sanitize_title( $base_slug );

		// Use the list of slugs to perform a check
		if ( is_wp_error( $existing_slugs ) || empty( $existing_slugs ) || ! in_array( $base_slug, $existing_slugs, true ) ) {
			return $base_slug;
		}

		$slug_increment = 2;
		$current_slug   = $base_slug . '-' . $slug_increment;

		while ( in_array( $current_slug, $existing_slugs, true ) ) {
			++$slug_increment;
			$current_slug = $base_slug . '-' . $slug_increment;
		}

		return $current_slug;
	}
}
