<?php

/**
 * @file
 * This module provides a method for creating and maintaining
 * tournament brackets.
 *
 * @author Jim Bullington <jimb@jrbcs.com>
 */

// default color codes for images and pdfs
global $_bracket_bg_color_default;
global $_bracket_fg_color_default;
global $_bracket_bar_bg_color_default;
global $_bracket_bar_fg_color_default;
$_bracket_bg_color_default = '#FFFFFF';      // white
$_bracket_fg_color_default = '#000000';      // black
$_bracket_bar_bg_color_default = '#404080';  // dark blue
$_bracket_bar_fg_color_default = '#FFFFFF';  // white

module_load_include('inc', 'bracket', 'bracket_class');
module_load_include('inc', 'bracket', 'bracket_db');
module_load_include('inc', 'bracket', 'bracket_design');
module_load_include('inc', 'bracket', 'bracket_round');
module_load_include('inc', 'bracket', 'bracket_result');
module_load_include('inc', 'bracket', 'bracket_route');
module_load_include('inc', 'bracket', 'bracket_seed');
module_load_include('inc', 'bracket', 'bracket_image');
module_load_include('inc', 'bracket', 'bracket_pdf');
module_load_include('inc', 'bracket', 'bracket_api');
if (module_exists('views')) {
  module_load_include('inc', 'bracket', 'bracket_views');
}

define('BRACKET_CACHE', 'bracket_cache');

//=========================================================================
// drupal hooks
//=========================================================================
/**
 * Implementation of hook_permission().
 */
function bracket_permission() {

  return array(
    'view brackets' => array(
      'title' => t('View Brackets'), 
      'description' => t('View Bracket Nodes.'),
    ),
    'create brackets' => array(
      'title' => t('Create Brackets'), 
      'description' => t('Create Bracket Nodes.'),
    ),
    'edit brackets' => array(
      'title' => t('Edit Brackets'), 
      'description' => t('Edit Any Bracket Nodes.'),
    ),
    'edit own brackets' => array(
      'title' => t('Edit Own Brackets'), 
      'description' => t('Edit Only Bracket Nodes Created by User.'),
    ),
  );
}

/**
 * Implementation of hook_node_info().
 */
function bracket_node_info() {

  $info = array(
    'bracket' => array(
      'name' => t('Bracket'),
      'base' => 'bracket',
      'description' => t('Create a tournament bracket.')
     )
   );
   
   return $info;
}

/**
 * Implementation of hook_node_access
 */
function bracket_node_access($node, $op, $account) {

  $result = NODE_ACCESS_IGNORE;
  $type = is_string($node) ? $node : $node->type;

  if ($type == 'bracket') {
    $result = NODE_ACCESS_DENY;
    switch ($op) {
      case 'view':
        // if node is published, return view access
        if (is_object($node) && $node->status) {
          if (user_access('view brackets', $account)) {
            $result = NODE_ACCESS_ALLOW;
          }
        }
        // if unpublished, return update access - users who can update the node should be able to view it
        else  {
          if (node_access('update', $node, $account)) {
            $result = NODE_ACCESS_ALLOW;
          }
        }
        break;
      case 'create':
        if (user_access('create brackets', $account)) {
          $result = NODE_ACCESS_ALLOW;
        }
        break;
      case 'update':
      case 'delete':
        if (user_access('edit brackets', $account) || (user_access('edit own brackets', $account) && (is_object($node) && $account->uid == $node->uid))) {
          $result = NODE_ACCESS_ALLOW;
        }
        break;
    }
  }

  return $result;
}

/**
 * Implementation of hook_menu().
 */
function bracket_menu() {

  $items = array();

  $items['admin/config/content/bracket'] = array(
    'title' => 'Brackets',
    'description' => 'Change bracket settings',
    'page callback' => 'bracket_settings',
    'access callback' => 'user_access',
    'access arguments' => array('administer site configuration'),
    'type' => MENU_NORMAL_ITEM,
  );

  // bracket listing.
  $items['admin/content/bracket'] = array(
    'title' => 'Brackets',
    'page callback' => 'bracket_admin_content',
    'access callback' => 'user_access',
    'access arguments' => array('administer content'),
    'description' => 'View and edit all the brackets on your site.',
    'type' => MENU_NORMAL_ITEM,
  );

  $items['node/%bracket_menu/bracket-image'] = array(
    'page callback' => 'bracket_image',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('view', 1),
    'type' => MENU_CALLBACK,
  );

  $items['node/%bracket_menu/bracket-pdf'] = array(
    'page callback' => 'bracket_pdf',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('view', 1),
    'type' => MENU_CALLBACK,
  );

  $items['node/%bracket_menu/bracket-clone'] = array(
    'title' => 'Clone',
    'page callback' => 'bracket_clone',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('create', 1),
    'weight' => 2,
    'type' => MENU_LOCAL_TASK
  );

  $items['node/%bracket_menu/bracket-clear'] = array(
    'title' => 'Clear',
    'page callback' => 'bracket_clear',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('update', 1),
    'weight' => 3,
    'type' => MENU_LOCAL_TASK
  );

  $items['node/%bracket_menu/bracket-export'] = array(
    'title' => 'Export',
    'page callback' => 'bracket_export',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('update', 1),
    'weight' => 4,
    'type' => MENU_LOCAL_TASK
  );

  $items['node/%bracket_menu/bracket-import'] = array(
    'title' => 'Import',
    'page callback' => 'bracket_import',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('update', 1),
    'weight' => 5,
    'type' => MENU_LOCAL_TASK
  );

  $items['node/%bracket_menu/edit/info'] = array(
    'title' => 'Bracket Info',
    'page callback' => 'node_page_edit',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('update', 1),
    'weight' => 0,
    'type' => MENU_DEFAULT_LOCAL_TASK
  );

  $items['node/%bracket_menu/edit/route'] = array(
    'title' => 'Routing',
    'page callback' => 'bracket_route_edit',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('update', 1),
    'weight' => 0,
    'file' => 'bracket_route.inc',
    'type' => MENU_LOCAL_TASK
  );

  $items['node/%bracket_menu/edit/seed'] = array(
    'title' => 'Seeding',
    'page callback' => 'bracket_seed_edit',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('update', 1),
    'weight' => 0,
    'file' => 'bracket_seed.inc',
    'type' => MENU_LOCAL_TASK
  );

  $items['node/%bracket_menu/edit/round'] = array(
    'title' => 'Rounds',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('bracket_round_list_form', 1),
    'access callback' => 'node_access',
    'access arguments' => array('update', 1),
    'weight' => 1,
    'file' => 'bracket_round.inc',
    'type' => MENU_LOCAL_TASK
  );
  
  $items['node/%bracket_menu/edit/round/%bracket_round_menu'] = array(
    'load arguments' => array(1),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('bracket_round_edit_form', 1, 4),
    'access callback' => 'node_access',
    'access arguments' => array('update', 1),
    'type' => MENU_LOCAL_TASK
  );

  $items['node/%bracket_menu/edit/results'] = array(
    'title' => 'Results',
    'page callback' => 'bracket_result_edit',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('update', 1),
    'weight' => 2,
    'file' => 'bracket_result.inc',
    'type' => MENU_LOCAL_TASK
  );
  
  return $items;
}

/**
 * Menu loader callback; Load a bracket node if the given nid is a bracket
 */
function bracket_menu_load($nid) {

  if (!is_numeric($nid)) {
    return FALSE;
  }
  $node = node_load($nid);
  if (empty($node->type) || $node->type != 'bracket') {
    return FALSE;
  }
  return $node;
}

/**
 * Menu loader callback; Load a bracket node and return the round object if valid
 */
function bracket_round_menu_load($roundid, $nid) {

  $node = bracket_menu_load($nid);
  if ($node) {
    if ($roundid >= 1 && $roundid <= count($node->round)) {
      return $roundid;
    }
  }
  return FALSE;
}

/**
 * Implementation of hook_theme().
 */
function bracket_theme() {
  
  $theme = array(
    'bracket_view' => array(
      'variables' => array('node' => NULL, 'view_mode' => NULL),
    ),
    'bracket_admin_content' => array(
      'variables' => array('nodes' => NULL),
    ),
    'bracket_route_edit_form' => array(
      'render element' => 'form',
    ),
    'bracket_round_edit_form' => array(
      'render element' => 'form',
    ),
    'bracket_match' => array(
      'variables' => array('node' => NULL, 'round_index' => NULL, 'match_index' => NULL, 'orientation' => NULL),
      'template' => 'templates/bracket-match',
    ),
    'bracket_match_lr' => array(
      'variables' => array('node' => NULL, 'round_index' => NULL, 'match_index' => NULL),
      'template' => 'templates/bracket-match-lr',
    ),
    'bracket_result' => array(
      'variables' => array('node' => NULL, 'result_index' => NULL, 'orientation' => NULL),
      'template' => 'templates/bracket-result',
    ),
    'bracket_images' => array(
      'variables' => array('node' => NULL),
      'template' => 'templates/bracket-images',
    )
  );
  
  // add designs
  foreach (bracket_design_list() as $key => $desc) {

    // form path and template name    
    $path = drupal_get_path('module', 'bracket') . '/designs/' . $key . '/';
    $tpl = 'bracket-' . $key;

    // only add if template file exists
    if (file_exists(realpath($path . $tpl . '.tpl.php'))) {
    
      // add to theme cache
      $theme['bracket_' . $key] = array(
        'variables' => array('node' => NULL),
        'path' => $path,
        'template' => $tpl
        );
    }
  }
  
  return $theme;
}

//=========================================================================
// bracket settings
//=========================================================================
function bracket_settings() {

  return drupal_get_form('bracket_settings_form');
}

function bracket_settings_form() {

  $form = array();

  $form['general'] = array(
    '#type' => 'fieldset',
    '#title' => t('Bracket Settings'),
    '#collapsible' => FALSE,
    '#collapsed' => FALSE
  );

  $form['general']['display'] = array(
    '#type' => 'select',
    '#title' => t('Default Display'),
    '#options' => bracket_display_options(),
    '#default_value' => variable_get('bracket_default_display', 'Image'),
    '#description' => t('Select the default display option for brackets. Use the button below to update all bracket display options to the current default display option - set the desired option first.')
  );

  $form['general']['update_bracket_display'] = array(
    '#type' => 'submit',
    '#value' => t('Update All Bracket Displays'),
  );

  $form['general'][BRACKET_CACHE] = array(
    '#type' => 'checkbox',
    '#title' => t('Cache Bracket Images'),
    '#default_value' => variable_get(BRACKET_CACHE, FALSE),
    '#description' => t('Cache bracket images and pdfs - may improve performance during peak loads.  Unlike the Drupal cache, brackets are cached for all users, except for those who have bracket update access.')
  );
    
  $form['general']['purge_cache_now'] = array(
    '#type' => 'submit',
    '#value' => t('Purge Bracket Cache Now'),
  );
  
  $form['general']['upload'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow Image Uploads'),
    '#default_value' => variable_get('bracket_image_upload', FALSE),
    '#description' => t('Allow the user to upload images with brackets.')
  );

  $form['general']['upload_path'] = array(
    '#type' => 'textfield',
    '#title' => t('Image Upload Path'),
    '#default_value' => variable_get('bracket_image_upload_path', ''),
    '#description' => t('This is the path where bracket images will be uploaded - if not specified, the default file path will be used.
                         This path must be writable by the user uploading the image.'),
    '#required' => FALSE
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save Configuration Settings'),
  );

  return $form;
}

function bracket_settings_form_validate($form_id, &$form_state) {

  $upload = $form_state['values']['upload'];
  if ($upload) {
    $dir = $form_state['values']['upload_path'];
    if ($dir != '') {
      // must be writable
      $is_writable = file_prepare_directory($dir);
      if (!$is_writable) {
        form_set_error('upload_path', 'Upload path must be writeable');
      }
    }
  }
}

function bracket_settings_form_submit($form_id, &$form_state) {

  if ($form_state['values']['op'] == $form_state['values']['purge_cache_now']) {
    bracket_clear_cache_all();
    $msg = 'Bracket cache was purged.';
    watchdog('bracket', $msg);
    drupal_set_message($msg, 'info');
    return;
  }
  
  if ($form_state['values']['op'] == $form_state['values']['update_bracket_display']) {
    update_all_bracket_displays();
    $msg = 'Bracket display options were updated.';
    watchdog('bracket', $msg);
    drupal_set_message($msg, 'info');
    return;
  }

  // clear bracket cache and drupal cache if setting changes
  $current = variable_get(BRACKET_CACHE, FALSE);
  $new = $form_state['values'][BRACKET_CACHE];
  if ($current != $new) {
    bracket_clear_cache_all();
    cache_clear_all();
  }
  
  variable_set('bracket_default_display', $form_state['values']['display']);
  variable_set(BRACKET_CACHE, $new);
  variable_set('bracket_image_upload', $form_state['values']['upload']);
  variable_set('bracket_image_upload_path', $form_state['values']['upload_path']);

  drupal_set_message(t('Configuration settings were saved.'));
}

function update_all_bracket_displays() {

  $option = variable_get('bracket_default_display', 'Image');
  $result = db_query("SELECT n.nid, n.title FROM {node} n WHERE n.type = 'bracket'");
  foreach ($result as $record) {
    $node = node_load($record->nid);
    $node->options['display'] = $option;
    node_save($node);
    watchdog('bracket', t('Updated bracket - ' . $row->title . ' (' . $row->nid . ') - to display option: ' . $option));
  }
}

//=========================================================================
// bracket node hooks
//=========================================================================

/**
 * Implementation of hook_view
 */
function bracket_view($node, $view_mode) {

  // no teasers for now
  if ($view_mode == 'teaser') {
    return $node;
  }
  
  $node->content['bracket'] = array(
    '#markup' => theme('bracket_view', array('node' => $node, 'view_mode' => $view_mode)),
    '#weight' => 10
  );
  
  return $node;
}

/**
 * Theming function for bracket_view
 */
function theme_bracket_view($variables) {

  $node = $variables['node'];
  $view_mode = $variables['view_mode'];

  if ($node->type != 'bracket' || !isset($node->design) || $node->design == '') {
    drupal_set_message(t('Unable to display bracket - possibly damaged node.'), 'error');
    return '';
  }
  
  // Add the css file
  drupal_add_css(drupal_get_path('module', 'bracket') . '/bracket.css');
  
  $output = '<div class="bracket">' . "\n";
  if (!isset($node->options['hide_pdf']) || (isset($node->options['hide_pdf']) && !$node->options['hide_pdf'])) {
    $output .= '<div class="bracket-print-link">' . l(t('Click here for a printable version'), 'node/' . $node->nid . '/bracket-pdf') . "</div>\n";
  }
  if (isset($node->options['display']) && $node->options['display'] == 'HTML') {
    $output .= theme('bracket_' . $node->design, array('node' => $node));
  }
  else {
    $output .= '<div class="bracket-img"><img src="' . url('node/' . $node->nid . '/bracket-image') . '"></div>' . "\n";
  }
  
  $output .= '</div><div class="clear-block"></div>' . "\n";

  return $output;
}

/**
 * Implementation of hook_load().
 */
function bracket_prepare($node) {

  // add default bracket fields
  if (arg(1) == 'add') {
    $bracket = new Bracket();
    foreach ($bracket as $key => $value) {
      $node->$key = $value;
    }
  }
}

/**
 * Implementation of hook_load().
 */
function bracket_load($nodes) {

  // load bracket node values
  foreach ($nodes as $nid => $node) {
    $bracket = bracket_db_load($node);
    foreach ($bracket as $key => $value) {
      $nodes[$nid]->$key = $value;
    }
  }
}

/**
 * Implementation of hook_form().
 */
function bracket_form($node) {

  global $_bracket_bg_color_default;
  global $_bracket_fg_color_default;
  global $_bracket_bar_bg_color_default;
  global $_bracket_bar_fg_color_default;
  global $_bracket_pdf_font_name;
  global $_bracket_image_font_file;
  global $_bracket_image_font_bold_file;
  global $_bracket_image_font_italic_file;
  global $_bracket_image_font_bolditalic_file;
  
  $form = array();

  $form['bracket'] = array(
    '#type' => 'fieldset',
    '#title' => t('Bracket Info'),
    '#collapsible' => FALSE,
    '#collapsed' => FALSE,
    '#weight' => -8
  );

  $form['bracket']['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#required' => TRUE,
    '#default_value' => $node->title,
    '#weight' => -9,
    '#description' => t('Enter a title for this bracket.')
  );

  $form['bracket']['subtitle'] = array(
    '#type' => 'textfield',
    '#title' => t('Subtitle'),
    '#required' => FALSE,
    '#default_value' => $node->subtitle,
    '#weight' => -8,
    '#description' => t('Enter a subtitle for this bracket.')
  );

  $form['bracket']['comments'] = array(
    '#type' => 'textarea',
    '#title' => t('Comments'),
    '#required' => FALSE,
    '#default_value' => $node->comments,
    '#weight' => -7,
    '#description' => t('Comments for this bracket')
  );

  // only allow design selection at creation time
  if (!isset($node->nid)) {
    $options = array('' => t('Select a bracket design')) + bracket_design_list();
    $form['bracket']['design'] = array(
      '#type' => 'select',
      '#title' => t('Bracket Design'),
      '#default_value' => $node->design,
      '#options' => $options,
      '#required' => TRUE,
      '#weight' => -6,
      '#description' => t('Select a design for this bracket.'),
     );
  }
  // display design readonly otherwise
  else {
    $tmp = bracket_design_description($node->design);
    if ($tmp == '') {
      drupal_set_message(t('Error - Selected design was not found - @design', array('@design' => $node->design)), 'error');
    }
    $form['bracket']['design'] = array(
      '#type' => 'textfield',
      '#title' => t('Bracket Design'),
      '#default_value' => $tmp,
      '#size' => 100,
      '#required' => TRUE,
      '#weight' => -6,
      '#attributes' => array('readonly' => 'readonly'),
      '#description' => t('The design for this bracket - this cannot be altered.'),
     );
  }

  $form['bracket']['sport'] = array(
    '#type' => 'textfield',
    '#title' => t('Sport'),
    '#required' => FALSE,
    '#default_value' => $node->sport,
    '#weight' => -5,
    '#description' => t('Enter the sport for this bracket.')
  );

  $form['bracket']['division'] = array(
    '#type' => 'textfield',
    '#title' => t('Division'),
    '#required' => FALSE,
    '#default_value' => $node->division,
    '#weight' => -4,
    '#description' => t('Enter the division for this bracket.')
  );

  $form['bracket']['season'] = array(
    '#type' => 'textfield',
    '#title' => t('Season'),
    '#required' => FALSE,
    '#default_value' => $node->season,
    '#weight' => -3,
    '#description' => t('Enter the season for this bracket.')
  );

  $form['bracket']['brgroup'] = array(
    '#type' => 'textfield',
    '#title' => t('Group'),
    '#required' => FALSE,
    '#default_value' => $node->brgroup,
    '#weight' => -2,
    '#description' => t('Enter the group for this bracket - ex boys, girls, men, women, etc.')
  );

  $form['bracket']['footer'] = array(
    '#type' => 'textarea',
    '#title' => t('Footer'),
    '#required' => FALSE,
    '#default_value' => $node->footer,
    '#weight' => -1,
    '#description' => t('Bracket comments - appear as a footer.'),
  );

  $form['bracket']['logo'] = array(
    '#type' => 'fieldset',
    '#title' => t('Logo Image')
  );

  if (variable_get('bracket_image_upload', FALSE)) {

    $form['bracket']['logo']['logoupload'] = array(
      '#type' => 'file',
      '#title' => t('Upload Logo Image'),
      '#description' => t('Click "Browse..." to select an image to upload. Supported image types are JPG and PNG.
                           The maximum file size per upload is %size MB.', array('%size' => round(file_upload_max_size()/(1024*1024), 0)))
    );
  }

  $form['bracket']['logo']['logopath'] = array(
    '#type' => 'textfield',
    '#title' => t('Logo Image Path'),
    '#size' => 100,
    '#maxlength' => 100,
    '#description' => t('Path to the logo image file. Supported image types are JPG and PNG.'),
    '#default_value' => $node->logopath
  );

  $upl = variable_get('bracket_image_upload_path', FALSE);
  
  if ($node->logopath) {
    $form['bracket']['logo']['current_logo'] = array(
      '#type' => 'markup',
      '#markup' => '&nbsp;<br /><img src="' . bracket_logo_url($node->logopath) . '">'
    );

    // only allow delete, if file exists in the upload directory
    if (!bracket_path_is_url($node->logopath) && $upl) {
      if (file_check_location($node->logopath, $upl)) {  
        $form['bracket']['logo']['delete_logo'] = array(
          '#type' => 'checkbox',
          '#title' => t('Delete Logo'),
          '#description' => t('Check to delete current logo. WARNING - image file will be deleted!')
        );
      }
    }
  }

  $form['bracket']['sponsorlogo'] = array(
    '#type' => 'fieldset',
    '#title' => t('Sponsor Logo Image')
  );

  if (variable_get('bracket_image_upload', FALSE)) {

    $form['bracket']['sponsorlogo']['sponsorlogoupload'] = array(
      '#type' => 'file',
      '#title' => t('Upload Sponsor Logo Image'),
      '#description' => t('Click "Browse..." to select an image to upload. Supported image types are JPG and PNG.
                           The maximum file size per upload is %size MB.', array('%size' => round(file_upload_max_size()/(1024*1024), 0)))
    );
  }

  $form['bracket']['sponsorlogo']['sponsorlogopath'] = array(
    '#type' => 'textfield',
    '#title' => t('Sponsor Logo Image Path'),
    '#size' => 100,
    '#maxlength' => 100,
    '#description' => t('Path to the sponsor logo image file. Supported image types are JPG and PNG.'),
    '#default_value' => $node->sponsorlogopath
  );

  if ($node->sponsorlogopath) {
    $form['bracket']['sponsorlogo']['current_sponsorlogo'] = array(
      '#type' => 'markup',
      '#markup' => '&nbsp;<br /><img src="' . bracket_logo_url($node->sponsorlogopath) . '">'
    );

    // only allow delete, if file exists in the upload directory
    if (!bracket_path_is_url($node->sponsorlogopath) && $upl) {
      if (file_check_location($node->sponsorlogopath, $upl)) {  
        $form['bracket']['sponsorlogo']['delete_sponsorlogo'] = array(
          '#type' => 'checkbox',
          '#title' => t('Delete Sponsor Logo'),
          '#description' => t('Check to delete current sponsor logo. WARNING - image file will be deleted!')
        );
      }
    }
  }

  if (variable_get('bracket_image_upload', FALSE)) {
    // so uploads will work
    $form['#validate'][] = 'bracket_form_validate';
    $form['#attributes']['enctype'] = 'multipart/form-data';
  }

  $form['bracket']['options'] = array(
    '#type' => 'fieldset',
    '#title' => t('Bracket Display Options'),
    '#collapsed' => TRUE,
    '#collapsible' => TRUE,
    '#tree' => TRUE
  );

  if (!isset($node->options['display'])) {
    $node->options['display'] = variable_get('bracket_default_display', 'Image');
  }
  $form['bracket']['options']['display'] = array(
    '#type' => 'select',
    '#title' => t('Display'),
    '#options' => bracket_display_options(),
    '#default_value' => $node->options['display'],
    '#description' => t('Select the display option for this bracket.')
  );
  
  if (!isset($node->options['hide_pdf'])) {
    $node->options['hide_pdf'] = FALSE;
  }
  $form['bracket']['options']['hide_pdf'] = array(
    '#type' => 'checkbox',
    '#title' => t('Hide PDF Link'),
    '#default_value' => $node->options['hide_pdf'],
    '#description' => t('If checked, the link to download a PDF version of the bracket will not appear above the bracket.')
  );

  $form['bracket']['options']['show_match_id'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show Match IDs'),
    '#default_value' => $node->options['show_match_id'],
    '#description' => t('Check to display match IDs on the bracket.')
  );

  $form['bracket']['options']['image_options'] = array(
    '#type' => 'fieldset',
    '#title' => t('Image and PDF Options'),
    '#collapsed' => FALSE,
    '#collapsible' => FALSE,
    '#tree' => TRUE,
    '#description' => t('These options apply to Image and PDF output only.'),
  );
  
  if (!isset($node->options['image_options']['fg_color']) || empty($node->options['image_options']['fg_color'])) {
    $node->options['image_options']['fg_color'] = $_bracket_fg_color_default;
  }
  $form['bracket']['options']['image_options']['fg_color'] = array(
    '#type' => 'textfield',
    '#title' => t('Foreground & Text Color'),
    '#size' => 7,
    '#maxlength' => 7,
    '#required' => TRUE,
    '#description' => t('In HTML color format - #RRGGBB (Default is @color).', array('@color' => $_bracket_fg_color_default)),
    '#default_value' => $node->options['image_options']['fg_color']
  );

  if (!isset($node->options['image_options']['bg_color']) || empty($node->options['image_options']['bg_color'])) {
    $node->options['image_options']['bg_color'] = $_bracket_bg_color_default;
  }
  $form['bracket']['options']['image_options']['bg_color'] = array(
    '#type' => 'textfield',
    '#title' => t('Background Color'),
    '#size' => 7,
    '#maxlength' => 7,
    '#required' => TRUE,
    '#description' => t('In HTML color format - #RRGGBB (Default is @color).', array('@color' => $_bracket_bg_color_default)),
    '#default_value' => $node->options['image_options']['bg_color']
  );

  if (!isset($node->options['image_options']['show_bracket_bar'])) {
    $node->options['image_options']['show_bracket_bar'] = FALSE;
  }
  $form['bracket']['options']['image_options']['show_bracket_bar'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show Bracket Bar'),
    '#default_value' => $node->options['image_options']['show_bracket_bar'],
    '#description' => t('Check to display bracket bar and round comments on bracket. Note: Some designs do not utilize this option.')
  );

  if (!isset($node->options['image_options']['bar_bg_color']) || empty($node->options['image_options']['bar_bg_color'])) {
    $node->options['image_options']['bar_bg_color'] = $_bracket_bar_bg_color_default;
  }
  $form['bracket']['options']['image_options']['bar_bg_color'] = array(
    '#type' => 'textfield',
    '#title' => t('Bracket Bar Background Color'),
    '#size' => 7,
    '#maxlength' => 7,
    '#description' => t('In HTML color format - #RRGGBB (Default is @color).', array('@color' => $_bracket_bar_bg_color_default)),
    '#default_value' => $node->options['image_options']['bar_bg_color']
  );

  if (!isset($node->options['image_options']['bar_fg_color']) || empty($node->options['image_options']['bar_fg_color'])) {
    $node->options['image_options']['bar_fg_color'] = $_bracket_bar_fg_color_default;
  }
  $form['bracket']['options']['image_options']['bar_fg_color'] = array(
    '#type' => 'textfield',
    '#title' => t('Bracket Bar Foreground (Text) Color'),
    '#size' => 7,
    '#maxlength' => 7,
    '#description' => t('In HTML color format - #RRGGBB (Default is @color).', array('@color' => $_bracket_bar_fg_color_default)),
    '#default_value' => $node->options['image_options']['bar_fg_color']
  );

  $form['bracket']['options']['image_options']['bar_example'] = array(
    '#type' => 'markup',
    '#markup' => '<div style="background-color:' . $node->options['image_options']['bar_bg_color'] . ';color:' . $node->options['image_options']['bar_fg_color'] . ';">' . t('Bracket Bar Example') .'</div>'
  );

  $form['bracket']['options']['image_options']['image_fonts'] = array(
    '#type' => 'fieldset',
    '#title' => t('Image Font Files'),
    '#collapsed' => FALSE,
    '#collapsible' => FALSE,
    '#tree' => TRUE,
    '#description' => t('Image font files must be present in the fonts folder of the bracket module.'),
  );

  if (!isset($node->options['image_options']['image_fonts']['image_font']) || empty($node->options['image_options']['image_fonts']['image_font'])) {
    $node->options['image_options']['image_fonts']['image_font'] = $_bracket_image_font_file;
  }
  $form['bracket']['options']['image_options']['image_fonts']['image_font'] = array(
    '#type' => 'textfield',
    '#title' => t('Image Normal Font File'),
    '#size' => 50,
    '#maxlength' => 50,
    '#description' => t('Image font file for normal font (Default is @font).', array('@font' => $_bracket_image_font_file)),
    '#default_value' => $node->options['image_options']['image_fonts']['image_font']
  );

  if (!isset($node->options['image_options']['image_fonts']['image_font_bold']) || empty($node->options['image_options']['image_fonts']['image_font_bold'])) {
    $node->options['image_options']['image_fonts']['image_font_bold'] = $_bracket_image_font_bold_file;
  }
  $form['bracket']['options']['image_options']['image_fonts']['image_font_bold'] = array(
    '#type' => 'textfield',
    '#title' => t('Image Bold Font File'),
    '#size' => 50,
    '#maxlength' => 50,
    '#description' => t('Image font file for bold font (Default is @font).', array('@font' => $_bracket_image_font_bold_file)),
    '#default_value' => $node->options['image_options']['image_fonts']['image_font_bold']
  );

  if (!isset($node->options['image_options']['image_fonts']['image_font_italic']) || empty($node->options['image_options']['image_fonts']['image_font_italic'])) {
    $node->options['image_options']['image_fonts']['image_font_italic'] = $_bracket_image_font_italic_file;
  }
  $form['bracket']['options']['image_options']['image_fonts']['image_font_italic'] = array(
    '#type' => 'textfield',
    '#title' => t('Image Italic Font File'),
    '#size' => 50,
    '#maxlength' => 50,
    '#description' => t('Image font file for italic font (Default is @font).', array('@font' => $_bracket_image_font_italic_file)),
    '#default_value' => $node->options['image_options']['image_fonts']['image_font_italic']
  );

  if (!isset($node->options['image_options']['image_fonts']['image_font_bolditalic']) || empty($node->options['image_options']['image_fonts']['image_font_bolditalic'])) {
    $node->options['image_options']['image_fonts']['image_font_bolditalic'] = $_bracket_image_font_bolditalic_file;
  }
  $form['bracket']['options']['image_options']['image_fonts']['image_font_bolditalic'] = array(
    '#type' => 'textfield',
    '#title' => t('Image Bold Italic Font File'),
    '#size' => 50,
    '#maxlength' => 50,
    '#description' => t('Image font file for bold italic font (Default is @font).', array('@font' => $_bracket_image_font_bolditalic_file)),
    '#default_value' => $node->options['image_options']['image_fonts']['image_font_bolditalic']
  );

  $options = bracket_pdf_font_options();
  if (!isset($node->options['image_options']['pdf_font']) || empty($node->options['image_options']['pdf_font'])) {
    $node->options['image_options']['pdf_font'] = $_bracket_pdf_font_name;
  }
  $form['bracket']['options']['image_options']['pdf_font'] = array(
    '#type' => 'select',
    '#title' => t('PDF Font'),
    '#default_value' => $node->options['image_options']['pdf_font'],
    '#options' => $options,
    '#description' => t('Select the PDF font for this bracket (Default is @font).', array('@font' => $_bracket_pdf_font_name)),
   );

  return $form;
}

/**
 * Implementation of hook_validate().
 */
function bracket_validate($node, $form, &$form_state) {

  $msg = 'Invalid HTML color code - must be #RRGGBB';
  if (!bracket_validate_color($node->options['image_options']['fg_color'])) {
    form_set_error('options][image_options][fg_color', $msg);
  }
  if (!bracket_validate_color($node->options['image_options']['bg_color'])) {
    form_set_error('options][image_options][bg_color', $msg);
  }
  if (!bracket_validate_color($node->options['image_options']['bar_fg_color'])) {
    form_set_error('options][image_options][bar_fg_color', $msg);
  }
  if (!bracket_validate_color($node->options['image_options']['bar_bg_color'])) {
    form_set_error('options][image_options][bar_bg_color', $msg);
  }
}

/**
 * Return true if the given color is a valid HTML color
 * code in the format of : #RRGGBB
 *
 * @param $color
 *   the path of the image file
 * @return
 *   TRUE if color is valid, otherwise FALSE
 */
function bracket_validate_color($color) {

  if (preg_match('/^(#)([0-9a-fA-F]{3})([0-9a-fA-F]{3})?$/', $color)) {
    return TRUE;
  }
  return FALSE;
}

/**
 * validation hook of bracket form - handles image uploads and deletes
 */
function bracket_form_validate($form_id, &$form_state) {

  bracket_form_process_image('logoupload', 'logopath', 'delete_logo', $form_state);
  bracket_form_process_image('sponsorlogoupload', 'sponsorlogopath', 'delete_sponsorlogo', $form_state);
}

/**
 * process image uploads and deletes
 *
 * @param $upload_field
 *   the name of the file field containing the upload
 * @param $path_field
 *   the name of the text field containing the image path
 * @param $delete_field
 *   the name of the checkbox field containing the delete option
 */
function bracket_form_process_image($upload_field, $path_field, $delete_field, &$form_state) {

  // get bracket upload path
  $dir = variable_get('bracket_image_upload_path', '');
  // if not set, use public desitnation
  if ($dir == '') {
    $dir = 'public://';
  }
  $validators = array(
    'file_validate_is_image' => array(),
    'file_validate_extensions' => array('jpg jpeg png'),
  );
  // save the uploaded file
  if ($file = file_save_upload($upload_field, $validators, $dir)) {
    // set the path value for the node
    $form_state['values'][$path_field] = $file->uri;
    drupal_set_message(t('Image saved - ' . $file->uri . '.'));
  }
  // if user wants to delete the image
  if (array_key_exists($delete_field, $form_state['values'])) {
    // only delete if file is in the upload directory
    $path = $form_state['values'][$path_field];
    if ($path) {
      if (file_check_location($path, $dir)) {  
        // delete the file
        file_delete($path);
        // clear the value for the node
        $form_state['values'][$path_field] = '';
        drupal_set_message('Logo image deleted.');
      }
    }
  }
}

/**
  * Implementation of hook_insert
  */
function bracket_insert($node) {

  // create bracket components
  bracket_create($node);

  bracket_db_insert($node);
}

/**
  * Implementation of hook_update
  */
function bracket_update($node) {

  // if submitted from hook_form(), must add bracket components back
  if (isset($node->op) && $node->op == $node->submit) {
    // load bracket components
    $node2 = bracket_db_load($node);

    // copy bracket components to submitted node
    $node->comp = $node2->comp;
    $node->round = $node2->round;
    $node->result = $node2->result;
  }

  bracket_db_update($node);

  // delete bracket images from cache
  if (variable_get(BRACKET_CACHE, FALSE)) {
    bracket_clear_cache($node);
  }
  else {
    cache_clear_all();
  }
}

/**
  * Implementation of hook_delete
  */
function bracket_delete($node, $log = TRUE) {

  bracket_db_delete($node);

  // delete bracket images from cache
  if (variable_get(BRACKET_CACHE, FALSE)) {
    bracket_clear_cache($node);
  }
  else {
    cache_clear_all();
  }
}

//=========================================================================
// bracket clone form
//=========================================================================

function bracket_clone($node) {

  return drupal_get_form('bracket_clone_form', $node);
}

function bracket_clone_form($form, $form_state, $node) {

  drupal_set_title(t('Clone') . ' - ' . check_plain($node->title));

  // get the bracket form, with source node values
  $form =  bracket_form($node);

  $form['help'] = array(
    '#type' => 'markup',
    '#markup' => t('Use this form to clone a bracket - bracket design, comments, competitors and match results are all copied.'),
    '#weight' => -10
  );

  // add stuff to make clone work
  $form['nid'] = array(
    '#type' => 'hidden',
    '#value' => $node->nid
  );

  $form['clone'] = array(
    '#type' => 'submit',
    '#value' => t('Clone Bracket')
  );

  return $form;
}

function bracket_clone_form_submit($form_id, &$form_state) {

  global $user;

  // load the source node
  $node = node_load($form_state['values']['nid']);

  // make a new node and copy some info
  $node2 = new stdClass();
  $node2->type = $node->type;
  $node2->uid = $user->uid;
  $node2->comment = $node->comment;
  $node2->title = $form_state['values']['title'];
  $node2->subtitle = $form_state['values']['subtitle'];
  $node2->comments = $form_state['values']['comments'];
  $node2->sport = $form_state['values']['sport'];
  $node2->division = $form_state['values']['division'];
  $node2->season = $form_state['values']['season'];
  $node2->brgroup = $form_state['values']['brgroup'];
  $node2->footer = $form_state['values']['footer'];
  $node2->logopath = $form_state['values']['logopath'];
  $node2->sponsorlogopath = $form_state['values']['sponsorlogopath'];
  $node2->design = $node->design;
  $node2->options = $node->options;

  // insert the node - default bracket will be generated
  node_save($node2);

  // copy bracket components from source node
  $node2->comp = $node->comp;
  $node2->round = $node->round;
  $node2->result = $node->result;

  // save the completely cloned node
  node_save($node2);

  drupal_set_message(t('Bracket @title has been cloned', array('@title' => $node->title)));

  drupal_goto('node/' . $node2->nid . '/edit');
}

//=========================================================================
// bracket clear form
//=========================================================================

function bracket_clear($node) {

  return drupal_get_form('bracket_clear_form', $node);
}

function bracket_clear_form($form, $form_state, $node) {

  drupal_set_title(t('Clear') . ' - ' . check_plain($node->title));

  $form['help'] = array(
    '#type' => 'markup',
    '#markup' => t('Use this form to clear bracket competitors and match results.')
  );

  $form['nid'] = array(
    '#type' => 'hidden',
    '#value' => $node->nid
  );

  $form['options'] = array(
    '#type' => 'fieldset',
    '#title' => t('Clear Options'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#weight' => 0
  );

  $form['options']['opt'] = array(
      '#type' => 'checkboxes',
      '#options' => array('comp' => t('Competitors'), 'comp_comments' => t('Competitor Comments'), 'match' => t('Match Results'), 'comments' => t('Match Comments')),
      '#required' => TRUE,
      '#weight' => 1,
    );

  $form['msg'] = array(
    '#type' => 'markup',
    '#markup' => '<p><strong>' . t('Note: This action cannot be undone.') . '</strong></p>'
  );

  $form['clear'] = array(
    '#type' => 'submit',
    '#value' => t('Clear Bracket')
  );

  return $form;
}

function bracket_clear_form_submit($form_id, &$form_state) {

  // load the node
  $node = node_load($form_state['values']['nid']);

  if ($form_state['values']['opt']['comp']) {
    // clear competitors
    for ($i=1; $i<=count($node->comp); $i++) {
      $node->comp[$i]->name = '';
    }
  }

  if ($form_state['values']['opt']['match']) {
    // clear match results
    for ($i=1; $i<=count($node->round); $i++) {
      $r = $node->round[$i];
      for ($j=1; $j<=count($r->match); $j++) {
        $r->match[$j]->win[1] = 0;
        $r->match[$j]->win[2] = 0;
        $r->match[$j]->score[1] = '';
        $r->match[$j]->score[2] = '';
        if ($i > 1) {
          $r->match[$j]->compid[1] = 0;
          $r->match[$j]->compid[2] = 0;
        }
      }
    }
    // clear final results
    for ($i=1; $i<=count($node->result); $i++) {
      $node->result[$i]->compid = 0;
    }
  }

  if ($form_state['values']['opt']['comments']) {
    // clear match results
    for ($i=1; $i<=count($node->round); $i++) {
      $r = $node->round[$i];
      for ($j=1; $j<=count($r->match); $j++) {
        $r->match[$j]->comment[1] = '';
        $r->match[$j]->comment[2] = '';
      }
    }
  }

  if ($form_state['values']['opt']['comp_comments']) {
    // clear match results
    for ($i=1; $i<=count($node->round); $i++) {
      $r = $node->round[$i];
      for ($j=1; $j<=count($r->match); $j++) {
        $r->match[$j]->comp_comment[1] = '';
        $r->match[$j]->comp_comment[2] = '';
      }
    }
  }

  // save the node
  node_save($node);

  drupal_set_message(t('Bracket @title has been cleared', array('@title' => $node->title)));
}

//=========================================================================
// bracket export form
//=========================================================================

function bracket_export($node) {

  return drupal_get_form('bracket_export_form', $node);
}

function bracket_export_form($form, $form_state, $node) {

  drupal_set_title(t('Export') . ' - ' . check_plain($node->title));

  $form['help'] = array(
    '#type' => 'markup',
    '#markup' => t('Use this form to export a complete bracket or results.')
  );

  $form['nid'] = array(
    '#type' => 'hidden',
    '#value' => $node->nid
  );

  $form['options'] = array(
    '#type' => 'fieldset',
    '#title' => t('Export Options'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#weight' => 0
  );

  $form['options']['opt'] = array(
      '#type' => 'radios',
      '#options' => array('bracket' => t('Complete Bracket'), 'results' => t('Bracket Results Only')),
      '#required' => TRUE,
      '#weight' => 1,
    );

  $form['clear'] = array(
    '#type' => 'submit',
    '#value' => t('Export Bracket')
  );

  return $form;
}

function bracket_export_form_submit($form_id, &$form_state) {

  // include xml code
  require_once 'bracket_xml.inc';

  // load the node
  $node = node_load($form_state['values']['nid']);

  // generate the xml
  $output = bracket_xml_export($node, $form_state['values']['opt']);

  // make a file name from title
  $fname = preg_replace('/[^0-9a-z\.\_\-]/i', '_', $node->title);

  // prepare to download
  drupal_add_http_header('Content-Type',  'text/plain');
  drupal_add_http_header('Content-Length', strlen($output));
  drupal_add_http_header('Content-Disposition', 'attachment; filename="' . $fname . '.xml"');

  // send the output
  echo $output;

  exit();
}

//=========================================================================
// bracket import form
//=========================================================================

function bracket_import($node) {

  return drupal_get_form('bracket_import_form', $node);
}

function bracket_import_form($form, $form_state, $node) {

  drupal_set_title(t('Import') . ' - ' . check_plain($node->title));

  $form['help'] = array(
    '#type' => 'markup',
    '#markup' => t('Use this form to import a complete bracket or bracket competitors.')
  );

  $form['nid'] = array(
    '#type' => 'hidden',
    '#value' => $node->nid
  );

  $form['options'] = array(
    '#type' => 'fieldset',
    '#title' => t('Import Options'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#weight' => 0
  );

  $form['options']['opt'] = array(
      '#type' => 'radios',
      '#options' => array('bracket' => t('Complete Bracket'), 'results' => t('Results to Competitors')),
      '#required' => TRUE,
      '#weight' => 1,
    );

  $form['upload'] = array(
    '#type' => 'file',
    '#title' => t('Import File'),
    '#description' => t('Click "Browse..." to select the file to import.')
  );

  $form['#attributes']['enctype'] = 'multipart/form-data';

  $form['import'] = array(
    '#type' => 'submit',
    '#value' => t('Import Bracket')
  );

  return $form;
}

function bracket_import_form_submit($form_id, &$form_state) {

  // include xml code
  require_once 'bracket_xml.inc';

  // check for upload
  $xmlfile = file_save_upload('upload');

  // if something was uploaded, get file contents and parse xml
  if ($xmlfile) {

    // load the node
    $node = node_load($form_state['values']['nid']);

    // import the xml
    if (!bracket_xml_import($xmlfile, $node, $form_state['values']['opt'])) {

      drupal_set_message(t('Unable to parse XML file - Bracket was not imported.'), 'error');
    }
    else {

      // save the imported node
      node_save($node);
      drupal_set_message(t('Bracket @title Imported', array('@title' => $node->title)));
    }
  }
  else {

    drupal_set_message(t('Nothing was uploaded.'), 'error');
  }
}

/**
 * Display bracket list for admin/content/bracket
 */
function bracket_admin_content() {
  
  $nodes = db_select('node', 'n')
    ->fields('n')
    ->condition('n.type', 'bracket', '=')
    ->execute()
    ->fetchAllAssoc('nid');

  return theme('bracket_admin_content', array('nodes' => $nodes));
}


/**
 * Theme the list of brackets
 */
function theme_bracket_admin_content($variables) {

  $nodes = $variables['nodes'];

  $header = array(
    t('Title'),
    array('data' => t('Operations'), 'colspan' => '5')
  );

  $rows = array();
  foreach ($nodes as $node) {
    $rows[] = array(
      l($node->title, 'node/'. $node->nid),
      node_access('update', $node) ? l(t('Edit'), 'node/'. $node->nid .'/edit') : '',
      node_access('update', $node) ? l(t('Clone'), 'node/'. $node->nid .'/clone') : '',
      node_access('update', $node) ? l(t('Clear'), 'node/'. $node->nid .'/clear') : '',
      node_access('update', $node) ? l(t('Export'), 'node/'. $node->nid .'/export') : '',
      node_access('update', $node) ? l(t('Import'), 'node/'. $node->nid .'/import') : '',
    );
  }

  return theme('table', array('header' => $header, 'rows' => $rows));
}

//=========================================================================
// bracket interface functions
//=========================================================================

/**
 * Create a bracket
 *
 * @param $node
 *   the node containing the bracket
 */
function bracket_create(&$node) {

  bracket_design_load($node->design);

  $function = $node->design . '_create';

  if (function_exists($function)) {

    $args = array(&$node);
    call_user_func_array($function, $args);
  }
}

/**
 * Output a bracket image
 *
 * @param $node
 *   the node containing the bracket
 */
function bracket_image($node) {

  global $user;

  // if internal caching is on
  if (variable_get(BRACKET_CACHE, FALSE)) {
    // tell Drupal not to cache this url
    bracket_disable_page_cache();
  }

  // form cache key
  $key = 'bracket/' . $node->nid . '/image';

  // don't retrieve from cache for update users
  $img = FALSE;
  if (bracket_node_access('update', $node, $user) == NODE_ACCESS_DENY) {
    // try to fetch from cache
    $img = bracket_fetch_from_cache($key);
  }
  
  // if image not cached, generate image
  if (!$img) {

    // design image function
    $function = $node->design . '_image';
    if (function_exists($function)) {

      // go generate image 
      $args = array($node);
      $img = call_user_func_array($function, $args);
      
      // save in cache
      bracket_save_in_cache($key, $img);
    }
  }
 
  // send image
  drupal_add_http_header('Content-Type', 'image/png');
  echo $img;
}

/**
 * Output a bracket pdf
 *
 * @param $node
 *   the node containing the bracket
 */
function bracket_pdf($node) {

  global $user;

  // if internal caching is on
  if (variable_get(BRACKET_CACHE, FALSE)) {
    // tell Drupal not to cache this url
    bracket_disable_page_cache();
  }

  // form cache key
  $key = 'bracket/' . $node->nid . '/pdf';

  // don't retrieve from cache for update users
  $img = FALSE;
  if (bracket_node_access('update', $node, $user) == NODE_ACCESS_DENY) {
    // try to fetch from cache
    $img = bracket_fetch_from_cache($key);
  }
  
  // if pdf not cached, generate pdf
  if (!$img) {

    // design pdf function
    $function = $node->design . '_pdf';
    if (function_exists($function)) {

      // go generate pdf
      $args = array($node);
      $img = call_user_func_array($function, $args);

      // save in cache
      bracket_save_in_cache($key, $img);
    }
  }
  
  // force PDF download
  drupal_add_http_header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');

  if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
    drupal_add_http_header('Content-Type', 'application/force-download');
  }
  else {
    drupal_add_http_header('Content-Type', 'application/octet-stream');
  }
    
  // make a file name from title
  $fname = preg_replace('/[^0-9a-z\.\_\-]/i', '_', $node->title);

  // send PDF
  drupal_add_http_header('Content-Disposition', 'attachment; filename="' . $fname .'.pdf"');
  drupal_add_http_header('Content-Length',  strlen($img));
  echo $img;
}

/**
 * Fetch bracket image from cache
 *
 * @param $key
 *   the cache key
 */
function bracket_fetch_from_cache($key) {

  $img = FALSE;
  
  // retrieve from cache if so configured
  if (variable_get(BRACKET_CACHE, FALSE)) {
    $cache = cache_get($key, 'cache');
    if (is_object($cache) && ($cache->data)) {
      $img = $cache->data;
    }
  }
  
  return $img;
}

/**
 * Save bracket image in cache
 *
 * @param $key
 *   the cache key
 * @param $img
 *   the image to cache
 */
function bracket_save_in_cache($key, $img) {

  // save in cache if enabled
  if (variable_get(BRACKET_CACHE, FALSE)) {
    // save in cache
    cache_set($key, $img, 'cache', CACHE_PERMANENT);
  }
}

/**
 * Clear bracket node images from cache
 *
 * @param $node
 *   the node containing the bracket
 */
function bracket_clear_cache($node) {

  // form cache key
  $key = 'bracket/' . $node->nid;
    
  // clear bracket node from the cache
  cache_clear_all($key, 'cache', TRUE);
}

/**
 * Clear all bracket node images from cache
 */
function bracket_clear_cache_all() {

  // clear all bracket images from the cache
  cache_clear_all('bracket', 'cache', TRUE);
}

/**
 * Convert an HTML color to decimal RGB parts
 *
 * Adapted from code at: http://www.anyexample.com/programming/php/php_convert_rgb_from_to_html_hex_color.xml
 *
 * @param $color
 *   the HTML color to convert
 * @return
 *   an array containing the RGB values
 */
function bracket_html2rgb($color) {

  if ($color[0] == '#') {
    $color = substr($color, 1);
  }

  if (strlen($color) == 6) {
    list($r, $g, $b) = array($color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5]);
  }
  elseif (strlen($color) == 3) {
    list($r, $g, $b) = array($color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2]);
  }
  else {
    return FALSE;
  }

  $r = hexdec($r);
  $g = hexdec($g);
  $b = hexdec($b);

  return array($r, $g, $b);
}

/**
 * Return bracket display options
 *
 * @return
 *   an array containing the display options
 */
function bracket_display_options() {
  
  return array('IMAGE' => t('Image'), 'HTML' => t('HTML'));
}

/**
 * Return logo url based on path
 *
 * @return
 *  logo url
 */
function bracket_logo_url($logopath) {

  // if an absolue path, return it
  if (bracket_path_is_url($logopath)) {
    return $logopath;
  }
  // return url
  else {
    // detect root-relative urls - remove root slash so file_create_url will expand it to local server
    $tmp = $logopath;
    if (substr($tmp, 0, 1) == '/') {
      $tmp = substr($tmp, 1);
    }
    return file_create_url($tmp);
  }
}

/**
 * Return logo url based on path
 *
 * @return
 *  true if path is an absolute url
 */
function bracket_path_is_url($path) {

  return preg_match("/^https?:\/\//", $path);
}

/**
 * disable the Drupal page cache (taken from webform module)
 *
 */
function bracket_disable_page_cache() {

  // Drupal 7 method.
  if (function_exists('drupal_page_is_cacheable')) {
    drupal_page_is_cacheable(FALSE);
  }
  // Drupal 6 hack to disable page cache.
  else {
    $GLOBALS['conf']['cache'] = FALSE;
  }
}
