<?php

use Civi\DataProcessor\Output\ExportOutputInterface;

/**
 * @author Jaap Jansma <jaap.jansma@civicoop.org>
 * @license AGPL-3.0
 */

class CRM_DataprocessorSearch_StateMachine_Search extends CRM_Core_StateMachine {

  /**
   * The task that the wizard is currently processing.
   *
   * @var string
   */
  protected $_task;

  /**
   * Class constructor.
   *
   * @param \CRM_DataprocessorSearch_Controller_Search $controller
   * @param mixed $action
   */
  public function __construct(CRM_DataprocessorSearch_Controller_Search $controller, $action = CRM_Core_Action::NONE) {
    parent::__construct($controller, $action);

    $this->_pages = array();
    $this->_pages[$controller->getSearchName()] = array(
      'className' => $controller->getSearchClass(),
    );

    $this->_task = self::getTaskClass($controller);
    if (empty($this->_task)) {
      $this->_task = $this->getExportFormClass($controller);
    }

    if (is_array($this->_task)) {
      foreach ($this->_task as $t) {
        if ($t) {
          $this->_pages[$t] = NULL;
        }
      }
    }
    elseif ($this->_task) {
      $this->_pages[$this->_task] = NULL;
    }

    $this->addSequentialPages($this->_pages);
  }

  /**
   * Return the form name ofCRM_DataprocessorSearch_StateMachine_Search the task.
   *
   * @return string
   */
  public function getTaskFormName(): string {
    if (is_array($this->_task)) {
      // return first page
      return CRM_Utils_String::getClassName($this->_task[0]);
    }
    else {
      return CRM_Utils_String::getClassName($this->_task);
    }
  }

  /**
   * Should the controller reset the session.
   * In some cases, specifically search we want to remember
   * state across various actions and want to go back to the
   * beginning from the final state, but retain the same session
   * values
   *
   * @return bool
   */
  public function shouldReset(): bool {
    return FALSE;
  }

  /**
   * Determine the form name based on the action. This allows us
   * to avoid using  conditional state machine, much more efficient
   * and simpler
   *
   * @param CRM_DataprocessorSearch_Controller_Search $controller
   *   The controller object.
   *
   * @return string
   */
  private function getTaskClass(CRM_DataprocessorSearch_Controller_Search $controller) {
    // total hack, check POST vars and then session to determine stuff
    $value = CRM_Utils_Array::value('task', $_POST);
    if (!isset($value)) {
      $value = $controller->get('task');
    }
    $controller->set('task', $value);

    if ($value) {
      return $controller->getTaskClass($value);
    }
    return null;
  }

  /**
   * Find the selected export form.
   *
   * @param \CRM_DataprocessorSearch_Controller_Search $controller
   *
   * @return string|null
   */
  private function getExportFormClass(CRM_DataprocessorSearch_Controller_Search $controller):? string {
    try {
      $export_id = CRM_Utils_Request::retrieve('export_id', 'Integer');
    } catch (CRM_Core_Exception $e) {
    }
    if (empty($export_id)) {
      $export_id = $controller->get('export_id');
    }
    if ($export_id) {
      $controller->set('export_id', $export_id);
      $factory = dataprocessor_get_factory();
      try {
        $outputType = civicrm_api3("DataProcessorOutput", "getvalue", [
          'id' => $export_id,
          'return' => 'type',
        ]);
        $outputClass = $factory->getOutputByName($outputType);
        if ($outputClass instanceof ExportOutputInterface) {
          return $outputClass->getExportFormClassName();
        }
      } catch (CiviCRM_API3_Exception $e) {
        return null;
      }
    }
    return null;
  }



}
