<?php
// $Id: audio_images.module,v 1.22 2008/05/25 17:21:26 drewish Exp $

include_once drupal_get_path('module', 'audio') .'/audio_image.inc';

/**
 * Implementation of hook_menu().
 */
function audio_images_menu() {
  $items = array();
  $items['admin/settings/audio/images'] = array(
    'title' => 'Images',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('audio_images_admin_settings'),
    'access arguments' => array('administer site configuration'),
    'file' => 'audio_images.admin.inc',
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

/**
 * Implementation of hook_theme
 */
function audio_images_theme() {
  return array(
    'audio_images_form' => array(
      'arguments' => array('form'),
    ),
    'audio_images' => array(
      'arguments' => array('audio_images'),
    ),
    'audio_image' => array(
      'arguments' => array('images'),
    ),
  );
}

/**
 * Implementation of hook_file_download().
 */
function audio_images_file_download($filename) {
  $filepath = file_create_path($filename);

  // Check if it's one of our files.
  $nid = db_result(db_query("SELECT ai.nid FROM {audio_image} ai WHERE ai.filepath = '%s'", $filepath));
  if ($nid && $node = node_load($nid)) {
    // Make sure they're allowed to view the node.
    if (node_access('view', $node)) {
      $info = image_get_info($filepath);
      return array(
        'Content-Type: '. mime_header_encode($info['mime_type']),
        'Content-Length: '. (int) $info['file_size'],
      );
    }

    // Access denied.
    return -1;
  }
}

/**
 * Implementation of hook_form_alter().
 *
 * Here we add our image fields to the audio node form.
 */
function audio_images_form_alter(&$form, &$form_state, $form_id) {
  // We only alter audio node edit forms.
  if ($form_id == 'audio_node_form') {
    $form['#submit'][] = 'audio_images_node_submit';

    $node = $form['#node'];

    $form['audio_images'] = array(
      '#type' => 'fieldset', '#title' => t('Audio Images'),
      '#collapsible' => TRUE,
      '#description' => t('Cover art or other images.'),
      '#weight' => 0,
      '#tree' => TRUE,
    );

    if (isset($node->audio_images)) {
      $form['audio_images']['#theme'] = 'audio_images_form';
      foreach ((array) $node->audio_images as $pid => $image) {
        dvm($image);
        $form['audio_images'][$pid]['pid'] = array('#type' => 'value', '#value' => $pid);
        $form['audio_images'][$pid]['pictype'] = array('#type' => 'value', '#value' => $image['pictype']);
        $form['audio_images'][$pid]['filepath'] = array('#type' => 'value', '#value' => $image['filepath']);
        $form['audio_images'][$pid]['filemime'] = array('#type' => 'value', '#value' => $image['filemime']);
        $form['audio_images'][$pid]['filesize'] = array('#type' => 'value', '#value' => $image['filesize']);
        $form['audio_images'][$pid]['height'] = array('#type' => 'value', '#value' => $image['height']);
        $form['audio_images'][$pid]['width'] = array('#type' => 'value', '#value' => $image['width']);
        $form['audio_images'][$pid]['delete'] = array('#type' => 'checkbox', '#default_value' => $image['delete']);
      }
    }

    $form['audio_images']['new']['pictype'] = array(
      '#type' => 'select',
      '#title' => t('New image type'),
      '#value' => variable_get('audio_image_default_type', 0x03),
      '#options' => audio_image_type_dirty_array(),
    );
    $form['audio_images']['new']['audio_image_upload'] = array(
      '#type' => 'file',
      '#title' => t('Add a new image'),
      '#tree' => FALSE,
      '#description' => t('Click "Browse..." to select an image to add to this audio file. <strong>NOTE:</strong> Supported image types include GIF, JPG, and PNG.  Suggested dimensions: 170 X 170 pixels.'),
    );
  }
}

/**
 * Theme function to format the audio image fieldset.
 */
function theme_audio_images_form(&$form) {
  $pictypes = audio_image_type_dirty_array();
  $rows = array();
  foreach (element_children($form) as $pid) {
    if ($pid != 'new') {
      $rows[] = array(
        l($pictypes[$form[$pid]['pictype']['#value']], $form[$pid]['filepath']['#value']),
        $form[$pid]['filemime']['#value'],
        $form[$pid]['height']['#value'] .'x'. $form[$pid]['width']['#value'],
        $form[$pid]['filesize']['#value'],
        drupal_render($form[$pid]['delete']),
      );
    }
  }
  $header = array(t('Type'), t('MIME Type'), t('Dimensions'), t('Size'), t('Delete'));
  return theme('table', $header, $rows) . drupal_render($form);
}

/**
 * Node submit handler
 */
function audio_images_node_submit($form, &$form_state) {
  $node = (object) $form_state['values'];

  // Check for an uploaded image.
  $validators = array('file_validate_is_image' => array());
  if ($file = file_save_upload('audio_image_upload', $validators)) {
    $pictype = (integer) $form_state['values']['audio_images']['new']['pictype'];

    if ($image = audio_image_from_file($file->filepath, $pictype)) {
      $pid = 'new_'. count($form_state['values']['audio_images']);
      $image['pid'] = $pid;
      $form_state['values']['audio_images'][$pid] = $image;
    }
  }
}

/**
 * Implementation of hook_nodeapi().
 */
function audio_images_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  switch ($op) {
    case 'load':
      return audio_images_nodeapi_load($node);
    case 'insert':
      return audio_images_nodeapi_insert($node);
    case 'update':
      if ($node->revision) {
        return audio_images_nodeapi_insert_revision($node);
      }
      return audio_images_nodeapi_update($node);
    case 'delete':
      return audio_images_nodeapi_delete($node);
    case 'delete revision':
      return audio_images_nodeapi_delete_revision($node);
  }
}

function audio_images_nodeapi_load($node) {
  $ret['audio_images'] = array();
  $result = db_query("SELECT pid, pictype, filemime, width, height, filepath, filesize FROM {audio_image} WHERE vid=%d", $node->vid);
  while ($img = db_fetch_array($result)) {
    $ret['audio_images'][$img['pid']] = $img;
  }
  return $ret;
}

function audio_images_nodeapi_insert(&$node) {
  // Add new images.
  foreach ((array)$node->audio_images as $pid => $image) {
    if (_audio_images_istemp($image['pid'])) {
      _audio_images_save_new($node, $image);
    }
  }
}

function audio_images_nodeapi_insert_revision(&$node) {
  foreach ((array)$node->audio_images as $pid => $image) {
    // Deletions.
    if ($image['delete']) {
      _audio_images_delete($pid, $image['filepath']);
    }
    // Additions.
    else if (_audio_images_istemp($image['pid'])) {
      _audio_images_save_new($node, $image);
    }
    // Make copies of unchanged images.
    else {
      _audio_images_save_copy($node, $image);
    }
  }
}

function audio_images_nodeapi_update(&$node) {
  foreach ((array)$node->audio_images as $pid => $image) {
    // Deletions.
    if ($image['delete']) {
      _audio_images_delete($pid, $image['filepath']);
    }
    // Additions.
    else if (_audio_images_istemp($image['pid'])) {
      _audio_images_save_new($node, $image);
    }
  }
}

function audio_images_nodeapi_delete(&$node) {
  // Delete any associated previews.
  _audio_images_delete_previews($node);

  // Delete the image files and remove them from the database.
  $result = db_query('SELECT filepath FROM {audio_image} WHERE nid = %d', $node->nid);
  while ($file = db_fetch_object($result)) {
    file_delete($file->filepath);
  }
  db_query('DELETE FROM {audio_image} WHERE nid = %d', $node->nid);
}

function audio_images_nodeapi_delete_revision(&$node) {
  // Delete any associated previews.
  _audio_images_delete_previews($node);

  // Delete the image files and remove them from the database.
  $result = db_query('SELECT filepath FROM {audio_image} WHERE vid = %d', $node->vid);
  while ($file = db_fetch_object($result)) {
    file_delete($file->filepath);
  }
  db_query('DELETE FROM {audio_image} WHERE vid = %d', $node->vid);
}

/**
 * Is an image a temporary preview?
 *
 * @param $pid
 *   Mixed, string or integer.
 * @return
 *   Boolean indicating if the image is a temporary preview.
 */
function _audio_images_istemp($pid) {
  return (strpos($pid, 'new') !== FALSE);
}

/**
 * Adds an image to the audio_image table and moves it to the audio/images
 * directory.
 */
function _audio_images_save_new(&$node, $image) {
  $temppath = $image['filepath'];
  _audio_images_save_copy($node, $image);
  file_delete($temppath);
}

/**
 * Save an image to the audio_image table and copies it to the audio/images
 * directory.
 *
 * The caller needs to delete original image file if it was a temporary.
 */
function _audio_images_save_copy(&$node, $image) {
  $newpath = _audio_image_filename($node->vid, $image['filemime'], $image['pictype'], FALSE);
  if (file_copy($image['filepath'], $newpath, FILE_EXISTS_REPLACE)) {
    db_query("INSERT INTO {audio_image} (nid, vid, pictype, filemime, width, height, filepath, filesize)
      VALUES (%d, %d, %d, '%s', %d, %d, '%s', %d)",
      $node->nid, $node->vid, $image['pictype'], $image['filemime'],
      $image['width'], $image['height'], $newpath, filesize($newpath));

    $image['filepath'] = $newpath;
    $image['pid'] = db_last_insert_id();
    $node->audio_images[$image['pid']] = $image;
  }
}

function _audio_images_delete($pid, $filepath) {
  file_delete($filepath);
  // Delete from the database if it's not a preview.
  if (!_audio_images_istemp($pid)) {
    db_query("DELETE FROM {audio_image} WHERE pid = %d", $pid);
  }
}

/**
 * Delete any preview images associated with the node.
 */
function _audio_images_delete_previews(&$node) {
  foreach ((array)$node->audio_images as $pid => $image) {
    if (_audio_images_istemp($pid)) {
      file_delete($image['filepath']);
      unset($node->audio_images[$pid]);
    }
  }
}

/**
 * Returns the array of the default image type.
 *
 * If no default image is found, returns a random image array.
 */
function audio_images_get($audio_images, $pictype = NULL) {
  if (is_null($pictype)) {
    $pictype = variable_get('audio_default_image_type', 0x03);
  }
  if (is_array($audio_images)) {
    foreach ($audio_images as $image) {
      if ($image['pictype'] == $pictype) {
        return $image;
      }
    }
    // The specified image was not found, return a random image.
    return $audio_images[array_rand($audio_images)];
  }
  return FALSE;
}

/**
 * Create a block for audio images.
 *
 * @param $audio_images
 *   The node's array of images
 */
function theme_audio_images($audio_images) {
  if ($image = audio_images_get($audio_images)) {
    return "<div class='audio-image'>\n". theme('audio_image', $image) ."\n</div>\n";
  }
}

/**
 * Create an <img> element for an audio image.
 */
function theme_audio_image($image) {
  $url = file_create_url($image['filepath']);
  $alt = audio_image_type_dirty_array($image['pictype']);

  list($width, $height) = @getimagesize($image['filepath']);
  $attributes = array('width' => $width, 'height' => $height);

  return theme('image', $url, $alt, '', $attributes, FALSE);
}
