<?php

class MEOW_Post extends WOOF_Post { 

  protected $field_data;
  protected $incoming;
	
	public function set($name) {
    global $wf;
    return $wf->set($name, $this, "post");
  }
  
  public function field($name, $set_index = 1) {
    global $wf;
    return $wf->field($name, $set_index, $this);
  }
  
  public function s($name) {
    return $this->set($name);
  }
  
  public function f($name, $set_index = 1) {
    return $this->field($name, $set_index);
  }
  
  public function blank() {
    return $this->id == -1;
  }
  
  
  public function posts($r = array()) {
    
    global $wf;
    
    $r = wp_parse_args($r, array());
    
    $r["meta_query"] = array(
      array(
        "key" => "_mp_master",
        "value" => $this->id()
      )
    );

    return $wf->posts($r);

  }
  

  public function incoming($args = array()) {
    global $meow_provider, $wf;
      
    $this->switch_site();
    
    $post_ids = $meow_provider->incoming($this, WOOF::array_arg($args, "for"));
    
    $this->incoming = array();

    if (count($post_ids)) {
      // if there are no matching post ids, don't query, return an empty array
    
      $defaults = array(
        "post_type" => "any",
        "nopaging" => true,
        "posts_per_page" => -1
      );
  
      $r = wp_parse_args( $args, $defaults );
      $r = array_merge( $r , array("post__in" => $post_ids));
    
      $ret = $wf->posts($r);
  
    } else {
      $ret = new WOOF_Collection( array() );
    }
    
    $this->restore_site();
    
    return $ret;
    
  }
  
  public function incoming_terms($taxonomy, $args = array()) {
    global $meow_provider, $wf;
      
    $this->switch_site();
    
    $term_ids = $meow_provider->incoming($this, WOOF::array_arg($args, "for"), "term");
    
    $this->incoming = array();

    if (count($term_ids)) {
      // if there are no matching term ids, don't query, return an empty array
    
      $defaults = array(
        
      );
  
      $r = wp_parse_args( $args, $defaults );
      $r = array_merge( $r , array("include" => $term_ids));
    
      $ret = $wf->terms( $taxonomy, $r );
  
    } else {
      $ret = new WOOF_Collection( array() );
    }
    
    $this->restore_site();
    
    return $ret;
    
  }


  public function incoming_users($args = array()) {
    
    global $meow_provider, $wf;
    
    $this->switch_site();
    
    $user_ids = $meow_provider->incoming($this, WOOF::array_arg($args, "for"), "user");
    
    $this->incoming = array();

    if (count($user_ids)) {
      // if there are no matching user ids, don't query, return an empty array
    
      $defaults = array(
        
      );
  
      $r = wp_parse_args( $args, $defaults );
      $r = array_merge( $r , array("include" => $user_ids));
    
      $ret = $wf->users( $r );
  
    } else {
      $ret = new WOOF_Collection( array() );
    }
    
    $this->restore_site();
    
    return $ret;
    
  }
  
  
  public function query_incoming($args = array()) {
    $r = wp_parse_args($args);
    $r["query"] = "1";
    return $this->incoming($r);
  }
  
  public function has_field($name) {
    $field = $this->field($name);
    
    if (!$field->exists() || $field->blank()) {
      return false;
    }
    
    return $field;
  }
  
  public function has_set($name) {
    $set = $this->set($name);

    if (!$set->exists() || $set->blank()) {
      return false;
    }
    
    return $set;
  }
  
  public function has($name) {

    if ($set = $this->has_set($name)) {
      return $set;
    } else {
      if ($field = $this->has_field($name)) {
        return $field;
      }
    } 
    
    return false;
  }

  public function __call($name, $arguments = array()) {

    global $wf;

    if (preg_match("/incoming\_([a-z0-9\_]+)/", $name, $matches)) {

      // look for "incoming" post types, with arguments, so that we can call incoming_cars("orderby=title") for example

      $pt_name = $matches[1];
      $singular = WOOF_Inflector::singularize($pt_name);
      
      foreach ($wf->types() as $type) {
        if ($type->name == $pt_name) {
          return $this->incoming("post_type=".$pt_name)->first(); // return the first incoming post (ignore the args)
        } else if ($type->name == $singular) {
          
          $args = array("post_type" => $singular);
           
          if (isset($arguments[0])) {
            $args = wp_parse_args( $arguments[0] );
            $args["post_type"] = $singular;
          }
          
          return $this->incoming($args);
        } 
      }
      
      // next we'll try taxonomy names
      
      foreach ($wf->taxonomies() as $tax) {
        if ($tax->name == $singular) {
          
          if (isset($arguments[0])) {
            $args = wp_parse_args( $arguments[0] );
          }
          
          return $this->incoming_terms($tax, $args);
        }
      }
      
      
    } else {
      
      $singular = WOOF_Inflector::singularize($name);
      
      foreach ($wf->types() as $type) {
        if ($type->name == $name) {
          return $this->posts("post_type=".$singular)->first(); // return the first post (ignore the args)
        } else if ($type->name == $singular) {
          
          $args = array("post_type" => $singular);
           
          if (isset($arguments[0])) {
            $args = wp_parse_args( $arguments[0] );
            $args["post_type"] = $singular;
          }
          
          return $this->posts($args);
        } 
      }
      
    }
    
    return parent::__call($name, $arguments);

  }
  
  public function __get($name) {
  
    global $wf;
    
    // is we're accessing the set named "content" and it exists, prioritise this first
    // this allows us to call "content()" to get the standard content FIELD.
    
    if ($name == "content") {
      $set = $this->set("content");
      
      if ($set->exists()) {
        return $set;
      }
    }
    
    // fallback to WOOF_Wrap's get FIRST.
    
    $value = $this->get($name);
    
    if (is_woof_silent($value)) {
      $value = $this->set($name);
    }

    if (!is_woof_silent($value)) {
      return $value;
    }

    // look for "incoming" post types, so that we can get "incoming_cars" for example
    
    if (preg_match("/incoming\_([a-z0-9\_]+)/", $name, $matches)) {
    
      $pt_name = $matches[1];
      $singular = WOOF_Inflector::singularize($pt_name);
      
      foreach ($wf->types() as $type) {
        if ($type->name == $pt_name) {
          return $this->incoming("post_type=".$pt_name)->first(); // return the first incoming post
        } else if ($type->name == $singular) {
          return $this->incoming("post_type=".$singular);
        }
      }
      
      
      // next we'll try taxonomy names
      
      foreach ($wf->taxonomies() as $tax) {
        if ($tax->name == $singular) {
          return $this->incoming_terms($tax);
        } 
      }
      
      
    } else {

      $singular = WOOF_Inflector::singularize($name);

      foreach ($wf->types() as $type) {
        if ($type->name == $name) {
          return $this->posts("post_type=".$name)->first(); // return the first post (ignore the args)
        } else if ($type->name == $singular) {
          return $this->posts("post_type=" . $singular);
        } 
      }

    }
    
    // fallback to the parent method
    
    return parent::__get($name);
    
  }
  
  public function set_names() {
    global $meow_provider;
    
    $sets = array();
    // returns an array of field set names applicable to this post
    
    $this->switch_site();
    
    $assigned_sets = $meow_provider->post_type_field_sets($this->type_name(), $this->template());
    
    foreach ($assigned_sets as $set) {
      $sets[] = $set->name;
    }
    
    $this->restore_site();
    
    return $sets;
    
  }
  
  public function update($include_sets = true) {
    
    global $wf;
    
    $auto_id = $this->id();
    
    parent::update();
    
    $wf->record_true_id( $this, "post", $auto_id, $this->id() );
    
    // also checks through the field sets for this post and updates those
    $sets = $this->set_names();
    
    if ($include_sets) {
      foreach ($sets as $name) {
        
        $set = $this->set($name);
      
        if ($set->is_dirty()) {
          $set->update();
        } 
      
      }
    }

    return $this;
  }
  
	public function process_meta() {
		
		global $wf, $meow_provider;
		
		parent::process_meta();	
		
		
		// build the "info" / "data" structure which can be used by MEOW_Field to prevent needing to query 

		// get the assigned field sets for this object

		$template = $wf->template_for_post( $this->id );
		$sets = $meow_provider->post_type_field_sets( $this->type_name, $template );

		// get_field_data($name, $set_index);
		
		if (!isset($this->field_data)) {
			$this->field_data = array();
		}
		
		foreach ($this->_meta as $meta_key => $meta_items) {
			
			foreach ($meta_items as $index => $meta_value) {
				$set_index = $index + 1; // 1-based indexes
        
				list($set_name, $field_name, $prop_name) = MPFT::parse_meta_key($meta_key);
				
				$set_field_name = $set_name . ":" . $field_name;
				
				$field_info = null;
				
				if ( isset( $sets[$set_name]->fields[$field_name] ) ) {
					$field_info = $sets[$set_name]->fields[$field_name];
				}

					
				if ($field_info) {
					
					if ( ! isset( $this->field_data[ $set_field_name ] ) ) {
						$this->field_data[ $set_field_name ] = array(
							"info" => $field_info,
							"items" => array()
						);
					}

					if ( ! isset( $this->field_data[$set_field_name]["items"][$set_index] ) ) {
						$this->field_data[$set_field_name]["items"][$set_index] = array( "prop" => array() );
					}
					
					if ($prop_name == "") {

						// this is a value
							
            $value = $meow_provider->load_value($meta_value, $field_info);
      
            if (is_array($value)) {
              $blank = !count($value);
            } else {
        	    $blank = ( trim($value) == "" || is_null( $meta_value ) );
            }
    
						$this->field_data[$set_field_name]["items"][$set_index]["__blank"] = $blank;
						$this->field_data[$set_field_name]["items"][$set_index]["val"] = $value;
							
					} else {
						
						// this is a property on a value
						$this->field_data[$set_field_name]["items"][$set_index]["prop"][$prop_name] = $meow_provider->load_prop( $prop_name, $meta_value, $field_info);

					}
					
				
				} // if $field_info
			
			
			} // endforeach
			
			
		} // endforeach
		
		
	}
	
	public function get_field_data( $name, $set_index ) {
		
		if ( isset($this->field_data[$name]["items"][$set_index]) ) {
			return array(
				"info" => $this->field_data[$name]["info"],
				"data" => (object) $this->field_data[$name]["items"][$set_index]
			);
		}
		
		return false;
		
	}
	
  public function eval_json_field($name, $fields) {
    
    global $wf;

    $result = $wf->eval_json_field_on($this, $name, $fields);
    
    if ($result !== false) {
      return $result;
    }

    return parent::eval_json_field($name, $fields);
  
  }
  
  public function terms($taxonomy = null, $fields = array()) {
    
    // allows custom field based related terms to be included in queries
    
    global $wf, $meow_provider;

    $terms = parent::terms($taxonomy);
    
    $this->switch_site();
    
    if ($wf->regard_field_terms()) {
      
      $ids = $meow_provider->outgoing_terms($this, $fields);
      $field_terms = $wf->terms_by_id($ids, $taxonomy);

      if (count($field_terms)) {
        $terms->merge($field_terms, false);
        $terms->dedupe();
      }
      
    }
    
    $this->restore_site();
    
    return $terms;
    
  }
  
  public function json_href() {

    global $wf;

		if ( $wf->using_wp_rest_api() ) {
			return get_json_url( $this->_site_id, "/posts/" . $this->id() );	
		} else {
	    $url = $this->url(true);
    
	    if ($this->item->post_type == "post") {
	      $url = "post/" . $this->slug();
	    }
    
	    return rtrim( $this->site->url(), "/" ) . "/" . trim( $wf->rest_api_slug(), "/" ) . "/" . trim( $url, "/" );
		}

  }
  
  public static function json_fields() {
    return "id,author,date,modified,title,url,content,excerpt,slug,status,type,comments_open,pings_open,comment_count,featured_image,format";
  }
  
  public function json($fields, $context = "view") {
    
    global $wf;
    
    $type = $this->type_name();

    $json = array();
    
    if ( $wf->using_meow_rest_api() && apply_filters("mp_rest_post_href_field", true ) ) {
      $json["href"] = $this->json_href();
    }

    if (!is_array($fields)) {
      $fields = $wf->parse_field_list( $fields );
    } 
    
    if (!isset($fields)) {
      $fields = $wf->parse_field_list( self::json_fields() );
    }
    
    foreach ($fields as $name => $sub_fields) {
      
      $val = null;

      switch ($name) {

        case "id" : 
        case "ID" : 
        
          $val = (int) $this->id();
          break;
        
        case "author" :

          $val = $this->author->json();

          break;
        case "type" :

          $val = $this->type_name;
          break;

        case "date" :

          $val = $this->date("c");
          break;

        case "modified" :

          $val = $this->item->post_modified;
          
          if ($val == 0) {
            $val = null;
          } else {
            $val = $this->modified("c");
          }
          break;

        case "comments_open" :

          $val = $this->comment_status == "open";
          break;

        case "pings_open" :

          $val = $this->ping_status == "open";
          break;

        case "comment_count" : 
        
          $val = (int) $this->comment_count();
          break;
         
        default: {
          $val = $this->eval_json_field($name, $sub_fields); 
        }

      }

      $json[$name] = $val;
    }
    
    return $json;
    
  }
  
  public function debug_data() {
    return $this->field_debug_data();
  }
  
}
