<?php
// $Id$

/**
 *
 */
function mapi_invoke_extensions($op, $name = null, &$data = null, $read = null) {
  static $modules;

  if (!isset($modules)) {
    $modules = array();
    mapi_invoke_extensions('list');
  }

  // get the appropriate extension
  $ext = mapi_file_ext($name);
  $ext = ($ext ? $ext : $name);

  // if it is transform specific
  if ($ext) {
    if (array_key_exists($ext, $modules)) {
      $func = $modules[$ext] .'_mapi_extensions';
      if (function_exists($func)) {
        return $func($op, $name, $data, $read);
      }
    }
  }
  // otherwise simply cycle through them all
  else {
    $results = array();
    foreach (module_implements('mapi_extensions') as $module) {
      unset($result);
      $func = $module .'_mapi_extensions';
      if (function_exists($func)) {
        $result = $func($op, $name, $data, $read);
      }
      if (isset($result)) {
        if (!is_array($result)) {
          $result = array($result);
        }

        $results = array_merge($results, $result);
        if ($op == 'list') {
          foreach ($result as $ext) {
            $modules[$ext] = $module;
          }
        }
      }
    }

    return $results;
  }
}

/**
 *
 */
function mapi_invoke_types($op, $type = null, $edit = null) {
  return mapi_invoke_hook('types', $op, $type, $edit);
}

/**
 *
 */
function mapi_invoke_programs($op, $program = null, $edit = null) {
  return mapi_invoke_hook('programs', $op, $program, $edit);
}

/**
 *
 */
function mapi_invoke_transforms($op, $transform = null, $data = null, $file = null) {
  static $modules;

  if (!isset($modules)) {
    $modules = array();
    mapi_invoke_transforms('list');
  }

  // if it is transform specific
  if ($transform) {
    if (array_key_exists($transform, $modules)) {
      $func = $modules[$transform] .'_mapi_transforms';
      if (function_exists($func)) {
        return $func($op, $transform, $data, $file);
      }
    }
  }
  // otherwise simply cycle through them all
  else {
    $results = array();
    foreach (module_implements('mapi_transforms') as $module) {
      unset($result);
      $func = $module .'_mapi_transforms';
      if (function_exists($func)) {
        $result = $func($op, $transform, $data, $file);
      }
      if (isset($result)) {
        if (!is_array($result)) {
          $result = array($result);
        }

        $results = array_merge($results, $result);
        if ($op == 'list') {
          foreach ($result as $trans) {
            $modules[$trans] = $module;
          }
        }
      }
    }
    ksort($results);

    return $results;
  }
}

/**
 *
 */
function mapi_invoke_presenters($op, $presenter = null, $filename = null, $data = null) {
  return mapi_invoke_hook('presenters', $op, $presenter, $filename, $data);
}

/**
 *
 */
function mapi_invoke_hook($hook, $op, &$data1, &$data2, &$data3 = null) {
  static $modules;
  static $reference;

  if ($op == 'list') {
    $modules[$hook] = array();
    $reference[$hook] = array();

    // cycle through modules that implement the mapi_extensions
    foreach (module_implements('mapi_'. $hook) as $module) {
      $function = $module .'_mapi_'. $hook;
      $result = $function('list', $data1, $data2, $data3);
      if (isset($result) && is_array($result)) {
        // check that array contains only strings
        foreach ($result as $ref) {
          // if not string, continue the modules process
          if (!is_string($ref)) {
            continue 2;
          }
        }
        $modules[$hook][$module] = $result;
      }
      else if (isset($result) && is_string($result)) {
        $modules[$hook][$module] = array($result);
      }
    }

    // now with the modules create the extension list
    foreach ($modules[$hook] as $module => $refs) {
      foreach ($refs as $ref) {
        if ($hook != 'transforms' || !$data1) {
          $reference[$hook][$ref] = $module;
        }
      }
    }

    return array_keys($reference[$hook]);
  }
  else {
    if (!isset($modules[$hook]) || !isset($reference[$hook])) {
      mapi_invoke_hook($hook, 'list', $data1, $data2, $data3);
    }

    switch ($hook) {
      case 'extensions':
        $ext = mapi_file_ext($data1);
        $ext = ($ext ? $ext : $data1);
        $function = $reference[$hook][$ext] .'_mapi_extensions';
        if (function_exists($function)) {
          $result = $function($op, $data1, $data2, $data3);
        }
        break;
      case 'programs':
      case 'types':
        $function = $reference[$hook][$data1] .'_mapi_'. $hook;
        if (function_exists($function)) {
          $result = $function($op, $data1, $data2);
        }
        break;
      case 'transforms':
        if (!isset($reference[$hook][$data1])) {
          mapi_invoke_transforms('list');
        }
      case 'presenters':
        $function = $reference[$hook][$data1] .'_mapi_'. $hook;
        if (function_exists($function)) {
          $result = $function($op, $data1, $data2, $data3);
        }
        break;
    }
    if (isset($result)) {
      return $result;
    }
  }
}

/**
 *
 */
function mapi_invoke_workspaces($op, $module) {
  static $workspaces = array();

  if ($op == 'list') {
    $workspaces = array('' => array(
      'files' => file_directory_path(),
      'temp' => file_directory_temp(),
    ));
    foreach (module_implements('mapi_workspaces') as $module) {
      $results = module_invoke($module, 'mapi_workspaces');
      if (is_array($results)) {
        // add the default, temp should always be available
        $workspaces[$module] = array(
          'default' => file_directory_temp()
        );

        // check that each path is actually that
        foreach ($results as $key => $path) {
          if (is_dir($path)) {
            $workspaces[$module][$key] = rtrim($path, '/\\');
          }
          else {
            watchdog('mapi', t('Attempting to add non-existant workspace path (%path).', array('%path' => $path)), WATCHDOG_ERROR);
          }
        }
      }
    }
  }
  elseif ($op == 'paths') {
    if (empty($workspaces)) {
      mapi_invoke_workspaces('list', null);
    }

    if (is_null($module)) {
      return $workspaces[''];
    }
    elseif (array_key_exists($module, $workspaces)) {
      return $workspaces[$module];
    }
    return array();
  }
}

/**
 *  Invocation method for hook_mapi_profile.
 */
function mapi_invoke_profile($op, &$profile = null, $filename = null) {
  static $cache;

  // setup the cache for handling the profiles
  if (!isset($cache)) {
    $cache = array();

    $list = mapi_profile_list();
    $item = mapi_invoke_profile('list', $name, $filename);

    $handlers = variable_get('mapi_profile_handlers', array());
    foreach ($list as $name) {
      // get module handler for the profile name.
      $suggest = (array_key_exists($name, $handlers) ? $handlers[$name] : null);

      // make sure we have something to select for handlers.
      if (!$suggest) {
        if (isset($item[$name]) && is_array($item[$name]) && array_key_exists($name, $item)) {
          $suggest = array_shift($item[$name]);
        }
      }

      // make sure that the module exists
      if ($suggest) {
        $cache[$name] = $suggest;
      }
    }

    // don't perform listing twice.
    if ($op == 'list') {
      return $item;
    }
  }

  switch ($op) {
    // main notification messages
    case 'create':
    case 'delete':
    case 'update':
      module_invoke_all('mapi_profile', $op, $profile, $filename);
      break;

    case 'presenter':
    case 'settings':
    case 'filename':
      // check the cached list for the module which handles this
      if ($profile && is_object($profile) && array_key_exists($profile->name, $cache)) {
        $module = $cache[$profile->name];
        $func = $module .'_mapi_profile';
        $results = $func($op, $profile, $filename);
        if ($results && is_string($results)) {
          return $results;
        }
      }

      // return the filename, if nothing else functioned.
      if ($op == 'filename') {
        return $filename;
      }

    // allows modules to add their own details to the profile
    case 'load':
      // create context array
      if ($profile && is_object($profile)) {
        foreach (module_implements('mapi_profile') as $module) {
          $func = $module .'_mapi_profile';
          $results = $func('load', $profile, null);
        }
      }
      break;

    // returns a list of the appropriate profiles the module can manage
    // but orders them by profile
    case 'list':
      $list = array();

      foreach (module_implements('mapi_profile') as $module) {
        $blank = null;
        $func = $module .'_mapi_profile';
        $results = $func('list', $blank, null);
        if ($results && is_array($results)) {
          foreach ($results as $name) {
            $list[$name][] = $module;
          }
        }
      }

      return $list;
  }
}

