<?php
// $Id$

/**
 *  Implementation of hook_mapi_extensions()
 */
function mapi_image_mapi_extensions($op, $name, &$data, $read) {
  $list = array(
    'gif' => 'image/gif',
    'png' => 'image/png',
    'jpg' => 'image/jpeg',
  );

  switch ($op) {
    case 'list':
      return array_keys($list);
    case 'mime':
      return $list[$name];
    case 'metadata':
      // NEEDS WORK: Get the metadata information for the filename
      break;
    case 'dimensions':
      $info = image_get_info($name);

      return array(
        'height' => $info['height'],
        'width' => $info['width']
      );
  }
}

/**
 *  Implementation of hook_mapi_types()
 */
function mapi_image_mapi_types($op, $type = null, $edit = null) {
  switch ($op) {
    // list of defined types for the module
    case 'list':
      return array('image');

    // list of extensions for the particular type
    case 'extensions':
      return array('png', 'gif', 'jpg');

    // information regarding the type
    case 'info':
      return array(
        'image' => array(
          'title' => t('Image'),
          'description' => t('These are image files.'),
        ),
      );

    // provides the form details for the type
    case 'configure':
      break;

    // validates the form details from configure
    case 'validate':
      break;

    // allows intervention to convert form return values into something more appropriate for storage
    case 'save':
      break;
  }
}

/**
 *  Implementation of hook_mapi_transforms()
 */
function mapi_image_mapi_transforms($op, $transform, $data, $file) {
  switch ($op) {
    // provide standard transforms
    case 'list':
      switch ($transform) {
        case 'crop':
        case 'scale':
        case 'resize':
          return array('jpg', 'gif', 'png');
        default:
          return array('crop', 'scale', 'resize');
      }
      break;

    case 'info':
      $list = array(
        'crop' => array(
          'description' => t('Allows cropping of images to specific boundaries.'),
        ),
        'scale' => array(
          'description' => t('Resizes a picture, keeping the original aspect ratio.'),
        ),
        'resize' => array(
          'description' => t('Resizes the picture to a specified setting.'),
        ),
      );
      if (array_key_exists($transform, $list)) {
        return $list[$transform];
      }
      return $list;
    case 'test':
      switch ($file) {
        case 'jpg':
        case 'gif':
        case 'png':
          return $file;
      }
      break;

    case 'defaults':
      $items = array('width' => '100%', 'height' => '100%');
      if ($transform == 'scale') {
        $items['fit'] = 'inside';
      }
      elseif ($transform == 'crop') {
        $items['xoffset'] = 'left';
        $items['yoffset'] = 'top';
      }
      return $items;
    case 'form':
      if ($transform == 'scale') {
        $helptext = array();
        $helptext['inside'] = t('<strong>Inside dimensions</strong>: Final dimensions will be less than or equal to the entered width and height. Useful for ensuring a maximum height and/or width.');
        $helptext['outside'] = t('<strong>Outside dimensions</strong>: Final dimensions will be greater than or equal to the entered width and height. Ideal for cropping the result to a square.');
        $description = '<ul><li>'. implode('</li><li>', $helptext) .'</li><ul>';

        $form['fit'] = array(
          '#type' => 'select',
          '#title' => t('Scale to fit'),
          '#options' => array('inside' => t('Inside dimensions'), 'outside' => t('Outside dimensions')),
          '#default_value' => (isset($data['fit']) ? $data['fit'] : 'inside'),
          '#weight' => 1,
          '#description' => $description,
        );
      }

      $form['width'] = array(
        '#type' => 'textfield',
        '#title' => t('Width'),
        '#default_value' => (isset($data['width']) ? $data['width'] : '100%'),
        '#description' => t('Enter a width in pixels or as a percentage. i.e. 500 or 80%.'),
      );

      $form['height'] = array(
        '#type' => 'textfield',
        '#title' => t('Height'),
        '#default_value' => (isset($data['height']) ? $data['height'] : '100%'),
        '#description' => t('Enter a height in pixels or as a percentage. i.e. 500 or 80%.'),
      );

      if ($transform == 'crop') {
        $form['xoffset'] = array(
          '#type' => 'textfield',
          '#title' => t('X Offset'),
          '#default_value' => (isset($data['yoffset']) ? $data['xoffset'] : 'left'),
          '#description' => t('Enter an offset in pixels or use a keyword: <em>left</em>, <em>center</em>, or <em>right</em>.'),
        );

        $form['yoffset'] = array(
          '#type' => 'textfield',
          '#title' => t('Y Offset'),
          '#default_value' => (isset($data['yoffset']) ? $data['yoffset'] : 'top'),
          '#description' => t('Enter an offset in pixels or use a keyword: <em>top</em>, <em>center</em>, or <em>bottom</em>.'),
        );
      }

      return $form;
      break;
    case 'validate':
      if (!preg_match("/^\d+(%|)$/", $data['height'])) {
        form_set_error('height', t('Height must be a number, or a percentage.'));
      }
      // check if number or percentage
      if (!preg_match("/^\d+(%|)$/", $data['width'])) {
        form_set_error('width', t('Width must be a number, or a percentage.'));
      }
      if ($transform == 'crop') {
        //
        if (!preg_match("/^(\d+|left|center|right)$/i", $data['xoffset'])) {
          form_set_error('xoffset', t('XOffset must be either a number, or left, center, or right.'));
        }
        //
        if (!preg_match("/^(\d+|top|center|bottom)$/i", $data['yoffset'])) {
          form_set_error('yoffset', t('YOffset must be either a number, or top, center, or bottom.'));
        }
      }
      break;
    case 'transform':
      // get necessary information from the data
      $dest = (isset($data['dest']) ? $data['dest'] : $file);
      $data = (isset($data['settings']) ? $data['settings'] : array());

      // get the details, since we may need to change things
      $details = image_get_info($file);

      $data['width'] = ($data['width'] ? $data['width'] : $details['width']);
      $data['height'] = ($data['height'] ? $data['height'] : $details['height']);

      // readjust for percentages
      $width = (substr($data['width'], -1) == '%' ? ($details['width'] / 100) * trim($data['width'], '%') : $data['width']);
      $height = (substr($data['height'], -1) == '%' ? ($details['height'] / 100) * trim($data['height'], '%') : $data['height']);

      if ($transform == 'scale') {
        // now check for the fit
        if ($data['fit'] == 'outside') {
          $ratio = $details['width'] / $details['height'];
          $new_ratio = $width / $height;
          $width = ($ratio > $new_ratio ? 0 : $width);
          $height = ($ratio < $new_ratio ? 0 : $height);
        }
        // set impossibly large values if the width and height aren't set.
        $width = $width ? $width : 9999999;
        $height = $height ? $height : 9999999;
      }

      // otherwise perform the action
      switch ($transform) {
        case 'scale':
          // NEEDS WORK: fixup the < into <= so that same size gets copied
          // doesn't scale up, so simply copy the file to the location
          if ($details['height'] < $height && $details['width'] < $width) {
            $result = ($file != $dest ? @copy($file, $dest) : true);
          }
          else {
            $result = image_scale($file, $dest, $width, $height);
          }
          break;
        case 'crop':
          $result = image_crop($file, $dest, $data['xoffset'], $data['yoffset'], $width, $height);
          break;
        case 'resize':
          $result = image_resize($file, $dest, $width, $height);
          break;
      }

      // failure should be reported
      if (!$result) {
        mapi_error(t('Transform failed [%transform] on [%file]', array('%transform' => $transform, '%file' => $dest)));
      }

      // always return generated filename
      return $dest;
  }
}
