<?php
/**
 * Factory class for building the proper Layout
 * object using VTCore rules
 *
 * @author jason.xie@victheme.com
 *
 */
class VTCore_Wordpress_Factory_Layout
extends VTCore_Bootstrap_Element_BsElement
implements VTCore_Wordpress_Interfaces_Factory {

  protected $context = array(
    'type' => 'div',
    'attributes' => array(
      'id' => 'page',
    ),
    'areas' => array(),
    'regions' => array(),
    'blocks' => array(),
  );


  /**
   * Overriding parent method.
   * Building the layout structures
   */
  public function buildElement() {

    // Check if we should bypass cache
    $this->maybeByPassCache();

    // Load cache
    $this->loadCache();

    if ($this->getChildrens() == array()) {

      // Building the areas
      foreach ($this->getContext('areas') as $name => $context) {
        $object = new VTCore_Wordpress_Layout_Area($context);
        $object->setMachineID('area-' . $name);
        $this->addChildren($object);
        unset($object);
      }


      // Building the Regions and inject to its parent areas
      foreach ($this->getContext('regions') as $name => $context) {
        $object = new VTCore_Wordpress_Layout_Region($context);
        $object->addContext('regionId', $name);
        $object->setMachineID('region-' . $name);
        $parents = $this->findChildren('id', 'area-' . $object->getContext('parent'));

        foreach ($parents as $parent) {
          $parent->addChildren($object);
        }
        unset($object);
      }


      // Building the Blocks and inject it to the parent Regions
      foreach ($this->getContext('blocks') as $name => $context) {
        $name = 'VTCore_Wordpress_Layout_Blocks';
        if (class_exists($context['object'], true)) {
          $name = $context['object'];
        }
        $object = new $name($context);

        $parents = $this->findChildren('id', 'region-' . $object->getContext('parent'));

        foreach ($parents as $parent) {
          $parent->addChildren($object);
        }
        unset($object);
      }


      $this->sortElements();

      set_transient('vtcore_layout_cache', $this->getChildrens(), 12 * HOUR_IN_SECONDS);
    }

  }



  /**
   * Method for checking if class should bypass cache
   * @return VTCore_Wordpress_Factory_Layout
   */
  public function maybeByPassCache() {
    // Wordpress on debug mode
    if ((defined('WP_DEBUG') && WP_DEBUG)
        || (defined('VTCORE_CLEAR_CACHE') && VTCORE_CLEAR_CACHE)) {

      $this->clearCache();
    }

    return $this;
  }


  /**
   * Method for loading from cache
   * @return VTCore_Wordpress_Factory_Layout
   */
  public function loadCache() {
    $children = get_transient('vtcore_layout_cache');

    if (!empty($children)) {
      $this->setChildren($children);
    }

    return $this;
  }


  /**
   * Method for clearing cached elements
   * @return VTCore_Wordpress_Factory_Layout
   */
  public function clearCache() {
    delete_transient('vtcore_layout_cache');
    return $this;
  }




  /**
   * Sorting elements based on it weight context
   * @return VTCore_Wordpress_Factory_Layout
   */
  private function sortElements() {

    $areas = $this->getChildrens();

    // Sorting regions, and blocks.
    foreach ($areas as $area) {

      $regions = $area->getChildrens();

      foreach ($regions as $region) {
        $blocks = $region->getChildrens();

        if (!empty($blocks)) {
          // Sorting blocks
          uasort($blocks, array($this, 'sortByWeight'));
          $region->setChildren($blocks);
        }
        unset($blocks);
      }

      // Sorting Regions
      if (!empty($regions)) {
        uasort($regions, array($this, 'sortByWeight'));
        $area->setChildren($regions);
        unset($regions);
      }
    }

    // Sorting Areas
    uasort($areas, array($this, 'sortByWeight'));
    $this->setChildren($areas);
    unset($areas);



    return $this;
  }




  /**
   * Helper function for comparing weight value between
   * a and b
   * @return number
   */
  private function sortByWeight($a, $b) {
    return $a->getContext('weight') > $b->getContext('weight') ? 1 : -1;
  }

}