<?php

/**
 * Manager class for importing ISIS data into a Symfony project.
 * Importing can be done either on actions or tasks.
 */
class sfIsisImporterManager extends IsisConnector
{
  /**
   * @var string $loglevel Log level
   */
  var $loglevel = 'info';

  /**
   * @var int $processed Number of processed entries
   */
  var $processed = 0;

  /**
   * Constructor.
   */
  public function __construct($loglevel = 'info')
  {
    parent::__construct();

    // Get a logger instance.
    $this->logger = sfIsisImporterLog::getInstance($loglevel);
  }

  /**
   * Log dispatcher.
   *
   * @param string $message Log message
   * @param string $level   Log level
   */
  public function log($message, $level = 'info')
  {
    $this->logger->log($message, $level);
  }

  /**
   * Progress notifier dispatcher.
   *
   * @param int $entry Entry number
   */
  public function progress($entry)
  {
    $this->processed = $this->logger->progress($entry, $this->entries);
  }

  /**
   * Create an ISIS configuration for a given database.
   *
   * @param  string $database Database name
   * @return array            Basic configuration
   */
  public function config($database)
  {
    // Default cinisis config file.
    $config = $this->isis->file();

    if (file_exists($config))
    {
      $this->log("Using Cinisis config file $config.");
      $config = sfYaml::load($config);
    }
    else {
      // Default configuration.
      $this->log("Cinisis config file not found, building configuration.");
      $config = array(
        'implementation' => 'BiblioIsis',
      );
    }

    $config['database'] = $database;
    return $config;
  }

  /**
   * List available ISIS databases.
   *
   * @return array Available databases
   */
  public function databases()
  {
    $databases = array();

    foreach (glob(sfConfig::get('sf_lib_dir') ."/cinisis/schemas/*.yaml") as $file)
    {
      $database = basename($file, '.yaml');
      $options  = sfYaml::load($file);
      
      if (isset($options['import']['order']))
      {
        $databases[$options['import']['order']] = $database;
      }
      else
      {
        $this->log("Database config $database has no order option, skipping.");
      }
    }

    ksort($databases);
    return $databases;
  }

  /**
   * After import procedure.
   */
  public function afterImport() {
    // Output ISIS log messages.
    if (is_array($this->isis->db->log))
    {
      foreach ($this->isis->db->log as $log)
      {
        $this->log("[isis] $log");
      }
    }

    $this->log("Finished mass import procedure.", 'notice');
    $this->log("Total entries processed: $this->processed.", 'notice');
  }

  /**
   * Execute a mass import of ISIS database entries. This function reads
   * each database entry and dispatch each field read to a custom
   * dispatch function.
   *
   * @param object $caller  Caller object
   * @param string $section Caller section (whether an action or task)
   * @param int    $entries Number of entries to import (defaults to all)
   */
  public function massImport($caller, $section, $entries = NULL, $offset = 0)
  {
    // Additional logging settings.
    $this->logger->setCaller($caller);
    $this->logger->setSection($section);

    foreach ($this->databases() as $database)
    {
      // Open database.
      $importer = $this->newImporter($database);

      if ($importer)
      {
        // Determine base model and max entries.
        $this->log('Starting mass import procedure for database schema "'. $database .'".', 'notice');
        $base_model = $importer->isis->format['import']['base_model'];
        $this->max  = ($entries != NULL && $entries + $offset <= $importer->isis->entries) ? $entries + $offset : $importer->isis->entries;

        if ($base_model)
        {
          for ($entry = $offset + 1; $entry <= $this->max; $entry++)
          {
            $importer->addEntry($base_model, $entry);
            $this->progress($entry);
          }
        }

        $this->afterImport();
      }
    }
  }

  /**
   * Setup a new importer.
   *
   * @param  string $database Database name
   * @return mixed            Importer object or false
   */
  public function newImporter($database)
  {
    $class = 'IsisImporterDb'. ucfirst($database);
    if (class_exists($class))
    {
      return new $class($this->config($database));
    }

    return false;
  }
}