<?php
/**
 * Utility class for all singleton static methods
 * This is needed for building template easily
 * without initializing pletora of classes.
 *
 * @todo Trim down some of the methods so we dont
 *       ended up in gazzilion of static methods.
 *
 * @author jason.xie@victheme.com
 *
 */
class VTCore_Zeus_Utility
extends VTCore_Wordpress_Utility {


  /**
   * Calculating the approx size of the content region.
   * The calculated results is not perfect for all page sizes such as
   * for the responsive layouts and should only be used for handling
   * the wordpress $content_width feature.
   */
  static public function calculateApproxContentWidth($contentWidth) {

    $pagewidth = str_replace('max-', '', VTCore_Zeus_Utility::getOption('page', 'maxwidth'));
    if ($pagewidth != 'fluid') {
      $region = self::getRegion('content');
      $grid = $region->getContext('grids');
      $column = $grid['columns']['small'];
      $contentWidth = ($pagewidth / 12) * $column;
    }

    return esc_attr($contentWidth);
  }




  /**
   * Retrieving area object by its machine id
   * @see VTCore_Zeus_Layout_Factory
   */
  static public function getArea($area) {
    $layout = VTCore_Zeus_Init::getLayout();
    $areas = $layout->findChildren('id', 'area-' . $area);
    return array_shift($areas);
  }




  /**
   * Retrieving region object by its machine id.
   * @see VTCore_Zeus_Layout_Factory
   */
  static public function getRegion($region) {
    $layout = VTCore_Zeus_Init::getLayout();
    $regions = $layout->findChildren('id', 'region-' . $region);
    return array_shift($regions);
  }





  /**
   * Building the bootstrap grid column class
   * taken from the region object.
   * @see VTCore_Zeus_Layout_Factory
   */
  static public function getColumnSize($region) {
    $object = self::getRegion($region);
    $objectClass = 'region-' . $object->getArgument('id') . ' ';
    $objectClass .= is_object($object) ? $object->getGrid()->getClass() : 'col-xs-12 col-sm-12 col-md-12 col-lg-12';
    return esc_attr($objectClass);
  }




  /**
   * Retrieving grid size for specific region
   * and viewport
   */
  static public function getRegionColumn($region, $size) {
    $region = self::getRegion($region);
    $grids = $region->getContext('grids');
    return isset($grids['columns'][$size]) ? esc_attr($grids['columns'][$size]) : false;
  }





  /**
   * Retrieving sidebar configuration per user settings
   * @see VTCore_Zeus_Features
   */
  static public function getSidebar($page) {
    $sidebar = VTCore_Zeus_Init::getFeatures()->getFeature('sidebars');
    $output = isset($sidebar[$page]) ? $sidebar[$page] : $sidebar['full'];

    if ($output ==  'none') {
      $output = false;
    }

    return esc_attr($output);
  }





  /**
   * Get the user configuration for showing / hiding elements
   * per page and key.
   * @see VTCore_Zeus_Features
   */
  static public function getShow($page, $key) {
    $show = VTCore_Zeus_Init::getFeatures()->getFeature('show', 'attr');
    return isset($show[$page][$key]) ? $show[$page][$key] : false;
  }





  /**
   * Retrieving features options
   * @see VTCore_Zeus_Features
   */
  static public function getOption($page, $key) {
    $option = VTCore_Zeus_Init::getFeatures()->getFeature('options', 'attr');
    return isset($option[$page][$key]) ? $option[$page][$key] : false;
  }





  /**
   * Retrieving features options
   * @see VTCore_Zeus_Features
   */
  static public function getImage($size, $key) {
    $option = VTCore_Zeus_Init::getFeatures()->getFeature('images', 'attr');
    return isset($option[$size][$key]) ? $option[$size][$key] : false;
  }




  /**
   * Checking if the sidebar actually has widget or not.
   * @see VTCore_Zeus_Layout_Regions
   */
  static public function isActiveSidebar($region) {
    $object = self::getRegion($region);
    $active = is_object($object) ? $object->isActive() : false;
    return apply_filters('is_active_sidebar', $active, $region);
  }





  /**
   * Retrieving dynamic css from schema
   * @see VTCore_Zeus_Schema_Factory
   */
  static public function getSchemaCSS() {
    return VTCore_Zeus_Init::getSchema()->getCSS();
  }




  /**
   * Retrieving dynamic css from schema
   * @see VTCore_Zeus_Schema_Factory
   */
  static public function getActiveSchema() {
    return VTCore_Zeus_Init::getSchema()->getActiveSchemaID();
  }




  /**
   * Loading Google fonts from schema via wp_enqueue_scripts
   * @see VTCore_Zeus_Schema_Factory
   */
  static public function loadGoogleFonts() {
    return VTCore_Zeus_Init::getSchema()->loadGoogleFont();
  }






  /**
   * Retrieving logo from schemas, the schemas will
   * handle the merging between default schema values
   * and user configured value.
   */
  static public function getLogo() {
    $logo = VTCore_Zeus_Init::getFeatures()->get('options.logo', 'post');

    if (isset($logo['image']) && is_numeric($logo['image'])) {
      list($image, $width, $height) = wp_get_attachment_image_src($logo['image'], 'logo');
      $logo['image'] = $image;
    }

    return $logo;
  }





  /**
   * Retrieving favicon from features and convert the
   * favicon to correct image url.
   */
  static public function getFavicon() {
    $favicon = VTCore_Zeus_Init::getFeatures()->get('options.favicon.image', 'url');

    if (is_numeric($favicon)) {
      list($image, $width, $height) = wp_get_attachment_image_src($favicon, 'full');
      $favicon = $image;
    }

    return $favicon;
  }




  /**
   * Retrieving footer configuration
   */
  static public function getFooter($key) {
    $footer = VTCore_Zeus_Init::getFeatures()->get('options.footer', 'post');

    if (isset($footer['image']) && is_numeric($footer['image'])) {
      $images = wp_get_attachment_image_src($footer['image']);
      $footer['image'] = $images[0];
    }

    return $footer[$key];
  }






  /**
   * Helper function for quickly building a WordPress Pager elements
   * that is safe to use with multiple pager in the same page.
   *
   * This function also offers feature to build a minified pager which
   * only display previous and next link.
   *
   * @param object $wp_query
   * @param boolean / array $mini
   * @param number $id
   * @return false or pagination HTML
   */
  static public function getPager($wp_query = FALSE, $mini = FALSE, $id = 1) {

    if (!$wp_query) {
      global $wp_query;
    }

    $get = filter_input_array(INPUT_GET, FILTER_SANITIZE_SPECIAL_CHARS);
    unset($get['paged_' . $id]);

    $prev = '&laquo';
    $next = '&raquo';
    $max = 0;

    if ($mini) {

      $next = '<i class="color fa fa-angle-right"></i>';
      $prev = '<i class="color fa fa-angle-left"></i>';

      if (is_array($mini) && isset($mini['next']) && isset($mini['prev'])) {
        extract($mini);
      }

      $max = 1;
    }

    global $wp_rewrite;

    $big = 999999999;
    $link = html_entity_decode(get_pagenum_link($big));
    $link = trim(remove_query_arg('paged_' . $id, $link));

    if (!$wp_rewrite->using_permalinks() || is_admin()) {
      $base_url = str_replace('paged=', 'paged_' . $id .'=', $link);
    }
    else {
      // Somehow str_replace() will screw things up if we
      // replace the string in a single line due to backslash
      // this is happens only on linux system.
      $base_url = str_replace('/page/', '/?paged_' . $id . '=', $link);
      $base_url = str_replace($big . '/', $big, $base_url);
    }


    $show_all = false;
    if ($wp_query->max_num_pages < 10 ) {
      $show_all = true;
    }

    $args = array(
      'base'         => str_replace($big, '%#%', $base_url),
      'format'       => '?paged_' . $id . '=%#%',
      'total'        => $wp_query->max_num_pages,
      'current'      => max($max, $wp_query->query_vars['paged']),
      'show_all'     => $show_all,
      'prev_next'    => true,
      'prev_text'    => $prev,
      'next_text'    => $next,
      'end_size'     => '4',
      'type'         => 'list',
      'add_args'     => empty($get) ? false : array_unique($get),
      'add_fragment' => false,
    );

    // Support for woocommerce
    $args = apply_filters('woocommerce_pagination_args', $args);

    $pager = paginate_links($args);

    if ($mini && !empty($pager)) {
      $dom = new DOMDocument();
      libxml_use_internal_errors(true);
      $dom->preserveWhiteSpace = false;
      $dom->formatOutput       = true;
      $dom->loadHTML($pager);
      libxml_clear_errors();
      $dom->removeChild($dom->firstChild);

      $remove = array();
      foreach ($dom->getElementsByTagName('li') as $key => $item) {
        foreach ($item->childNodes as $childkey => $child) {
          $class = $child->getAttribute('class');
          $class = array_flip(explode(' ', $class));
          if (isset($class['page-numbers'])) {
            if (isset($class['next']) || isset($class['prev'])) {
              continue;
            }

            $remove[] = $item;
            break;
          }
        }
      }

      // @note dont remove element in the main loop will cause strange output
      foreach ($remove as $item) {
        $item->parentNode->removeChild($item);
      }

      foreach ($dom->getElementsByTagName('ul') as $key => $item) {
        $class = $item->getAttribute('class');
        $item->setAttribute('class', $class . ' pager-mini');
      }

      $pager = str_replace(array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $dom->saveHTML());
    }

    return $pager;
  }










  /**
   * Build page pagination links
   */
  static public function getPostPager() {

    $args = array(
      'before' => __('Pages', BASE_THEME) . ' : ',
      'after' => '',
      'nextpagelink' => '<span class="next">' . __('Next Page', BASE_THEME) . '</span>',
      'previouspagelink' => '<span class="previous">' . __('Previous Page', BASE_THEME) . '</span>',
      'pagelink' => '<span>%</span>',
      'echo' => false,
    );

    return wp_link_pages($args);
  }








  /**
   * Invoking custom comment form
   */
  static public function getCommentForm($args) {
    $defaults = array(
      'id_submit' => 'bootstrap-comment-button',
      'title_reply' => ' ',
    );

    $args = wp_parse_args($args, $defaults);

    comment_form($args);
  }







  /**
   * Invoking custom comment template
   */
  static public function getComment($comment, $args, $depth) {
    wp_enqueue_script('comment-reply');
    include(locate_template('templates/comments/comment.php'));
  }




  /**
   * Helper function for retrieving post via WP_Query object
   *
   * - Pagination friendly, as long as pager utilizes default paged query
   */
  static public function getPosts($args = FALSE) {
    if (!$args) {
      $args = array(
        'post_type' => 'post',
        'post_per_page' => get_option('posts_per_page'),
      );
    }

    return new WP_Query($args);
  }






  /**
   * Build list of taxonomy slugs from post object
   */
  public static function buildSlug($post) {
    $type = $post->post_type;

    if ($type != 'post') {
      $taxonomies = get_object_taxonomies($type);
    }
    else {
      $taxonomies = array('category');
    }

    $slug = array();
    foreach ($taxonomies as $taxonomy) {
      foreach (wp_get_post_terms($post->ID, $taxonomy) as $term) {
        $slug[] = $term->slug;
      }
    }

    return $slug;
  }



  /**
   * Determine if we should inverse the element
   * color based on give color or not
   *
   * @param $hexcolor
   * @return string
   */
  public static function getContrastYIQ($hexcolor){

    $r = hexdec(substr($hexcolor,0,2));
    $g = hexdec(substr($hexcolor,2,2));
    $b = hexdec(substr($hexcolor,4,2));
    $yiq = (($r*299)+($g*587)+($b*114))/1000;

    return ($yiq >= 128) ? 'inversed' : 'normal';
  }




  /**
   * A shortcut for easily retrieving active schema color value
   */
  public static function getActiveSchemaColorValue($key, $search) {
    return VTCore_Zeus_Init::getSchema()->getActiveSchema()->getColorValue($key, $search);
  }


  /**
   * Format time to "ago"
   */
  public static function relativeDate($secs) {

    $second = 1;
    $minute = 60;
    $hour = 60*60;
    $day = 60*60*24;
    $week = 60*60*24*7;
    $month = 60*60*24*7*30;
    $year = 60*60*24*7*30*365;

    $output = '';
    $secs = time() - $secs;

    if ($secs <= 0) {
      $output = "now";
    }

    elseif ($secs > $second && $secs < $minute) {
      $output = round($secs/$second) . ' ' . __('second', BASE_THEME);
    }

    elseif ($secs >= $minute && $secs < $hour) {
      $output = round($secs/$minute) . ' ' . __('minute', BASE_THEME);
    }

    elseif ($secs >= $hour && $secs < $day) {
      $output = round($secs/$hour) . ' ' . __('hour', BASE_THEME);
    }

    elseif ($secs >= $day && $secs < $week) {
      $output = round($secs/$day) . ' ' . __('day', BASE_THEME);
    }

    elseif ($secs >= $week && $secs < $month) {
      $output = round($secs/$week) . ' ' . __('week', BASE_THEME);
    }

    elseif ($secs >= $month && $secs < $year) {
      $output = round($secs/$month) . ' ' . __('month', BASE_THEME);
    }

    elseif ($secs >= $year && $secs < $year*10) {
      $output = round($secs/$year) . ' ' . __('year', BASE_THEME);
    }

    else {
      $output = ' ' . __('more than a decade', BASE_THEME);
    }

    if ($output <> "now"){
      $output = (substr($output,0,2) <> "1 ") ? $output . "s" : $output;
      $output .= ' ' . __('ago', BASE_THEME);
    }

    return $output;
  }
}