<?php

/**
 * IsisImporterRelations: provides ISIS import methods for importing data
 * into model entities.
 */
class sfIsisImporterRelations extends sfIsisImporterEntities {
  /**
   * Import one to one data.
   *
   * @param object $model    Model
   * @param array  $field    Field data from ISIS database schema
   * @param string $relation Relation name
   */
  public function addOneToOne(&$model, array $field, $relation)
  {
    foreach (new IsisRowIterator($this->isis, $field) as $row)
    {
      $data = new $relation();

      $this->addMain($data, $field, $row);
      $this->addSubfields($data, $field, $row);
      $data->save();

      $key         = sfInflector::underscore($relation) .'_id';
      $model->$key = $data->id;
    }
  }

  /**
   * Import one to many data.
   *
   * @param  object $model    Model
   * @param  string $relation Relation name
   * @return object           Relation model object
   */  
  public function addOneToMany(&$model, $relation)
  {
    $model_id          = $this->getModelId($model);
    $data              = new $relation();
    $data->{$model_id} = $model->id;
    $data->save();
    return $data;
  }

  /**
   * Add simple entities data into the model using main item data.
   *
   * @param object $model  Model
   * @param array  $field  Field data from ISIS database schema
   * @param string $entity Entity name
   * @param string $key    Optional data key
   */  
  public function addOneToManyMain(&$model, array $field, $entity, $key = 'name')
  {
    foreach (new IsisMainItemIterator($this->isis, $field) as $row => $value)
    {
      $this->log("Entity: $entity; Value: $value", 'debug');
      $data         = $this->addOneToMany($model, $entity);
      $data->{$key} = $value;
      $data->save();
    }    
  }

  /**
   * Add simple entities data into the model using subfield data.
   *
   * @param object $model Model
   * @param array  $field Field data from ISIS database schema
   * @param string $entity Entity name
   */  
  public function addOneToManySubfields(&$model, array $field, $entity)
  {
    $relations = array();

    foreach (new IsisSubfieldIterator($this->isis, $field) as $row => $subfield)
    {
      if (!isset($relations[$row]))
      {
        // Initialize a new relation.
        $relations[$row] = $this->addOneToMany($model, $entity);
      }

      $relations[$row]->{$subfield} = $this->isis->getSubfield($field, $subfield, $row);
    }

    // Save all relations.
    foreach($relations as $relation)
    {
      $relation->save();
    }    
  }

  /**
   * Import a single value to a many to many data model.
   *
   * @param object $model    Model
   * @param mixed  $values   Values to be added
   * @param string $relation Relation name
   * @param string $key      Value key
   */
  public function addManyToMany(&$model, $value, $relation, $key = 'name')
  {
    return $this->addToSharedModel($model, $value, $relation, $key, 'add');
  }

  /**
   * Import a single value to a shared data model.
   *
   * @param object $model    Model
   * @param mixed  $values   Values to be added
   * @param string $relation Relation name
   * @param string $key      Value key
   * @param string $strategy Strategy do add the content into the database
   */
  public function addToSharedModel(&$model, $value, $relation, $key = 'name', $strategy = 'add')
  {
    $method = $strategy . $relation;

    // Populate related data.
    if (is_callable(array($this, $method)))
    {
      $data = $this->{$method}($value);
    }
    else
    {
      $data = $this->{$strategy .'Entity'}($relation, $value, $key);
    }

    // Get model and relation names and id fields.
    $model_id                   = $this->getModelId($model);
    $relation_id                = $this->getRelationId($relation);
    $model_relation             = $this->getModelRelation($model, $relation);

    // Make the relation.
    $model_data                 = new $model_relation();
    $model_data->{$model_id}    = $model->id;
    $model_data->{$relation_id} = $data->id;
    $model_data->save();

    return $model_data;
  }

  /**
   * Import many to many data.
   *
   * @param object $model    Model
   * @param array  $values   Values to be added
   * @param string $relation Relation name
   * @param string $key      Value key
   */
  public function addManyToManyEntities(&$model, array $values, $relation, $key = 'name')
  {
    foreach ($values as $value)
    {
      $existing = $this->getEntity($relation, $value, $key);

      // Prevent duplicate entries.
      if (!$existing)
      {
        $this->addManyToMany($model, $value, $relation, $key);
      }
      else {
        $this->log("Found duplicate entry $value for relation $key.", 'debug');
      }
    }
  }

  /**
   * Add field values in a many-to-many relation.
   *
   * @param object $model    Model
   * @param array  $field    Field data from ISIS database schema
   * @param string $relation Relation name
   * @param string $key      Value key
   */
  public function addManyToManyMain(&$model, array $field, $relation, $key = 'name')
  {
    foreach (new IsisMainItemIterator($this->isis, $field) as $value)
    {
      $this->addManyToManyEntities($model, $this->isis->explodeBrackets($value), $relation, $key);
    }    
  }
}