<?php
// ; $Id$

/**
 * @file
 * Enables BOINC team forum functionality.
 *
 * Allows forums to be created for any BOINC team
 */


/*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
 * Includes that provide supporting functions
 *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */

require_once('includes/boincteam_forum.forms.inc');
//require_once('includes/boincteam_forum.helpers.inc');


/*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
 * Hooks into core modules
 *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */

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

  return $items;
}

/**
* Implementation of hook_form_alter()
*/
function boincteam_forum_form_alter(&$form, $form_state, $form_id) {
  switch ($form_id) {
  // Team forum node edit form
  case 'team_forum_node_form':

    // Internal fields to indicate where these changes are taking place
    array_unshift($form, array(
      'tfid' => array(
        '#type' => 'hidden',
        '#value' => arg(3),
      ),
    ));
    break;

  default:
  }
}

/**
 * Implementation of hook_nodeapi(); add custom actions to node operations
 * Obsolete in Drupal 7...
 */
function boincteam_forum_nodeapi(&$node, $op, $a3 = null, $a4 = null) {
  // In Drupal 7, these operation cases will all exist as their own hooks,
  // so let's approximate that here so that this function can simply be removed
  // upon migration to 7
  switch($op) {
  case 'insert':
    boincteam_forum_node_insert($node);
    break;
  case 'load':
    boincteam_forum_node_load($node);
    break;
  case 'update':
    boincteam_forum_node_update($node);
    break;
  case 'validate':
    boincteam_forum_node_validate($node);
    break;
  case 'view':
    boincteam_forum_node_view($node);
    break;
  default:
  }
}

/**
 * Implementation of hook_node_insert(); add custom actions when a node
 * is inserted (forward compatible to Drupal 7)
 */
function boincteam_forum_node_insert($node) {
  switch($node->type) {
  case 'team_forum':
    $account = user_load($node->uid);
    $team_id = boincteam_forum_lookup_nid($node->tfid);
    if ($account->team == $team_id) {
      db_query("
        INSERT INTO {boincteam_forum_node} SET
          nid = %d,
          tfid = %d",
        $node->nid, $node->tfid
      );
    }
    unset($node->tfid);
    break;
  default:
  }
}

/**
 * Implementation of hook_node_load(); add custom actions when a node
 * is loaded (forward compatible to Drupal 7)
 */
function boincteam_forum_node_load($node) {
  switch($node->type) {
  case 'team_forum':
    $node->tfid = db_result(db_query("
      SELECT tfid FROM {boincteam_forum_node}
      WHERE nid = %d", $node->nid
    ));
    break;

  default:

  }
}

/**
 * Implementation of hook_node_update(); add custom actions when a node
 * is updated (forward compatible to Drupal 7)
 */
function boincteam_forum_node_update($node) {
  switch($node->type) {
  case 'team_forum':

    break;

  default:

  }
}

/**
 * Implementation of hook_node_validate(); add custom actions when a node
 * is validated (forward compatible to Drupal 7)
 */
function boincteam_forum_node_validate($node) {
  switch($node->type) {
  case 'team_forum':
    $account = user_load($node->uid);
    // Get tfid from node, but if empty/null, get it from the database
    if (!($node->tfid)) {
        $tfid = db_result(db_query("
      SELECT tfid FROM {boincteam_forum_node}
      WHERE nid = %d", $node->nid
        ));
    } else {
        $tfid = $node->tfid;
    }
    $team_id = boincteam_forum_lookup_nid($tfid);
    if (!$account->team OR $account->team != $team_id) {
      drupal_set_message(t('Failed to add team forum topic.'), 'error');
      drupal_goto('community/forum');
    }
    break;
  default:
  }
}

/**
 * Implementation of hook_node_view(); add custom actions when a node
 * is viewed (forward compatible to Drupal 7)
 */
function boincteam_forum_node_view($node) {
  switch($node->type) {
  case 'team_forum':
    $team_id = boincteam_forum_lookup_nid($node->tfid);
    $public_forum = boincteam_forum_is_public($node->tfid);
    $is_member = boincteam_is_member($team_id);
    $is_global_moderator = boincteam_forum_is_global_moderator();
    if (!$public_forum AND !$is_member AND !$is_global_moderator) {
      drupal_not_found();
      module_invoke_all('exit');
      exit();
    }
    break;
  default:
  }
}

/**
* Implementation of hook_views_api().
*/
function boincteam_forum_views_api() {
  return array(
    'api' => 2.0,
    'path' => drupal_get_path('module', 'boincteam_forum')
  );
}

/**
 * Implementation of hook_perm()
 */
function boincteam_forum_perm() {
  return array('manage boincteam forum');
}


/*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
 * BOINC team forum functions
 *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */

/*
 * Check if the user has global access to moderate team forums
 */
function boincteam_forum_is_global_moderator() {
  global $user;
  return user_access('manage boincteam forum');
}

/*
 * Check if any forums for a team are public
 */
function boincteam_forum_is_any_public($team_id) {
  $forums = boincteam_forum_list($team_id);
  foreach ($forums as $forum) {
    if ($forum->public) {
      return TRUE;
    }
  }
  return FALSE;
}

/*
 * Check if a team forum should be visible to everyone
 */
function boincteam_forum_is_public($tfid) {
  return db_result(db_query("
    SELECT public FROM {boincteam_forum} WHERE tfid=%d", $tfid
  ));
}

/*
 * Load the forums for a team, if any exist
 */
function boincteam_forum_list($team_id = NULL) {
  if (!$team_id) {
    global $user;
    $account = user_load($user->uid);
    $team_id = $account->team;
  }
  $team_forums = array();
  if ($team_id) {
    // Load any team forum objects for the user's team
    $result = db_query("
      SELECT tfid, nid, title, description, created, updated, public,
        min_time_between_posts, min_total_credit_to_post, min_avg_credit_to_post
      FROM {boincteam_forum} WHERE nid=%d", $team_id
    );
    $row = 0;
    while ($team_forum = db_fetch_object($result)) {

      $team_forum->link = url("community/teams/{$team_id}/forum/{$team_forum->tfid}");
      $team_forum->zebra = $row % 2 ? 'even' : 'odd';
      $team_forum->new_topics = 0; // TODO: Track user views of team topics
      $team_forum->new_text = '';
      $team_forum->new_url = '';
      $team_forum->num_topics = db_result(db_query("
        SELECT COUNT(nid) FROM {boincteam_forum_node}
        WHERE tfid = %d",
        $team_forum->tfid
      ));
      $team_forum->num_posts = db_result(db_query("
        SELECT COALESCE(SUM(ncs.comment_count),0) + COUNT(ncs.nid)
        FROM {boincteam_forum_node} bfn
        JOIN {node_comment_statistics} ncs ON ncs.nid = bfn.nid
        JOIN {node} n ON n.nid = ncs.nid
        WHERE bfn.tfid = %d AND n.status = 1",
        $team_forum->tfid
      ));
      $last_post = new stdClass();
      $last_post->timestamp = db_result(db_query("
        SELECT ncs.last_comment_timestamp FROM {node} n
        INNER JOIN {boincteam_forum_node} bfn
        INNER JOIN {node_comment_statistics} ncs ON n.nid = bfn.nid AND n.nid = ncs.nid
        WHERE n.status = 1 AND bfn.tfid = %d
        ORDER BY ncs.last_comment_timestamp DESC
        LIMIT 1",
        $team_forum->tfid
      ));
      $team_forum->last_reply = theme('forum_submitted', ($last_post->timestamp) ? $last_post : NULL);
      $team_forums[$team_forum->tfid] = $team_forum;
      $row++;
    }
  }
  return $team_forums;
}

/*
 * Load a team forum by ID
 */
function boincteam_forum_load($tfid) {
  // Load any team forum objects for the user's team
  $result = db_query("
    SELECT tfid, nid, title, description, created, updated, public,
      min_time_between_posts, min_total_credit_to_post, min_avg_credit_to_post
    FROM {boincteam_forum} WHERE tfid=%d", $tfid
  );
  return db_fetch_object($result);
}

/*
 * Look up the team ID for a given team forum
 */
function boincteam_forum_lookup_nid($tfid) {
  return db_result(db_query("
    SELECT nid FROM {boincteam_forum}
    WHERE tfid=%d", $tfid
  ));
}


/*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
 * Pane content for panels
 *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */

/**
 * Create team forum form
 */
function boincteam_forum_create_form_panel() {
  $output = '';
  $output .= '<h2 class="pane-title">' . bts('Create team message board', array(), NULL, 'boinc:team-forum')
    . '</h2>';
  $output .= drupal_get_form('boincteam_forum_create_form');

  return $output;
}

/**
 * Edit team forum form
 */
function boincteam_forum_edit_form_panel($tfid) {
  $team_forum = boincteam_forum_load($tfid);
  $output = '';
  $output .= '<h2 class="pane-title">' . bts('Edit message board', array(), NULL, 'boinc:team-forum') . ': ' .
    $team_forum->title . '</h2>';
  $output .= drupal_get_form('boincteam_forum_edit_form', $tfid);

  return $output;
}

/**
 * Link to team forums
 */
function boincteam_forum_link_panel($team_id) {
  $show_public_only = (
    !boincteam_is_member($team_id) AND
    !boincteam_forum_is_global_moderator()
  );
  $forums = boincteam_forum_list($team_id);
  $output = '';
  $output .= '<h2 class="pane-title">' . bts('Team forum', array(), NULL, 'boinc:team-forum') . '</h2>';
  $output .= '<p>'
    . bts('A discussion forum has been set up for team members.', array(), NULL, 'boinc:team-forum')
    . '</p>';
  $output .= '<ul class="tab-list action-list">';
  foreach ($forums as $forum) {
    if (!$show_public_only OR $forum->public) {
      $output .= '  <li class="tab primary">' .
        l(
          //$forum->title,
          bts('Enter forum', array(), NULL, 'boinc:team-forum'),
          "community/teams/{$team_id}/forum/{$forum->tfid}"
        ) . '</li>';
      // Since we're only supporting one team forum for now, we've labeled the
      // link in a generic way above and will now just break out of the loop
      break;
    }
  }
  $output .= '</ul>';
  return $output;
}

/**
 * General info about team forums
 */
function boincteam_forum_topic_overview_panel($nid = NULL) {
  $output = '';
  $output .= '<h2 class="pane-title">' . bts('About message boards', array(), NULL, 'boinc:team-forum') . '</h2>';
  $output .= '<div>';
  if ($nid) {
    $team = node_load($nid);
    $output .= '<p>' . bts('You may create a message board for use by @team',
      array('@team' => $team->title), NULL, 'boinc:team-forum') . ':</p>';
  }
  else {
    $output .= '<p>' . bts('This is a team-only message board', array(), NULL, 'boinc:team-forum') . ':</p>';
  }
  $output .= '<ul>';
  $output .= '  <li>' . bts('Only members may post', array(), NULL, 'boinc:team-forum') . '</li>';
  $output .= '  <li>' . bts('Only members may read (optional)', array(), NULL, 'boinc:team-forum') . '</li>';
  $output .= '  <li>' . bts('Founder & Team Admins have moderator privileges', array(), NULL, 'boinc:team-forum') .
    '</li>';
  $output .= '</ul>';
  $output .= '</div>';
  return $output;
}
