<?php

/**
 * @author Jaap Jansma (CiviCooP) <jaap.jansma@civicoop.org>
 * @license http://www.gnu.org/licenses/agpl-3.0.html
 */

namespace Civi\FormProcessor;

use Civi\FormProcessor\Type\AbstractType;
use CRM_FormProcessor_ExtensionUtil as E;

class DataBag {

  private $inputs = array();

  private $actions = array();

  private $inputData = array();

  private $inputTypes = array();

  private $actionData = array();

  private $formattedData = array();


  /**
   * Sets the input data for a given input.
   *
   * @param \CRM_FormProcessor_BAO_FormProcessorInput $inputObject
   * @param mixed $value
   * @return DataBag
   */
  public function setInputData($inputObject, $value, AbstractType $inputType) {
    $this->inputs[$inputObject->id] = $inputObject;
    $this->inputData[$inputObject->id] = $value;
    $this->inputTypes[$inputObject->id] = $inputType;
    DatabagFormatter::formatDatabag($this);
    return $this;
  }

  /**
   * Retrieves the input data for a given input.
   *
   * @param $input
   * @return string
   */
  public function getInputData($inputObject) {
    return $this->inputData[$inputObject->id];
  }

  /**
   * @param $name
   *
   * @return AbstractType|null
   */
  public function getInputType($name) {
    $input = $this->getInputByName($name);
    if ($input) {
      return $this->inputTypes[$input->id];
    }
    return null;
  }

  /**
   * Returns an array with all the inputs.
   *
   * @return array
   */
  public function getAllInputs() {
    return $this->inputs;
  }

  /**
   * Sets the action data for a given action.
   *
   * @param $action
   * @param string $field
   * @return DataBag
   */
  public function setActionData($actionObject, $field, $value) {
    $this->actions[$actionObject->id] = $actionObject;
    $this->actionData[$actionObject->name][$field] = $value;
    DatabagFormatter::formatDatabag($this);
    return $this;
  }

  /**
   * Retrieves all the action data for a given action.
   *
   * @param $actionObject
   * @return array
   */
  public function getActionData($actionObject) {
    if (isset($this->actionData[$actionObject->name])) {
      return $this->actionData[$actionObject->name];
    }
    return array();
  }

  /**
   * Returns an array with all the actions.
   *
   * @return array
   */
  public function getAllActions() {
    return $this->actions;
  }

  /**
   * Sets the action data from an action provider parameter bag object.
   *
   * @param $actionObject
   * @param $parameterBag
   * @return DataBag
   */
  public function setActionDataFromActionProviderParameterBag($actionObject, $parameterBag) {
    $this->actions[$actionObject->id] = $actionObject;
    foreach($parameterBag as $field => $value) {
      $this->actionData[$actionObject->name][$field] = $value;
    }
    DatabagFormatter::formatDatabag($this);
    return $this;
  }

  /**
   * Returns the data by its alias. Returns null when the alias is not set
   *
   * Example aliases:
   *   input.email
   *   action.3.contact_id
   *
   * @param string
   * @return mixed|null
   */
  public function getDataByAlias($alias) {
    $splitted_alias = explode(".", $alias);
    if ($splitted_alias[0] == 'input') {
      $input = $this->getInputByName($splitted_alias[1]);
      if ($input) {
        return $this->inputData[$input->id];
      }
    } elseif ($splitted_alias[0] == 'action' && isset($this->actionData[$splitted_alias[1]][$splitted_alias[2]])) {
      return $this->actionData[$splitted_alias[1]][$splitted_alias[2]];
    } elseif ($splitted_alias[0] == 'formatted' && isset($this->formattedData[$splitted_alias[1]])) {
      return $this->formattedData[$splitted_alias[1]];
    }
    return null;
  }

  /**
   * Returns all the aliases for data fields.
   *
   * An alias looks like:
   *   input.email
   *   action.3.contact_id
   *
   * @return array.
   */
  public function getAllAliases() {
    $aliases = array();
    foreach($this->inputs as $input) {
      $aliases[] = 'input.'.$input->name;
    }
    foreach($this->actions as $action) {
      if (!isset($this->actionData[$action->name])) {
        continue;
      }
      foreach($this->actionData[$action->name] as $field => $value) {
        $aliases[] = 'action.'.$action->name.'.'.$field;
      }
    }
    foreach(DatabagFormatter::getFormats() as $element => $label) {
      $aliases[] = 'formatted.'.$element;
    }
    return $aliases;
  }

  /**
   * Returns the input object by its name.
   */
  private function getInputByName($name) {
    foreach($this->inputs as $input) {
      if ($input->name == $name) {
        return $input;
      }
    }
    return null;
  }

  /**
   * @param $key
   * @param $formattedDatabag
   *
   * @return void
   */
  public function setFormattedDatabag($key, $formattedDatabag) {
    $this->formattedData[$key] = $formattedDatabag;
  }

}
