<?php

/**
 * This class handles generations of href for links.
 *
 * @author       Time.ly Network, Inc.
 * @instantiator Ai1ec_Factory_Html.create_href_helper_instance
 * @since        2.0
 * @package      Ai1EC
 * @subpackage   Ai1EC.Html
 */
class Ai1ec_Html_Element_Href {

    /**
     * @var array the parameters that are used in the urls
     */
    private $used_paramaters = array(
        'action',
        'page_offset',
        'month_offset',
        'oneday_offset',
        'week_offset',
        'time_limit',
        'exact_date',
        'cat_ids',
        'auth_ids',
        'post_ids',
        'tag_ids',
        'instance_ids',
        'events_limit',
        'request_format',
        'no_navigation'
    );

    /**
     * @var boolean
     */
    private $is_category;

    /**
     * @var boolean
     */
    private $is_tag;

    /**
     * @var boolean
     */
    private $is_author;

    /**
     * @var boolean
     */
    private $is_custom_filter;

    /**
     * @var array the arguments to parse
     */
    private $args;

    /**
     * @var int
     */
    private $term_id;

    /**
     * @var string
     */
    private $calendar_page;

    /**
     * @var boolean
     */
    private $pretty_permalinks_enabled;

    /**
     * @var string
     */
    private $uri_particle = null;

    /**
     * @param boolean $pretty_permalinks_enabled
     */
    public function set_pretty_permalinks_enabled( $pretty_permalinks_enabled ) {
        $this->pretty_permalinks_enabled = $pretty_permalinks_enabled;
        if ( $pretty_permalinks_enabled ) {
            $this->calendar_page = trim( (string)$this->calendar_page, '/' )
                . '/';
        }
    }

    /**
     * @param number $term_id
     */
    public function set_term_id( $term_id ) {
        $this->term_id = $term_id;
    }

    public function __construct( array $args, $calendar ) {
        $this->args = $args;
        $this->calendar_page = $calendar;
        if ( isset( $args['_extra_used_parameters'] ) ) {
            $this->used_paramaters = array_merge(
                $this->used_paramaters,
                $args['_extra_used_parameters']
            );
        }
        $this->used_paramaters = array_merge(
            $this->used_paramaters,
            apply_filters(
                'ai1ec_view_args_for_view',
                array()
            )
        );
    }

    /**
     * @param boolean $is_category
     */
    public function set_is_category( $is_category ) {
        $this->is_category = $is_category;
    }

    /**
     * @param boolean $is_tag
     */
    public function set_is_tag( $is_tag ) {
        $this->is_tag = $is_tag;
    }

    /**
     * @param boolean $is_author
     */
    public function set_is_author( $is_author ) {
        $this->is_author = $is_author;
    }

    /**
     * Generate the correct href for the view.
     * This takes into account special filters for categories and tags
     *
     * @return string
     */
    public function generate_href() {
        $href = '';
        $to_implode = array();
        foreach ( $this->used_paramaters as $key ) {
            if ( ! empty( $this->args[$key] ) ) {
                $value = $this->args[$key];
                if( is_array( $this->args[$key] ) ) {
                    $value = implode( ',', $this->args[$key] );
                }
                $to_implode[$key] = $key . Ai1ec_Uri::DIRECTION_SEPARATOR .
                    $value;
            }
        }
        if (
            $this->is_category ||
            $this->is_tag ||
            $this->is_author ||
            $this->is_custom_filter
        ) {
            $to_implode = $this->add_or_remove_category_from_href(
                $to_implode
            );
        }
        if ( $this->pretty_permalinks_enabled ) {
            $href .= implode( '/', $to_implode );
            if ( ! empty( $href ) ) {
                $href .=  '/';
            }
        } else {
            $href .= $this->get_param_delimiter_char( $this->calendar_page );
            $href .= 'ai1ec=' . implode( '|', $to_implode );
        }
        $full_url = $this->calendar_page . $href;
        // persist the `lang` parameter if present
        if ( isset( $_REQUEST['lang'] ) ) {
            $full_url = esc_url_raw( add_query_arg( 'lang', $_REQUEST['lang'], $full_url ) );
        }
        return $full_url;
    }

    /**
     * Sets that class is used for custom filter.
     *
     * @param bool   $value        Expected true or false.
     * @param string $uri_particle URI particle identifier.
     *
     * @return void Method does not return.
     */
    public function set_custom_filter( $value, $uri_particle = null ) {
        $this->is_custom_filter = $value;
        $this->uri_particle     = $uri_particle;
    }

    /**
     * Perform some extra manipulation for filter href. Basically if the current
     * category is part of the filter, the href will not contain it (because
     * clicking on it will actually mean "remove that one from the filter")
     * otherwise it will be preserved.
     *
     * @param array $to_implode
     * @return array
     */
    private function add_or_remove_category_from_href( array $to_implode ) {
        $array_key = $this->uri_particle;
        if ( null === $this->uri_particle ) {
            $array_key = $this->_current_array_key();
        }
        // Let's copy the origina cat_ids or tag_ids so we do not affect it
        $copy      = array();
        if ( isset( $this->args[$array_key] ) ) {
            $copy  = (array)$this->args[$array_key];
        }
        $key       = array_search( $this->term_id, $copy );
        // Let's check if we are already filtering for tags / categorys
        if( isset( $to_implode[$array_key] ) ) {
            if( $key !== false ) {
                unset( $copy[$key] );
            } else {
                $copy[] = $this->term_id;
            }
            if( empty( $copy ) ) {
                unset( $to_implode[$array_key] );
            } else {
                $to_implode[$array_key] = $array_key . Ai1ec_Uri::DIRECTION_SEPARATOR .
                    implode( ',', $copy );
            }
        } else {
            $to_implode[$array_key] = $array_key . Ai1ec_Uri::DIRECTION_SEPARATOR . $this->term_id;
        }
        return $to_implode;
    }

    /**
     * Match current argument key
     *
     * @return string Name of current argument key
     */
    protected function _current_array_key() {
        $map = array(
            'category' => 'cat',
            'tag'      => 'tag',
            'author'   => 'auth',
        );
        $use_name = '';
        foreach ( $map as $value => $name ) {
            if ( $this->{'is_' . $value} ) {
                $use_name = $name;
                break;
            }
        }
        return $use_name . '_ids';
    }

    /**
     * Returns the delimiter character to use if a new query string parameter is
     * going to be appended to the URL.
     *
     * @param string $url URL to parse
     *
     * @return string
     */
    public static function get_param_delimiter_char( $url ) {
        return strpos( $url, '?' ) === false ? '?' : '&';
    }

}
