<?php

/**
 * @file
 * Provides an Image Zoom field formatter for Image fields.
 *
 * This module provides a field formatter that allows users to specify an image
 * style to display, and another image style to use as the zoomed version of the
 * image. Hovering the mouse over the image will display the zoomed version,
 * which shifts with mouse movement.
 */

/**
 * Implements hook_libraries_info().
 */
function imagezoom_libraries_info() {
  $libraries['elevatezoom-plus'] = array(
    'name' => 'elevateZoom Plus',
    'vendor url' => 'http://igorlino.github.io/elevatezoom-plus/',
    'download url' => 'https://github.com/igorlino/elevatezoom-plus',
    'version arguments' => array(
      'file' => 'src/jquery.ez-plus.js',
      'pattern' => '/jQuery ezPlus\s+([\d\.]+)/',
      'lines' => 15,
      'cols' => 50,
    ),
    'files' => array(
      'js' => array(
        'src/jquery.ez-plus.js',
      ),
    ),
  );

  return $libraries;
}

/**
 * Implements hook_field_formatter().
 */
function imagezoom_field_formatter_info() {
  $formatters = array(
    'imagezoom' => array(
      'label' => t('Image Zoom'),
      'field types' => array('image'),
      'settings' => array(
        'imagezoom_zoom_type' => '',
        'imagezoom_display_style' => '',
        'imagezoom_zoom_style' => '',
        'imagezoom_additional' => '',
      ),
    ),
  );

  return $formatters;
}

/**
 * Implements hook_field_formatter_settings_form().
 */
function imagezoom_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  $element['imagezoom_zoom_type'] = array(
    '#type' => 'select',
    '#title' => t('Zoom type'),
    '#options' => imagezoom_zoom_types(),
    '#default_value' => $settings['imagezoom_zoom_type'],
  );

  $image_styles = image_style_options(FALSE);
  $element['imagezoom_display_style'] = array(
    '#type' => 'select',
    '#title' => t('Display image style'),
    '#options' => $image_styles,
    '#empty_option' => t('None (original image)'),
    '#default_value' => $settings['imagezoom_display_style'],
  );

  $element['imagezoom_zoom_style'] = array(
    '#type' => 'select',
    '#title' => t('Zoomed image style'),
    '#options' => $image_styles,
    '#empty_option' => t('None (original image)'),
    '#default_value' => $settings['imagezoom_zoom_style'],
  );

  $element['imagezoom_additional'] = array(
    '#type' => 'textarea',
    '#title' => t('Additional settings'),
    '#default_value' => $settings['imagezoom_additional'],
    '#description' => t('Add additional settings. For a list of available options, see the !docs. Settings should be added in the following format: <pre>@code</pre>', array(
      '!docs' => l(t('documentation'), 'http://igorlino.github.io/elevatezoom-plus/api.htm'),
      '@code' => 'option: value')
    ),
    '#weight' => 20,
  );

  return $element;
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function imagezoom_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  $summary = array();

  $zoom_types = imagezoom_zoom_types();
  $summary[] = t('Zoom type: @type', array(
    '@type' => $zoom_types[$settings['imagezoom_zoom_type']],
  ));

  $image_styles = image_style_options(FALSE);
  // Unset possible 'No defined styles' option.
  unset($image_styles['']);
  // Styles could be lost because of enabled/disabled modules that define
  // their styles in code.
  $summary[] = t('Display image style: @style', array(
    '@style' => isset($image_styles[$settings['imagezoom_display_style']]) ?
    $image_styles[$settings['imagezoom_display_style']] : 'original',
  ));
  $summary[] = t('Zoomed image style: @style', array(
    '@style' => isset($image_styles[$settings['imagezoom_zoom_style']]) ?
    $image_styles[$settings['imagezoom_zoom_style']] : 'original',
  ));

  return implode('<br />', $summary);
}

/**
 * Implements hook_field_formatter_view().
 */
function imagezoom_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $display_style = $display['settings']['imagezoom_display_style'];
  $zoom_style = $display['settings']['imagezoom_zoom_style'];

  $settings = array(
    'zoomType' => $display['settings']['imagezoom_zoom_type'],
  );
  $additonal_settings = imagezoom_settings_to_array($display['settings']['imagezoom_additional']);
  $settings += $additonal_settings;

  $context = array(
    'field' => $field,
    'instance' => $instance,
  );
  drupal_alter('imagezoom_settings', $settings, $context);

  $element = array();
  foreach ($items as $delta => $item) {
    $element[$delta] = array(
      '#theme' => 'imagezoom_image',
      '#item' => $item,
      '#display_style' => $display_style,
      '#zoom_style' => $zoom_style,
      '#settings' => $settings,
    );
  }

  return $element;
}

/**
 * Implements hook_theme().
 */
function imagezoom_theme($existing, $type, $theme, $path) {
  return array(
    'imagezoom_image' => array(
      'variables' => array(
        'item' => NULL,
        'display_style' => NULL,
        'zoom_style' => NULL,
        'settings' => NULL,
      ),
      'template' => 'imagezoom_image',
      'path' => $path . '/theme',
    ),
  );
}

/**
 * Preprocess function for imagezoom_image.
 */
function template_preprocess_imagezoom_image(&$variables) {
  $library = libraries_load('elevatezoom-plus');
  if (!$library['loaded']) {
    drupal_set_message($library['error message'], 'error');
  }
  drupal_add_js(array('imagezoom' => $variables['settings']), 'setting');
  drupal_add_js(drupal_get_path('module', 'imagezoom') . '/js/imagezoom.js');

  $item = $variables['item'];

  if ($variables['display_style']) {
    $variables['image'] = image_style_url($variables['display_style'], $item['uri']);
    $info = image_get_info($variables['image']);
  }
  else {
    $variables['image'] = file_create_url($item['uri']);
    $info = image_get_info($item['uri']);
  }

  $variables['width'] = $info['width'];
  $variables['height'] = $info['height'];
  $variables['alt'] = $item['alt'];
  $variables['title'] = $item['title'];

  if ($variables['zoom_style']) {
    $variables['zoom'] = image_style_url($variables['zoom_style'], $item['uri']);
  }
  else {
    $variables['zoom'] = file_create_url($item['uri']);
  }
}

/**
 * Returns an array of available zoom types.
 */
function imagezoom_zoom_types() {
  $types = array(
    'window' => t('Window'),
    'inner' => t('Inner'),
    'lens' => t('Lens'),
  );

  return $types;
}

/**
 * Convert a settings string to an array.
 */
function imagezoom_settings_to_array($string) {
  $array = explode("\n", $string);
  $settings = array();

  foreach ($array as $option) {
    $parts = explode(':', $option);
    $key = trim($parts[0]);
    $value = trim($parts[1]);
    $settings[$key] = $value;
  }

  return $settings;
}
