<?php
/**
 * Simple class for converting simple schema arrays
 * into proper VTCore CSSBuilder arrays. This class
 * will also bundle all css builder together in a
 * single array and build the final css output.
 *
 * This is a temporary class for easily building dynamic
 * css rules that can be altered or changed by user
 * via theme options or customizer. This will be deprecated
 * in the future when a proper class is created.
 *
 * @todo clean this mess up and create proper class for this.
 * @author jason.xie@victheme.com
 *
 */
class VTCore_Zeus_Schema_Color {

  private $schemaData = array();
  private $schema = array();
  private $directconvert = array(
    'background-color',
    'background-gradient',
    'background-image',
    'background-repeat',
    'background-size',
    'background-attachment',
    'background-position',
    'font-color',
    'font-family',
    'font-size',
    'font-style',
    'font-weight',
    'font-variant',
    'font-stretch',
    'border-width',
    'border-style',
    'border-color',
    'border-radius',
  );


  private $linkconvert = array(
    'link-color',
    'link-hover',
    'link-focus',
    'link-visited',
  );

  private $removelink = array(
    'link-border-color',
  );


  private $headingconvert = array(
    'heading-color',
    'heading-family',
    'heading-style',
    'heading-variant',
    'heading-stretch',
    'heading-weight',
    'heading-size',
  );


  private $key;
  private $ruleKey;
  private $arrayKey;
  private $additional;
  private $merge;
  private $clean;
  private $forceNotEmpty;

  private $context = array();


  /**
   * Constructing the css processor object
   * by assigning the context and options
   * to the object variable
   */
  public function __construct($schema, $merge = true, $clean = true, $force = false) {
    $this->schemaData = $schema;
    $this->merge = $merge;
    $this->clean = $clean;
    $this->forceNotEmpty = $force;

    $this->buildContext();
    $this->buildObject();
  }


  /**
   * Preprocess the given context by exploding
   * the shorthand rulekey and shorthand selectors
   * to the proper css selector and cssbuilder
   * object rulekey
   */
  private function buildContext() {
    foreach ($this->schemaData as $key => $rules) {

      if (!isset($rules['selectors'])) {
        continue;
      }

      $selectors = $rules['selectors'];

      // Clean out empty rules and not needed rules
      // to speed up the loop process
      unset($rules['selectors']);
      unset($rules['title']);
      unset($rules['description']);

      $this->key = $key;

      if ($this->clean) {
        $rules = array_filter($rules);
      }

      foreach ($rules as $rulekey => $value) {

        if ($this->clean == true && empty($value)) {
          continue;
        }

        // Force give dummy empty value
        // This is a crude hack to overcome the
        // CSSBuilder factory wont build proper
        // rules on empty rules as needed by customizer
        if ($this->forceNotEmpty == true && empty($value)) {
          $value = '__i__';
        }

        $this->selectors = $selectors;
        $this->arrayKey = array($key);
        $this->ruleKey = $rulekey;
        $this->additional = '';
        $this->processAdditional();
        $this->processArrayKey();
        $this->processRuleKey();

        if (!isset($this->context[$this->arrayKey]['rules'])) {
          $this->context[$this->arrayKey]['rules'] = array();
        }

        if (strpos($this->ruleKey, 'font-family') !== false) {
          $value = '"' . str_replace('+', ' ', $value) . '"';
        }

        // Simple explode convertion
        if (in_array($this->ruleKey, $this->directconvert)) {

          if ($this->ruleKey == 'background-image' && is_numeric($value)) {
            $image = wp_get_attachment_image_src($value, 'full');
            if (is_array($image)) {
              $value = array_shift($image);
            }
          }

          list($type, $rule) = explode('-', $this->ruleKey);
          $this->context[$this->arrayKey]['rules'][$type][$rule] = $value;
        }


        // Converting link rules
        if (in_array($this->ruleKey, $this->linkconvert)) {
          list($type, $rule) = explode('-', $this->ruleKey);
          $this->context[$this->arrayKey]['rules']['font']['color'] = $value;
        }

        // Converting heading element
        if (in_array($this->ruleKey, $this->headingconvert)) {
          $newselector = array();
          foreach ($this->selectors as $id => $selector) {
            foreach (array('h1', 'h2', 'h3', 'h4', 'h5', 'h6') as $element) {
              $newselector[] = $selector . ' ' . $element;
            }
          }

          $this->selectors = $newselector;
          list($type, $rule) = explode('-', $this->ruleKey);
          $this->context[$this->arrayKey]['rules']['font'][$rule] = $value;
        }


        // Force rebuild the selector
        foreach ($this->selectors as $id => $selector) {
          $this->context[$this->arrayKey]['selectors'][$id] = $selector . $this->additional;
        }

      }
    }
  }




  /**
   * Build the CSSBuilder object based on the
   * preprocessed rules and rulekey
   *
   * @return VTCore_Zeus_Schema_Color
   */
  private function buildObject() {
    foreach ($this->context as $key => $rule) {
      $this->schema[$key] = new VTCore_CSSBuilder_Factory();
      $this->schema[$key]->buildStyles($rule);

      if (defined('WP_DEBUG') && WP_DEBUG == false) {
        $this->schema[$key]->setMinify(true);
      }
    }

    return $this;
  }





  /**
   * Explode the shorthand array key to build the proper
   * css valid selector
   *
   * @return VTCore_Zeus_Schema_Color
   */
  private function processArrayKey() {
    // Preprocessing additional string for selectors
    if (strpos($this->ruleKey, 'link') !== false) {
      $key = $this->ruleKey;
      foreach ($this->directconvert as $direct) {
        if (strpos($this->ruleKey, $direct) !== false) {
          $this->ruleKey = str_replace('link-', '', $this->ruleKey);
        }
      }

      if ($this->merge == true) {
        $this->arrayKey[] = $this->ruleKey;
      }
      else {
        $this->arrayKey[] = $key;
      }
    }
    elseif (strpos($this->ruleKey, 'after') !== false) {
      $this->arrayKey[] = $this->ruleKey;
      $this->ruleKey = str_replace('after-', '', $this->ruleKey);
    }
    elseif (strpos($this->ruleKey, 'before') !== false) {
      $this->arrayKey[] = $this->ruleKey;
      $this->ruleKey = str_replace('before-', '', $this->ruleKey);
    }
    elseif (strpos($this->ruleKey, 'focus') !== false) {
      $this->arrayKey[] = $this->ruleKey;
      $this->ruleKey = str_replace('focus-', '', $this->ruleKey);
    }
    elseif (strpos($this->ruleKey, 'visited') !== false) {
      $this->arrayKey[] = $this->ruleKey;
      $this->ruleKey = str_replace('visited-', '', $this->ruleKey);
    }
    elseif (strpos($this->ruleKey, 'hover') !== false) {
      $this->arrayKey[] = $this->ruleKey;
      $this->ruleKey = str_replace('hover-', '', $this->ruleKey);
    }
    elseif (strpos($this->ruleKey, 'active') !== false) {
      $this->arrayKey[] = $this->ruleKey;
      $this->ruleKey = str_replace('hover-', '', $this->ruleKey);
    }
    elseif (strpos($this->ruleKey, 'icon') !== false) {
      $this->arrayKey[] = $this->ruleKey;
      $this->ruleKey = str_replace('hover-', '', $this->ruleKey);
    }
    elseif (strpos($this->ruleKey, 'heading') !== false) {
      $this->arrayKey[] = $this->ruleKey;
    }
    elseif ($this->merge == false) {
      $this->arrayKey[] = $this->ruleKey;
    }

    $this->arrayKey = implode('--', array_unique($this->arrayKey));

    return $this;
  }





  /**
   * Convert the shorthand rule keys to proper
   * rule key required by the CSSBuilder object
   *
   * @return VTCore_Zeus_Schema_Color
   */
  private function processRuleKey() {

      // Preprocessing additional string for selectors
    if (strpos($this->ruleKey, 'link') !== false) {
      foreach ($this->directconvert as $direct) {
        if (strpos($this->ruleKey, $direct) !== false) {
          $this->ruleKey = str_replace('link-', '', $this->ruleKey);
        }
      }
    }


    if (strpos($this->ruleKey, 'after') !== false) {
      $this->ruleKey = str_replace('after-', '', $this->ruleKey);
    }

    if (strpos($this->ruleKey, 'before') !== false) {
      $this->ruleKey = str_replace('before-', '', $this->ruleKey);
    }

    if (strpos($this->ruleKey, 'focus') !== false) {
      $this->ruleKey = str_replace('focus-', '', $this->ruleKey);
    }

    if (strpos($this->ruleKey, 'visited') !== false) {
      $this->ruleKey = str_replace('visited-', '', $this->ruleKey);
    }

    if (strpos($this->ruleKey, 'hover') !== false) {
      $this->ruleKey = str_replace('hover-', '', $this->ruleKey);
    }

    if (strpos($this->ruleKey, 'active') !== false) {
      $this->ruleKey = str_replace('active-', '', $this->ruleKey);
    }

    if (strpos($this->ruleKey, 'icon') !== false) {
      $this->ruleKey = str_replace('icon-', '', $this->ruleKey);
    }

    return $this;
  }




  /**
   * Process the magic shorthand key
   * @return VTCore_Zeus_Schema_Color
   */
  private function processAdditional() {
    // Preprocessing additional string for selectors
    if (strpos($this->ruleKey, 'link') !== false) {
      $this->additional .= ' a';
    }

    if (strpos($this->ruleKey, 'after') !== false) {
      $this->additional .= ':after';
    }

    if (strpos($this->ruleKey, 'before') !== false) {
      $this->additional .= ':before';
    }

    if (strpos($this->ruleKey, 'focus') !== false) {
      $this->additional .= ':focus';
    }

    if (strpos($this->ruleKey, 'visited') !== false) {
      $this->additional .= ':visited';
    }

    if (strpos($this->ruleKey, 'hover') !== false) {
      $this->additional .= ':hover';
    }

    if (strpos($this->ruleKey, 'active') !== false) {
      $this->additional .= '.active';
    }

    if (strpos($this->ruleKey, 'icon') !== false) {
      $this->additional .= ' i';
    }

    return $this;
  }



  /**
   * Retrieves the css string
   * @return string
   */
  public function getCSS() {
    $css = '';
    foreach ($this->schema as $object) {
      $css .= $object->__toString();
    }
    return $css;
  }



  /**
   * Retrieves the schema arrays
   *
   * @param string $key
   * @return multitype:
   */
  public function getSchema($key) {
    return $this->schema[$key];
  }
}