<?php

/**
 * @file
 * Hight contrast main file.
 */

/*
TO-DO:
 - Provide hooks: hook_high_contrast_enable, hook_high_contrast_disable
 - Make it work if cache is enabled
 - Add widgets: select list, radio buttons, etc.
 - Improve CSS stylesheet
 - Logo change only works with delta_blocks modules logo block.
 - Default high contrast logo can only be png (logo-hg.png). Should also be jpg.
*/

define('HIGH_CONTRAST_CSS_PATH', 'css/high_contrast.css');

/**
 * Implements hook_init().
 */
function high_contrast_init() {
  $theme_path = drupal_get_path('theme', variable_get('theme_default', NULL));
  drupal_add_css(drupal_get_path('module', 'high_contrast') . '/high_contrast.css');

  drupal_add_js(array('highContrast' => array('link' => _high_contrast_link())), 'setting');
  drupal_add_js(drupal_get_path('module', 'high_contrast') . '/js/high_contrast_link.js', array('scope' => 'footer'));

  if (isset($_SESSION['high_contrast_activated']) && $_SESSION['high_contrast_activated'] == 1) {
    if (_high_contrast_css_exists()) {
      drupal_add_css($theme_path . '/' . HIGH_CONTRAST_CSS_PATH, array(
        'group' => 10000,
        'weight' => 10000,
      ));
    }
    else {
      drupal_add_css(_high_contrast_get_current_css_styles(), array(
        'group' => 10000,
        'type' => 'inline',
        'weight' => 10000,
      ));
    }
  }
}

/**
 * Implements hook_menu().
 */
function high_contrast_menu() {

  $items['admin/config/user-interface/high-contrast'] = array(
    'title' => 'High Contrast',
    'description' => 'Settings related to High Contrast',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('high_contrast_settings_form'),
    'access callback' => 'user_access',
    'access arguments' => array('administer site configuration'),
  );

  $items['high_contrast_toggle'] = array(
    'title' => 'Activate high contrast styles',
    'description' => '',
    'page callback' => 'high_contrast_toggle_callback',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );

  return $items;
}

/**
 * Implements hook_block_info().
 */
function high_contrast_block_info() {
  $blocks = array();

  $blocks['high_contrast_switcher'] = array(
    'info' => t('High contrast switcher'),
    'cache' => DRUPAL_CACHE_GLOBAL,
  );

  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function high_contrast_block_view($delta = '') {
  $block = array();

  switch ($delta) {
    case 'high_contrast_switcher':
      $block['subject'] = '<none>';
      $block['content'] = theme('high_contrast_switcher');
      break;
  }

  return $block;
}

/**
 * Settings form.
 */
function high_contrast_settings_form() {
  $form = array();
  $theme_path = drupal_get_path('theme', variable_get('theme_default', NULL));

  $widgets = array(
    'links' => 'Links',
    // 'select' => 'Select list',
    // 'radio' => 'Radio buttons',
  );

  $form['high_contrast_switcher_widget'] = array(
    '#type' => 'select',
    '#title' => t('Switcher widget'),
    '#default_value' => _high_contrast_variable_get('high_contrast_switcher_widget'),
    '#options' => $widgets,
    '#required' => TRUE,
  );

  $form['high_contrast_switcher_label'] = array(
    '#type' => 'textfield',
    '#title' => t('Switcher label'),
    '#default_value' => _high_contrast_variable_get('high_contrast_switcher_label'),
    '#required' => TRUE,
  );

  $form['high_contrast_high_label'] = array(
    '#type' => 'textfield',
    '#title' => t('High contrast label'),
    '#default_value' => _high_contrast_variable_get('high_contrast_high_label'),
    '#required' => TRUE,
  );

  $form['high_contrast_separator'] = array(
    '#type' => 'textfield',
    '#title' => t('Separator'),
    '#default_value' => _high_contrast_variable_get('high_contrast_separator'),
    '#required' => TRUE,
  );

  $form['high_contrast_normal_label'] = array(
    '#type' => 'textfield',
    '#title' => t('Normal contrast label'),
    '#default_value' => _high_contrast_variable_get('high_contrast_normal_label'),
    '#required' => TRUE,
  );

  if (!_high_contrast_css_exists()) {
    $form['high_contrast_css_styles'] = array(
      '#type' => 'textarea',
      '#title' => t('Used CSS styles'),
      '#default_value' => _high_contrast_get_current_css_styles(),
      '#required' => TRUE,
      '#attributes' => array(
        'style' => 'width:50em; height:30em; line-height:1.2em; font-family:"Courier New", "Courier";',
      ),
      '#suffix' => '<p>' . t('Default CSS styles used to override the active theme') . ':</p><div><pre>' . _high_contrast_get_default_css_styles() . '</pre></div>',
      '#description' => 'To use css file, create high_contrast.css file under your theme css folder (' . HIGH_CONTRAST_CSS_PATH . ').',
    );
  }
  else {
    $form['high_contrast_css_styles'] = array(
      '#type' => 'item',
      '#markup' => t('High contrast is using !css_path', array('!css_path' => $theme_path . '/' . HIGH_CONTRAST_CSS_PATH)),
    );
  }

  $form['high_contrast_logo'] = array(
    '#type' => 'fieldset',
    '#title' => t('High contrast logo image settings'),
    '#description' => t('If toggled on, the following high contrast logo will be displayed.'),
    '#attributes' => array('class' => array('theme-settings-bottom')),
  );

  $form['high_contrast_logo']['high_contrast_default_logo'] = array(
    '#type' => 'checkbox',
    '#title' => t('Use the default logo (file named logo-hg in your theme folder if it exists'),
    '#default_value' => _high_contrast_variable_get('high_contrast_default_logo'),
    '#tree' => FALSE,
    '#description' => t('Check here if you want the theme to use the logo supplied with it.'),
  );

  $form['high_contrast_logo']['high_contrast_settings'] = array(
    '#type' => 'container',
    '#states' => array(
      // Hide the logo settings when using the default logo.
      'invisible' => array(
        'input[name="high_contrast_default_logo"]' => array('checked' => TRUE),
      ),
    ),
  );

  $form['high_contrast_logo']['high_contrast_settings']['high_contrast_logo_path'] = array(
    '#type' => 'textfield',
    '#title' => t('Path to custom high contrast logo'),
    '#description' => t('The path to the file you would like to use as your logo file instead of the default logo.'),
    '#default_value' => _high_contrast_variable_get('high_contrast_logo_path'),
  );

  $form['high_contrast_logo']['high_contrast_settings']['high_contrast_logo_upload'] = array(
    '#type' => 'file',
    '#title' => t('Upload high contrast logo image'),
    '#maxlength' => 40,
    '#description' => t("If you don't have direct file access to the server, use this field to upload your logo."),
  );

  $form = system_settings_form($form);
  // We don't want to call system_settings_form_submit(), so change #submit.
  array_pop($form['#submit']);
  $form['#submit'][] = 'high_contrast_settings_form_submit';
  $form['#validate'][] = 'high_contrast_settings_form_validate';
  return $form;
}

/**
 * Implements hook_preprocess_HOOK().
 */
function high_contrast_preprocess_delta_blocks_logo(&$variables) {
  if (isset($_SESSION['high_contrast_activated']) && $_SESSION['high_contrast_activated'] == 1) {
    $theme_path = drupal_get_path('theme', variable_get('theme_default', NULL));
    if (_high_contrast_variable_get('high_contrast_default_logo') == 0 && _high_contrast_variable_get('high_contrast_logo_path') !== '') {
      $variables['logo'] = file_create_url(_high_contrast_variable_get('high_contrast_logo_path'));
    }
    elseif (file_exists($theme_path . '/logo-hg.png')) {
      $variables['logo'] = file_create_url($theme_path . '/logo-hg.png');
    }
  }
}

/**
 * Validator for the system_theme_settings() form.
 */
function high_contrast_settings_form_validate($form, &$form_state) {
  // Handle file uploads.
  $validators = array('file_validate_is_image' => array());

  // Check for a new uploaded logo.
  $file = file_save_upload('high_contrast_logo_upload', $validators);
  if (isset($file)) {
    // File upload was attempted.
    if ($file) {
      // Put the temporary file in form_values so we can save it on submit.
      $form_state['values']['high_contrast_logo_upload'] = $file;
    }
    else {
      // File upload failed.
      form_set_error('high_contrast_logo_upload', t('The logo could not be uploaded.'));
    }
  }
}

/**
 * Process high_contrast_settings_form form submissions.
 */
function high_contrast_settings_form_submit($form, &$form_state) {
  // Exclude unnecessary elements before saving.
  form_state_values_clean($form_state);

  $values = $form_state['values'];

  // Extract the name of the theme from the submitted form values, then remove
  // it from the array so that it is not saved as part of the variable.
  $key = $values['var'];
  unset($values['var']);

  // If the user uploaded a new logo or favicon, save it to a permanent location
  // and use it in place of the default theme-provided file.
  if ($file = $values['high_contrast_logo_upload']) {
    unset($values['high_contrast_logo_upload']);
    $filename = file_unmanaged_copy($file->uri);
    $values['high_contrast_default_logo'] = 0;
    $values['high_contrast_logo_path'] = $filename;
    $values['high_contrast_toggle_logo'] = 1;
  }

  // If the user entered a path relative to the system files directory for
  // a logo or favicon, store a public:// URI so the theme system can handle it.
  if (!empty($values['high_contrast_logo_path'])) {
    $values['high_contrast_logo_path'] = _high_contrast_theme_settings_validate_path($values['high_contrast_logo_path']);
  }

  foreach ($values as $key => $val) {
    variable_set($key, $val);
  }

  drupal_set_message(t('The configuration options have been saved.'));

  cache_clear_all();
}

/**
 * Menu callback to enable the high contrast styles.
 */
function high_contrast_toggle_callback() {
  if (isset($_SESSION['high_contrast_activated']) && $_SESSION['high_contrast_activated'] == 1) {
    high_contrast_switch(FALSE);
  }
  else {
    high_contrast_switch(TRUE);
  }
}

/**
 * Toggle high contrast styles and redirects the user to a destination url.
 */
function high_contrast_switch($enable = FALSE) {
  $destination = '';
  $_SESSION['high_contrast_activated'] = $enable;
  if (isset($_GET['destination'])) {
    $destination = $_GET['destination'];
  }
  drupal_goto($destination);
}

/**
 * Implements hook_theme().
 */
function high_contrast_theme() {
  return array(
    'high_contrast_switcher' => array(
      'render element' => 'element',
    ),
    'high_contrast_switcher_links' => array(
      'render element' => 'element',
    ),
  );
}

/**
 * Theme function for high contrast switcher.
 */
function theme_high_contrast_switcher($vars) {
  $code = theme('high_contrast_switcher_links');

  /*
  //TO-DO: More widgets
  $widget = _high_contrast_variable_get('high_contrast_widget');

  if ($widget == 'select'){
  $code = theme('high_contrast_switcher_select');
  }
  else if ($widget == 'radio'){
  $code = theme('high_contrast_switcher_radio');
  }
  else{
  $code = theme('high_contrast_switcher_links');
  }
  */

  return $code;
}

/**
 * Get HTML for switcher links().
 */
function theme_high_contrast_switcher_links($vars) {
  $label = t(_high_contrast_variable_get('high_contrast_switcher_label'));

  $current_url = drupal_get_destination();

  if (isset($_SESSION['high_contrast_activated']) && $_SESSION['high_contrast_activated'] == 1) {
    $link_high = t(_high_contrast_variable_get('high_contrast_high_label'));
    $link_normal = l(
      t(_high_contrast_variable_get('high_contrast_normal_label')),
      'high_contrast_toggle',
      array(
        'query' => array('destination' => $current_url['destination']),
        'attributes' => array('rel' => 'nofollow'),
      )
    );
  }
  else {
    $link_high = l(
      t(_high_contrast_variable_get('high_contrast_high_label')),
      'high_contrast_toggle', array(
        'query' => array('destination' => $current_url['destination']),
        'attributes' => array('rel' => 'nofollow'),
      )
    );
    $link_normal = t(_high_contrast_variable_get('high_contrast_normal_label'));
  }

  $separator = _high_contrast_variable_get('high_contrast_separator');

  // Output.
  $code = '
    <div class="high_contrast_switcher high_contrast_switcher_links">
      <p>
        <span class="high_contrast_switcher_label">' . $label . '</span>' .
        '<span class="high_contrast_switcher_high' . (isset($_SESSION['high_contrast_activated']) && $_SESSION['high_contrast_activated'] == 0 ? ' has-switcher-link' : '') . '">' . $link_high . '</span>' .
        '<span class="high_contrast_switcher_separator">' . $separator . '</span>' .
        '<span class="high_contrast_switcher_normal' . (isset($_SESSION['high_contrast_activated']) && $_SESSION['high_contrast_activated'] == 1 ? ' has-switcher-link' : '') . '">' . $link_normal . '</span>' .
      '</p>
    </div>
    ';

  return $code;
}

/**
 * Implements hook_preprocess_html().
 */
function high_contrast_preprocess_html(&$vars) {
  if (isset($_SESSION['high_contrast_activated']) && $_SESSION['high_contrast_activated'] == 1) {
    $vars['classes_array'][] = 'high-contrast';
  }
}

/**
 * HELPER FUNCTIONS.
 */

/**
 * Wrapper for variable_get().
 */
function _high_contrast_variable_get($var) {
  return (variable_get($var, ''));
}

/**
 * Get default css styles if none exist yet.
 */
function _high_contrast_get_current_css_styles() {
  $theme_path = drupal_get_path('theme', variable_get('theme_default', NULL));

  if (_high_contrast_css_exists()) {
    $styles = file_get_contents($theme_path . '/' . HIGH_CONTRAST_CSS_PATH);
  }
  else {
    $styles = _high_contrast_variable_get('high_contrast_css_styles');

    if (empty($styles)) {
      $styles = _high_contrast_get_default_css_styles();
      variable_set('high_contrast_css_styles', $styles);
    }
  }

  return $styles;
}

/**
 * Get current url.
 */
function _high_contrast_get_current_url() {
  global $base_url;
  return $base_url . $_SERVER['REQUEST_URI'];
}

/**
 * Default CSS.
 */
function _high_contrast_get_default_css_styles() {

  $color1 = 'black';
  $color2 = 'yellow';
  $color3 = 'white';

  $css = '
*{
  background-color:' . $color1 . ' !important;
  background-image:none !important;
  color:' . $color3 . ' !important;
  line-height:1.5em !important;
  text-shadow: none !important;
}

a, a *{
  background-color:' . $color1 . ' !important;
  color:' . $color2 . ' !important;
  text-decoration:underline !important;
}
  a:hover, a:hover *{
    background-color:' . $color2 . ' !important;
    color:' . $color1 . ' !important;
    text-decoration:underline !important;
    text-decoration:none !important;
  }

input{
  background-color:' . $color3 . ' !important;
  color:' . $color1 . ' !important;
}

input[type=submit],
input[type=button],
button{
  background-color: ' . $color2 . ' !important;
  color: ' . $color1 . ' !important;
}
  input[type=submit]:hover,
  input[type=button]:hover,
  button:hover{
    text-decoration:underline !important;
  }
';

  return $css;
}

/**
 * Helper function for the system_theme_settings form.
 *
 * Attempts to validate normal system paths, paths relative to the public files
 * directory, or stream wrapper URIs. If the given path is any of the above,
 * returns a valid path or URI that the theme system can display.
 *
 * @param string $path
 *   A path relative to the Drupal root or to the public files directory, or
 *   a stream wrapper URI.
 *
 * @return mixed
 *   A valid path that can be displayed through the theme system, or FALSE if
 *   the path could not be validated.
 */
function _high_contrast_theme_settings_validate_path($path) {
  // Absolute local file paths are invalid.
  if (drupal_realpath($path) == $path) {
    return FALSE;
  }
  // A path relative to the Drupal root or a fully qualified URI is valid.
  if (is_file($path)) {
    return $path;
  }
  // Prepend 'public://' for relative file paths within public filesystem.
  if (file_uri_scheme($path) === FALSE) {
    $path = 'public://' . $path;
  }
  if (is_file($path)) {
    return $path;
  }
  return FALSE;
}

/**
 * Helper function to find out if the css/high_contrast.css exists.
 */
function _high_contrast_css_exists() {
  $theme_path = drupal_get_path('theme', variable_get('theme_default', NULL));
  if (file_exists($theme_path . '/' . HIGH_CONTRAST_CSS_PATH)) {
    return TRUE;
  }
  else {
    return FALSE;
  }
}

/**
 * Return high contrast toggle link HTML.
 * @return string HTML for toggle link.
 */
function _high_contrast_link() {
  $destination = drupal_get_destination();
  return l(
    t('Toggle high contrast'),
    'high_contrast_toggle', array(
      'query' => array('destination' => $destination['destination']),
      'attributes' => array(
        'class' => array('element-invisible', 'element-focusable'),
        'rel' => 'nofollow',
      ),
    )
  );
}
