<?php

/**
 * Implementation of hook_mapi_admin()
 */
function mapi_derivatives_mapi_admin($op, $item) {
  switch ($op) {
    case 'menu':
      // provides a list of the derivatives and the subsections for displaying them.
      if ($item) {
        $derivatives = _mapi_derivatives_cache();
        foreach ($derivatives['line'] as $did) {
          $path = MAPI_ADMIN_PATH .'/derivatives/'. $derivatives[$did]['line'];

          $items[] = array(
            'path' => $path,
            'title' => t($derivatives[$did]['name']),
            'callback arguments' => array("mapi_derivative_admin_view_form", $did),
          );

          // check to see if the path is the current path, in which case add not only
          // the extras, but also the transforms for the derivatives
          if (strpos($_GET['q'], $path) === 0) {
            foreach (array('add', 'view', 'transform', 'delete') as $key) {
              $items[] = array(
                'path' => $path .'/'. $key,
                'title' => t($key),
                'callback arguments' => array("mapi_derivative_admin_{$key}_form", $did),
                'type' => ($key == 'delete' ? MENU_CALLBACK : ($key == 'view' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK))
              );
            }

            // make sure the add transform is available
            $items[] = array(
              'path' => $path .'/transform/add',
              'title' => t('Add Transform'),
              'callback arguments' => array("mapi_derivative_admin_transform_add_form", $did, null),
            );

            // add the menu items for the specific transforms
            $transforms = mapi_transform_by_derivative($did);
            foreach ($transforms as $tid => $info) {
              $items[] = array(
                'path' => $path .'/transform/'. $tid,
                'title' => t($info),
                'callback arguments' => array("mapi_derivative_admin_transform_edit_form", $did, $tid),
              );

              foreach (array('edit', 'insert', 'delete') as $key) {
                $items[] = array(
                  'path' => $path .'/transform/'. $tid .'/'. $key,
                  'title' => t($key),
                  'callback arguments' => array("mapi_derivative_admin_transform_{$key}_form", $did, $tid),
                  'type' => ($key == 'delete' ? MENU_CALLBACK : ($key == 'edit' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK))
                );
              }
            }
          }
        }
      }
      // otherwise the standard derivative listing information
      else {
        $items[] = array(
          'path' => MAPI_ADMIN_PATH ."/derivatives",
          'title' => t('Derivatives'),
          'description' => t('This provides automated derivatives for media.'),
          'callback arguments' => array("mapi_derivative_admin_form"),
        );
        $items[] = array(
          'path' => MAPI_ADMIN_PATH ."/derivatives/add",
          'title' => t('Add Derivative'),
          'callback arguments' => array("mapi_derivative_admin_add_form", null),
        );
      }
      return $items;
  }
}

/**
 *  Administration form.
 */
function mapi_derivative_admin_form() {
  // this should contain standard settings, since everything else is in the menu system
  $derivatives = _mapi_derivatives_cache();

  // provide defaults for various usages of the derivatives
  $form['exts'] = array();
  foreach (mapi_extension_list() as $ext) {
    $exts = mapi_derivatives_by_ext($ext);
    $exts = drupal_map_assoc($exts);
    $exts = array_merge(array('' => t('original')), $exts);
    $form['exts'][$ext]["mapi_ext_{$ext}_page"] = array(
      '#type' => 'select',
      '#options' => $exts,
      '#default_value' => variable_get("mapi_ext_{$ext}_page", '')
    );
    $form['exts'][$ext]["mapi_ext_{$ext}_teaser"] = array(
      '#type' => 'select',
      '#options' => $exts,
      '#default_value' => variable_get("mapi_ext_{$ext}_teaser", '')
    );
    $form['exts'][$ext]["mapi_ext_{$ext}_full"] = array(
      '#type' => 'select',
      '#options' => $exts,
      '#default_value' => variable_get("mapi_ext_{$ext}_full", '')
    );
  }

  return system_settings_form($form);
}

function theme_mapi_derivative_admin_form(&$form) {
  $output = '';
  $rows = array();
  foreach (element_children($form['exts']) as $ext) {
    $row = array(
      $ext,
      drupal_render($form['exts'][$ext]["mapi_ext_{$ext}_page"]),
      drupal_render($form['exts'][$ext]["mapi_ext_{$ext}_teaser"]),
      drupal_render($form['exts'][$ext]["mapi_ext_{$ext}_full"]),
    );
    $rows[] = $row;
  }

  // render the table
  $output .= theme('table', array(t('Extension'), t('Page'), t('Teaser'), t('Full View')), $rows, array('style' => 'width: 100%'));

  // render everything else
  $output .= '<p />'. drupal_render($form);

  return $output;
}

/**
 *  Adds a derivative
 */
function mapi_derivative_admin_add_form($did) {
  $derivative = mapi_derivative_load($did);

  // set parent
  $form['parent'] = array('#type' => 'value', '#value' => ($derivative ? $did : 0));

  // provide name
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#description' => t('Name can contain only alphanumeric, hyphen or underscore characters.'),
    '#max_length' => 128,
    '#required' => true
  );

  // so we can limit the derivatives available to people to create
  $exts = ($derivative ? array_filter(explode('|', $derivative->exts)) : mapi_extension_list());

  $form['exts'] = array('#tree' => true);
  foreach (mapi_type_list($type) as $type) {
    foreach (mapi_type_extensions($type) as $ext) {
      $form['exts'][$type][$ext] = array(
        '#type' => 'checkbox',
        '#title' => $ext,
        '#return_value' => $ext,
        '#parents' => array('extensions', $ext),
        '#disabled' => !in_array($ext, $exts),
      );
    }
  }

  $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));

  return $form;
}

function mapi_derivative_admin_add_form_validate($form_id, $form_values) {
  if (!$form_values['name'] || !preg_match('/^[\w\d_\-]+$/i', $form_values['name'])) {
    form_set_error('name', t('Name must contain only alphanumeric, hyphen, or underscore characters.'));
  }

  // check that the derivative is unique for name and extension
  $exts = array_filter($form_values['extensions']);

  // check that it's based on the parent
  $parent = mapi_derivative_load($form_values['parent']);
  if (!count(array_intersect($exts, array_filter(explode('|', $parent->exts))))) {
    form_set_error('exts', t('There are no common extensions from parent derivative.'));
  }

  // check unique names
  if ($exts = mapi_derivative_unique($form_values['name'], $exts)) {
    form_set_error('exts', t('Derivative of the same name already exists for this extension.'));
  }
}

function mapi_derivative_admin_add_form_submit($form_id, $form_values) {
  if ($form_values['op'] == t('Submit')) {
    $parent = (isset($form_values['parent']) ? $form_values['parent'] : 0);
    $derivative = mapi_derivative_create($form_values['name'], array_filter($form_values['extensions']), $parent);

    // rebuild the cache
    $derivatives = _mapi_derivatives_cache(true);
    return MAPI_ADMIN_PATH .'/derivatives/'. $derivatives[$derivative->did]['line'];
  }
}

/**
 *  Views the derivative details
 */
function mapi_derivative_admin_view_form($did) {
  if (!($derivative = mapi_derivative_load($did))) {
    drupal_not_found();
    exit();
  }

  $derivatives = _mapi_derivatives_cache();
  $line = MAPI_ADMIN_PATH .'/derivatives/'. $derivatives[$did]['line'] .'/transform/';

  $form['did'] = array('#type' => 'value', '#value' => $did);

  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#value' => $derivative->name,
    '#disabled' => true
  );

  $exts = array_filter(explode('|', $derivative->exts));
  $form['extensions'] = array(
    '#prefix' => '<div class="derivative-extensions">',
    '#value' => theme('item_list', $exts, t('Extensions')),
    '#suffix' => '</div>',
  );

  // add everything that is in the transform section
  $form = array_merge($form, mapi_derivative_admin_transform_form($did));

  $form['delete'] = array('#type' => 'button', '#value' => t('Delete'));

  return $form;
}

function mapi_derivative_admin_view_form_validate($form_id, $form_values) {
  if ($form_values['op'] == t('Delete')) {
    $derivatives = _mapi_derivatives_cache();
    $path = $derivatives[$form_values['did']]['line'];
    drupal_goto(MAPI_ADMIN_PATH .'/derivatives/'. $path .'/delete');
    exit();
  }
}

/**
 *  Delete the derivative
 */
function mapi_derivative_admin_delete_form($did) {
  if (!($derivative = mapi_derivative_load($did))) {
    drupal_not_found();
    exit();
  }

  $form['did'] = array('#type' => 'value', '#value' => $derivative->did);

  $details = t('This action cannot be undone.');
  $details .= '<p />';
  $details .= t('Deleting a derivative destroys all subderivatives, as well as the generated derivatives.');

  $form = confirm_form($form,
    t('Are you sure you want to delete %title?', array('%title' => $derivative->name)),
    isset($_GET['destination']) ? $_GET['destination'] : MAPI_ADMIN_PATH .'/derivatives',
    $details,
    t('Delete'), t('Cancel'));

  return $form;
}

/**
 *  Delete Form Submission
 */
function mapi_derivative_admin_delete_form_submit($form_id, $form_values) {
  if ($form_values['confirm'] == 1) {
    $did = $form_values['did'];
    mapi_derivative_delete($did);
  }

  return (isset($_GET['destination']) ? $_GET['destination'] : MAPI_ADMIN_PATH .'/derivatives');
}

/**
 *  List of transforms for derivatives
 */
function mapi_derivative_admin_transform_form($did) {
  if (!($derivative = mapi_derivative_load($did))) {
    drupal_not_found();
    exit();
  }

  $derivatives = _mapi_derivatives_cache();
  $line = MAPI_ADMIN_PATH .'/derivatives/'. $derivatives[$did]['line'] .'/transform/';

  // add the transforms
  $rows = array();
  $transforms = mapi_transform_by_derivative($did);
  foreach ($transforms as $tid => $name) {
    $rows[] = array(
      array('data' => l($name, $line . $tid), 'rowspan' => 2),
      l(t('Insert'), $line . $tid .'/insert')
    );
    $rows[] = array(
      l(t('Delete'), $line . $tid .'/delete')
    );
  }

  // add the basic section
  $rows[] = array(
    l(t('Add'), $line .'add'),
    ''
  );

  $form['transforms'] = array('#value' => theme('table', array(t('Transform'), t('Operations')), $rows));

  return $form;
}

/**
 *  Adds a transform to a derivative
 */
function mapi_derivative_admin_transform_add_form($did, $tid) {
  if (!($derivative = mapi_derivative_load($did))) {
    drupal_not_found();
    exit();
  }

  // create the list of allowable extensions
  $transforms = mapi_transform_by_derivative($derivative->did);
  $start = explode('|', trim($derivative->exts, '|'));
  foreach (array_keys($transforms) as $key) {
    if ($key == $transform->tid) {
      break;
    }
    $start = mapi_transform_allowable($key, $start);
  }

  // takes the valid extensions and generates the list of allowable transforms
  $transforms = mapi_transform_list();
  foreach ($start as $ext) {
    $transforms = array_intersect($transforms, mapi_transform_by_ext($ext));
  }

  $form['insert'] = array('#type' => 'value', '#value' => $tid);
  $form['tid'] = array('#type' => 'value', '#value' => $transform->tid);
  $form['did'] = array('#type' => 'value', '#value' => $derivative->did);

  $form['header'] = array(
    '#value' => t('Please select from one of the following transformations'),
    '#suffix' => ':<p />'
  );

  // so we have a transformation list which applies for all transformations
  if (count($transforms) > 0) {
    foreach ($transforms as $transform) {
      $info = mapi_invoke_transforms('info', $transform);
      $form['transform'][$transform] = array(
        '#type' => 'radio',
        '#title' => t($transform),
        '#description' => $info['description'],
        '#parents' => array('transforms'),
        '#return_value' => $transform,
      );
      if ($transforms[0] == $transform) {
        $form['transform'][$transform]['#default_value'] = $transform;
      }
    }
  }
  else {
    $form['transform'] = array(
      '#prefix' => '<div>',
      '#value' => t('There are no transformations which can be used with the currently defined extensions.'),
      '#suffix' => '</div>',
    );
    $invalid = true;
  }

  if (empty($invalid)) {
    $form['submit'] = array('#type' => 'submit', '#value' => t('Add'));
  }

  return $form;
}

function mapi_derivative_admin_transform_add_form_submit($form_id, $form_values) {
  if ($form_values['op'] == t('Add')) {
    $values = mapi_invoke_transforms('defaults', $form_values['transforms']);

    // create the transform
    $transform = mapi_transform_create($form_values['did'], $form_values['transforms'], $values, $form_values['insert']);

    //
    $derivatives = _mapi_derivatives_cache();
    return MAPI_ADMIN_PATH .'/derivatives/'. $derivatives[$form_values['did']]['line'] .'/transform/'. $transform->tid;
  }
}

function mapi_derivative_admin_transform_insert_form($did, $tid) {
  return mapi_derivative_admin_transform_add_form($did, $tid);
}

function mapi_derivative_admin_transform_insert_form_submit($form_id, $form_values) {
  return mapi_derivative_admin_transform_add_form_submit($form_id, $form_values);
}

/**
 *  Edit the transform settings for a derivative
 */
function mapi_derivative_admin_transform_edit_form($did, $tid) {
  if (!($transform = mapi_transform_load($tid))) {
    drupal_not_found();
    exit();
  }

  // get the settings for this transform
  $form['tid'] = array('#type' => 'value', '#value' => $transform->tid);
  $form['did'] = array('#type' => 'value', '#value' => $transform->did);
  $form['name'] = array('#type' => 'value', '#value' => $transform->name);
  $form['details'] = mapi_invoke_transforms('form', $transform->name, $transform->settings);
  if (empty($form['details'])) {
    $form['details'] = array('#value' => t('There are no settings to fill in for this transform.'), '#prefix' => '<div>', '#suffix' => '</div>');
  }
  $form['details']['#tree'] = true;

  $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
  $form['delete'] = array('#type' => 'button', '#value' => t('Delete'));

  return $form;
}

function mapi_derivative_admin_transform_edit_form_validate($form_id, $form_values) {
  // switch to delete phase
  if ($form_values['op'] == t('Delete')) {
    $derivatives = _mapi_derivatives_cache();
    drupal_goto(MAPI_ADMIN_PATH .'/derivatives/'. $derivatives[$form_values['did']]['line'] .'/transform/'. $form_values['tid'] .'/delete');
    exit();
  }

  // check the form settings
  mapi_invoke_transforms('validate', $form_values['name'], $form_values['details']);
}

function mapi_derivative_admin_transform_edit_form_submit($form_id, $form_values) {
  $details = $form_values['details'];
  mapi_invoke_transforms('submit', $form_values['name'], $details);
  mapi_transform_update($form_values['tid'], $details);

  // go back to transforms page
  $derivatives = _mapi_derivatives_cache();
  return MAPI_ADMIN_PATH .'/derivatives/'. $derivatives[$form_values['did']]['line'] .'/transform';
}

/**
 *  Delete the transform from a derivative
 */
function mapi_derivative_admin_transform_delete_form($did, $tid) {
  $derivatives = _mapi_derivatives_cache();
  if (!($derivative = mapi_derivative_load($did))) {
    drupal_goto(MAPI_ADMIN_PATH .'/derivatives');
    exit();
  }

  $path = MAPI_ADMIN_PATH .'/derivatives/'. $derivatives[$did]['line'] .'/transform';
  if (!($transform = mapi_transform_load($tid)) || $transform->did != $derivative->did) {
    drupal_goto($path);
    exit();
  }

  // check for whether we still have something left.
  $derivative = mapi_derivative_load($transform->did);
  $transforms = mapi_transform_by_derivative($transform->did);

  $start = explode('|', trim($derivative->exts, '|'));
  foreach (array_keys($transforms) as $key) {
    if ($key == $transform->tid) {
      continue;
    }
    $start = mapi_transform_allowable($key, $start);
  }

  $form['did'] = array('#type' => 'value', '#value' => $derivative->did);
  $form['tid'] = array('#type' => 'value', '#value' => $transform->tid);

  if (count($start)) {
    $form = confirm_form($form,
      t('Are you sure you want to delete %title?', array('%title' => $transform->name)),
      isset($_GET['destination']) ? $_GET['destination'] : $path,
      t('This action cannot be undone. It also will destroy any derivatives which have been generated up until now.'),
      t('Delete'), t('Cancel'));
  }
  else {
    $form['info'] = array('#value' => t('Cannot delete this transform, as this destroys the flow of transforms and their extensions.'));
    $form['confirm'] = array('#type' => 'value', '#value' => 0);
    $form['cancel'] = array('#type' => 'submit', '#value' => t('Cancel'));
  }

  return $form;
}

/**
 * Transform delete form submission
 */
function mapi_derivative_admin_transform_delete_form_submit($form_id, $form_values) {
  if ($form_values['confirm'] == 1) {
    $tid = $form_values['tid'];
    mapi_transform_delete($tid);
  }

  $derivatives = _mapi_derivatives_cache();

  return (isset($_GET['destination']) ? $_GET['destination'] : MAPI_ADMIN_PATH .'/derivatives/'. $derivatives[$form_values['did']]['line'] .'/transform');
}

/**
 *   Theming functions for the forms
 */
function theme_mapi_derivative_admin_add_form(&$form) {
  $output = '';

  $output .= drupal_render($form['name']) .'<p />';

  $rows = array();
  foreach (element_children($form['exts']) as $type) {
    $row = array();
    $items = array();
    foreach (element_children($form['exts'][$type]) as $ext) {
      $items[] = drupal_render($form['exts'][$type][$ext]);
      $count = count($items);
      if (($count % 5 == 0) && $count) {
        $row[] = $items;
        $items = array();
      }
    }
    if (count($items)) {
      $row[] = array_pad($items, 5, '');
    }

    if (count($row)) {
      // add presenter name
      array_unshift($row[0], array('data' => $type, 'rowspan' => count($row)));
      $rows = array_merge($rows, $row);
    }
  }

  $output .= theme('table', array(t('Type'), array( 'data' => t('Extension'), 'colspan' => 5)), $rows);
  $output .= '<p />';
  $output .= drupal_render($form);

  return $output;
}

