<?php
// $Id: audio_attach.module,v 1.2 2007/02/19 18:37:37 zirafa Exp $

/**
 * @file audio_attach.module
 */

/**
 * Implementation of hook_help().
 */
function audio_attach_help($section) {
  switch ($section) {
    case 'admin/help#audio_attach':
      return t('<p>Allows audio files to be attached to any content type.  You can configure which content types by going to admin/content/types.</p>');
      break;
  }
} 

/**
 *  Implementation of hook_menu
 */
function audio_attach_menu($may_cache) {
  $items = array();

  if ($may_cache) {
  }
  elseif (arg(0) == 'audio_attach' && is_numeric(arg(2))) {
    $node = node_load(arg(2));
    // audio_attach/[op]/[node_id]/[audio_id]/[weight]
    $items[] = array(
      'path' => 'audio_attach',
      'callback' => 'audio_attach_action',
      'callback_arguments' => array(arg(1), arg(2), arg(3), arg(4)),
      'access' => node_access('update', $node),
      'type' => MENU_CALLBACK,
    );
  }
  return $items;
}

/**
 * implementation of hook_form_alter()
 */
function audio_attach_form_alter($form_id, &$form) {

  switch ($form_id) {
    // checkbox in the node's content type configuration page.
    case 'node_type_form':
      if(isset($form['identity']['type'])) {
          $form['workflow']['audio_attach'] = array(
            '#type' => 'radios', 
            '#title' => t('Attach audio files'),
            '#default_value' => variable_get('audio_attach_'. $form['#node_type']->type, 0),
            '#options' => array(t('Disabled'), t('Enabled')),
            '#description' => t('Should this node allows users to attach audio files?')
          );
        }
      break;
   
    // if enabled adjust the form
    case $form['type']['#value'] . '_node_form':
      if (variable_get('audio_attach_' . $form['type']['#value'], 0)) {
        $node = $form['#node'];
        $form['#attributes'] = array("enctype" => "multipart/form-data");
        $form['audio_attach'] = array('#type' => 'fieldset', '#title' => t('Attached audio files'), '#collapsible' => TRUE);
        $form['audio_attach']['existing_files']= _audio_existing_file_form();
        if (is_array($node->audio_attach)) {
          foreach($node->audio_attach as $weight => $aid) {
            $items[] = theme('audio_attach_list_item', $node->nid, $weight, $aid);
          }
          $form['audio_attach']['audio_list'] = array(
            '#type' => 'item', 
            '#value' => theme('audio_attach_sortable_list', $items,  null, 'ul', array('id' => 'audio-attach-sortable-list'))
          );
        }
        if ($node->audio_aid) {
          $form['audio_attach']['audio_aid'] = array('#type' => 'hidden', '#value' => $node->audio_aid);
        }        

        $form['audio_attach']['audio_upload'] = array(
          '#type' => 'file', 
          '#title' => t('Add a new audio file'),
          '#description' => t('Click "Browse..." to select an audio file to upload. <strong>NOTE:</strong> the current PHP configuration limits uploads to %maxsize. ', array('%maxsize' => format_size(file_upload_max_size()))),
        );
        $form['audio_attach']['audio_title'] = array(
          '#type' => 'textfield', 
          '#title' => t('Title'),
          '#default_value' => variable_get('audio_default_title_format', '!title by !artist')
        );
        $form['audio_attach']['audio_publish'] = array(
          '#type' => 'checkbox', 
          '#title' => t('Published'),
          '#return_value' => 1,
          '#default_value' => 1,
          '#description' => t('If checked, this audio file will be published to the rest of the site.')
        );
        $form['#after_build'] = array('_audio_attach_skip_validation');
      }
      break;
  }
}

function _audio_attach_skip_validation($form, $edit) {
  if ($_POST['op'] == t('Search for audio')) {
    _product_skip_validation($form);
  }
  return $form;
}

function _audio_skip_validation(&$element) {
  foreach (element_children($element) as $key) {
    if (isset($element[$key]) && $element[$key]) {
      _product_skip_validation($element[$key]);
    }
  }
  $element['#validated'] = TRUE;
}

function _audio_existing_file_form(){
	$settings = audio_get_tag_settings();
	$form  = array('#tree' => TRUE);
	foreach ($settings as $tag => $setting) {
		$form[$tag]['check'] ['#theme'] = 'audio_horizontal_checkbox';
		$form[$tag]['check'] = array(
      		'#title' => $tag,
			'#type' => 'checkbox',
      		'#default_value' => 1,
      		'#theme' => 'audio_horizontal_checkbox',
        );
   	}
   	$form["text"] = array(
          	'#type' => 'textfield', 
          	'#title' => t('Text to search')
     );	
   	$form['search']= array('#type' => 'button','#value' => t('Search for audio'));
	return $form;
}

function theme_audio_horizontal_checkbox($e) {
    $checkbox = '<span>';
    $checkbox .= '<input type="checkbox" name="'.$e['#name'].'" id="'.$e['#id'].'" value="'.$e['#return_value'].'" ';
    $checkbox .= $e['#value'] ? ' checked="checked" ' : ' ';
    $checkbox .= drupal_attributes($e['#attributes']). ' />';
    if (!is_null($e['#title'])) {
        $checkbox .= '<label for="'.$e['#id'].'">'.$e['#title'].'</label>';
    }
    $checkbox .= "</span>\n";
    unset($e['#title']);
    return $checkbox;
}
/**
* Implementation of hook_nodeapi().
*/
function audio_attach_nodeapi(&$node, $op, $teaser, $page) {
  global $user;
  // delete all references from other nodes if audio node is deleted 24/08/2006 sun
  if ($node->type == 'audio' && $op == 'delete'){
    db_query("DELETE FROM {audio_attach} WHERE aid = %d", $node->nid);
    return;
  }
  if ($node->type == 'audio' || !variable_get("audio_attach_$node->type", 0)){
    return;
  }
  switch ($op) {
    case 'prepare':
      $audio->title_format = $_POST['edit']['audio_title'];  
      $audio->status = $_POST['edit']['audio_publish'] ? 1 : 0;
      $audio->uid = $user->uid;
      $audio->name = $user->name;
      $audio->type = 'audio';
      audio_prepare($audio);
      if ($audio->audio_file) {
        node_validate($audio);
        if (!form_get_errors()) {
          $audio = node_submit($audio);
          node_save($audio);
          $node->audio_aid = $audio->nid;
        }
      }
      break;

    case 'insert':
    case 'update':
      if ($node->audio_aid) {
        audio_attach_add_child($node->nid, $node->audio_aid);
      }
      break;

    case 'delete':
      audio_attach_remove($node->nid);
      break;

    case 'load':
      $audio_attach = audio_attach_get_children($node->nid);
      return array('audio_attach' => $audio_attach);

    case 'view':
      if (is_array($node->audio_attach) && count($node->audio_attach) > 0) {
        $node->content['attach_audio'] = array(
          '#value' => theme('audio_attach_list', $node->audio_attach, $teaser),
          '#weight' => 10,
        );
      }
      break;
  }
}

/**
 *  Menu callback, perform an action on attachments
 */
function audio_attach_action($op, $nid = null, $aid = null, $weight = null) {
  switch($op) {
    case 'add':
      audio_attach_add_child($nid, $aid);
      break;
    case 'load':
      return audio_attach_get_children($nid);
    case 'remove':
      audio_attach_remove_child($aid, $nid, $weight);
      drupal_goto();
      break;
    case 'save_order':
    _audio_attach_save_order($nid);
     break;
 
  }
}

/**
 *  Theme used if multiple files are attached
 */
function theme_audio_attach_list($nids, $teaser = FALSE) {
  drupal_add_css(drupal_get_path('module', 'audio_attach') .'/audio_attach.css');
  foreach ($nids as $aid) {
    $audio = node_load($aid);
    $audio = node_prepare($audio, $teaser);
    $title = $audio->status ? l($audio->title, 'node/' . $audio->nid, NULL, NULL, NULL, TRUE) : check_plain($audio->title);
    $items[] = '<div class="title">'. $title .'</div>'. theme('audio_teaser', $audio);
  }
  return theme('item_list', $items, null, 'ol', array('class' => 'audio-attach-list'));
}




/******* These functions are mostly copied from the original playlist.module. **************/

/**
 *  Input a parent node id, and return an array of children id's ordered by their weight.         
 **/
function audio_attach_get_children($nid) { 
  $children = array();
  $result = db_query("SELECT aid, weight FROM {audio_attach} WHERE nid = %d ORDER BY weight ASC", $nid);
  while($row = db_fetch_object($result)) {
    $children[$row->weight] = $row->aid; 
  }
  return $children;
}


/**
 *  Swaps the weights of two children in a given playlist. Returns true if successful.
 */
function audio_attach_swap_weight($nid, $aid_1, $aid_2) {
  $weight_1 = audio_attach_get_weight($nid, $aid_1);  
  $weight_2 = audio_attach_get_weight($nid, $aid_2);
  if(($weight1 > -1) && ($weight2 > -1)) {
    audio_attach_set_weight($nid, $aid_1, $weight_2);
    audio_attach_set_weight($nid, $aid_2, $weight_1);
    return 1;
  }
  else {
    return 0;
  }
}

/**
 *   Set weight of an audio file directly.
 **/
function audio_attach_set_weight($nid, $aid, $weight) {
  $result = db_query("UPDATE {audio_attach} SET weight = %d WHERE nid = %d AND aid = %d", $weight, $nid, $aid); 
  return db_affected_rows($result);
} 
 
/**
 *   Get current weight of the audio file in the list
 **/
function audio_attach_get_weight($nid, $aid) {
  $weight = db_result(db_query("SELECT weight FROM {audio_attach} WHERE nid = %d AND aid = %d", $nid, $aid));
  return is_null($weight) ? -1 : $weight;  //we return -1 as a FAIL status code since 0 is used as a weight.
} 

/**
 *   Get next weight in a given list. 
 **/
function audio_attach_get_next_weight($nid) {
  $max = db_result(db_query("SELECT MAX(weight) FROM {audio_attach} WHERE nid = %d LIMIT 1", $nid));
  return (is_null($max)) ? 0 : ++$max;
}

/**
 *  Add a new child to a parent node
 */
function audio_attach_add_child($nid, $aid, $stack_bottom = TRUE) {
  $weight = audio_attach_get_next_weight($nid);
  $result = db_query("INSERT INTO {audio_attach} (nid, aid, weight) VALUES (%d, %d, %d)", $nid, $aid, $weight); 
} 

/**
 *  Delete a child node from a given parent node.  If no parent node is specified, it deletes the child from all parent nodes.  Returns true if successful.
 */
function audio_attach_remove_child($aid, $nid, $weight) {
  $result = db_query("DELETE FROM {audio_attach} WHERE nid = %d AND aid = %d AND weight = %d", $nid, $aid, $weight);
  return db_affected_rows($result);
}

/**
 *  Delete a parent node. Returns true if successful.  
 */
function audio_attach_remove($nid) {
  $result = db_query("DELETE FROM {audio_attach} WHERE nid = %d", $nid);
  return db_affected_rows($result);
} 

/**
 * Menu callback that saves the order of the audio files.  Depends on javascript functions as well as list output.
 * Called via AJAX
 */
function _audio_attach_save_order($nid){
  $items = $_REQUEST['audio-attach-sort-list'];
  foreach ($items as $aid) {
  	audio_attach_set_weight($nid, (int)$aid, $i++); 
  }
  drupal_set_message("Your changes have been saved.");
  print theme('status_messages');
}

/**
 *  Create a sortable list
 */
function theme_audio_attach_sortable_list($items = array(), $title = NULL, $type = 'ul', $attributes = NULL) {
  drupal_add_css(drupal_get_path('module', 'audio_attach') .'/audio_attach.css');
  //drupal_add_js(drupal_get_path('module', 'audio_attach') .'/scripts/interface.js');
  //drupal_add_js(drupal_get_path('module', 'audio_attach') .'/scripts/sort.js');
  
  $output = '';
  if ( is_array($items) ){
	  $output .= '<ul '.drupal_attributes($attributes).'>';
	  foreach ($items as $item) {
	    $output .= '<li class="sortableitem">'. $item .'</li>' ;
	  }
	  $output .= '</ul>';
  }
  return $output;
}
 

/* Builds one list item in the list of attached files.*/
function theme_audio_attach_list_item($nid, $weight, $aid) {
  $audio = node_load($aid);
  $drag = theme('image', drupal_get_path('module', 'audio_attach') .'/images/drag_me.gif');
  $link = l($audio->title, 'node/' . $audio->nid, NULL, NULL, NULL, TRUE);  
  $trashcan = l(theme('image', drupal_get_path('module', 'audio_attach') .'/images/icon_delete.gif'), "audio_attach/remove/$nid/$aid/$weight", array(), drupal_get_destination(), null, false, true);
  return $drag .' '. $link . ' ' . $trashcan;
}

/*
      $weight = playlist_get_weight($parent_id, $child_id);
      $up   = $children[$count - 1] ? $children[$count-1] : $child_id;
      $down = $children[$count + 1] ? $children[$count+1] : $child_id;
      */