<?php

/**
 * Model used for storing/retrieving taxonomy.
 *
 * @author     Time.ly Network, Inc.
 * @since      2.0
 * @package    Ai1EC
 * @subpackage Ai1EC.Html
 */
class Ai1ec_Taxonomy extends Ai1ec_Base {

    /**
     * @var array Map of taxonomy values.
     */
    protected $_taxonomy_map = array(
        'events_categories' => array(),
        'events_tags' => array(),
    );

    /**
     * Callback to pre-populate taxonomies before exporting ics.
     * All taxonomies which are not tags are exported as event_categories
     *
     * @param array $post_ids List of Post IDs to inspect.
     *
     * @return void
     */
    public function prepare_meta_for_ics( array $post_ids ) {
        $taxonomies = get_object_taxonomies( AI1EC_POST_TYPE );
        $categories = array();
        $excluded_categories = array(
            'events_tags'  => true,
            'events_feeds' => true
        );
        foreach ( $taxonomies as $taxonomy ) {
            if ( isset( $excluded_categories[$taxonomy] ) ) {
                continue;
            }
            $categories[] = $taxonomy;
        }
        foreach ( $post_ids as $post_id ) {
            $post_id = (int)$post_id;
            $this->_taxonomy_map['events_categories'][$post_id] = array();
            $this->_taxonomy_map['events_tags'][$post_id] = array();
        }
        $tags = wp_get_object_terms(
            $post_ids,
            array( 'events_tags' ),
            array( 'fields' => 'all_with_object_id' )
        );
        foreach ( $tags as $term ) {
            $this->_taxonomy_map[$term->taxonomy][$term->object_id][] = $term;
        }
        $category_terms = wp_get_object_terms(
            $post_ids,
            $categories,
            array( 'fields' => 'all_with_object_id' )
        );
        foreach ( $category_terms as $term ) {
            $this->_taxonomy_map['events_categories'][$term->object_id][] = $term;
        }
    }

    /**
     * Callback to pre-populate taxonomies before processing.
     *
     * @param array $post_ids List of Post IDs to inspect.
     *
     * @return void
     */
    public function update_meta( array $post_ids ) {
        foreach ( $post_ids as $post_id ) {
            $post_id = (int)$post_id;
            $this->_taxonomy_map['events_categories'][$post_id] = array();
            $this->_taxonomy_map['events_tags'][$post_id] = array();
        }
        $terms = wp_get_object_terms(
            $post_ids,
            array( 'events_categories', 'events_tags' ),
            array( 'fields' => 'all_with_object_id' )
        );
        foreach ( $terms as $term ) {
            $this->_taxonomy_map[$term->taxonomy][$term->object_id][] = $term;
        }
    }

    /**
     * Re-fetch category entries map from database.
     *
     * @return array Map of category entries.
     */
    public function fetch_category_map() {
        $category_map = array();
        $records      = (array)$this->_registry->get( 'dbi.dbi' )->select(
            'ai1ec_event_category_meta',
            array( 'term_id', 'term_image', 'term_color' )
        );
        foreach ( $records as $row ) {
            $image = $color = null;
            if ( $row->term_image ) {
                $image = $row->term_image;
            }
            if ( $row->term_color ) {
                $color = $row->term_color;
            }
            $category_map[(int)$row->term_id] = compact( 'image', 'color' );
        }
        return $category_map;
    }

    /**
     * Get taxonomy values for specified post.
     *
     * @param int    $post_id  Actual Post ID to check.
     * @param string $taxonomy Name of taxonomy to retrieve values for.
     *
     * @return array List of terms (stdClass'es) associated with post.
     */
    public function get_post_taxonomy( $post_id, $taxonomy ) {
        $post_id = (int)$post_id;
        if ( ! isset( $this->_taxonomy_map[$taxonomy][$post_id] ) ) {
            $definition = wp_get_post_terms( $post_id, $taxonomy );
            if ( empty( $definition ) || is_wp_error( $definition ) ) {
                $definition = array();
            }
            $this->_taxonomy_map[$taxonomy][$post_id] = $definition;
        }
        return $this->_taxonomy_map[$taxonomy][$post_id];
    }

    /**
     * Get post (event) categories taxonomy.
     *
     * @param int $post_id Checked post ID.
     *
     * @return array List of categories (stdClass'es) associated with event.
     */
    public function get_post_categories( $post_id ) {
        return $this->get_post_taxonomy( $post_id, 'events_categories' );
    }

    /**
     * Get post (event) tags taxonomy.
     *
     * @param int $post_id Checked post ID.
     *
     * @return array List of tags (stdClass'es) associated with event.
     */
    public function get_post_tags( $post_id ) {
        return $this->get_post_taxonomy( $post_id, 'events_tags' );
    }

    /**
     * Get cached category description field.
     *
     * @param int    $term_id Category ID.
     * @param string $field   Name of field, one of 'image', 'color'.
     *
     * @return string|null Field value or null if entry is not found.
     */
    public function get_category_field( $term_id, $field ) {
        static $category_meta = null;
        if ( null === $category_meta ) {
            $category_meta = $this->fetch_category_map();
        }
        $term_id = (int)$term_id;
        if ( ! isset( $category_meta[$term_id] ) ) {
            return null;
        }
        return $category_meta[$term_id][$field];
    }

    /**
     * Returns the color of the Event Category having the given term ID.
     *
     * @param int $term_id The ID of the Event Category.
     *
     * @return string|null Color to use
     */
    public function get_category_color( $term_id ) {
        return $this->get_category_field( $term_id, 'color' );
    }

    /**
     * Returns the image of the Event Category having the given term ID.
     *
     * @param int $term_id The ID of the Event Category.
     *
     * @return string|null Image url to use.
     */
    public function get_category_image( $term_id ) {
        return $this->get_category_field( $term_id, 'image' );
    }

}