<?php
/**
 * @file
 * Enable different locales to have their own date formats.
 */

/**
 * Implementation of hook_init().
 *
 * Initialize date formats according to the user's current locale.
 */
function date_locale_init() {
  global $conf;
  global $language;

  // Don't do this on the general date and time formats settings page, as we
  // want to display the defaults, not the ones specific to the language we're
  // currently browsing the site in.
  if (!drupal_match_path($_GET['q'], 'admin/settings/date-time/formats')) {
    $languages = array($language->language);
    if (module_exists('site_country')) {
      $country_code = variable_get('site_country_default_country', '');
      if (!empty($country_code)) {
        $country_language = $language->language . '-' . $country_code;
        array_unshift($languages, $country_language);
      }
    }
    drupal_alter('date_format_languages', $languages);

    // Setup appropriate date formats for this locale.
    $formats = date_locale_get_locale_date_format($languages);
    foreach ($formats as $format_type => $format) {
      $conf[$format_type] = $format;
    }
  }
}

/**
 * Implementation of hook_menu().
 */
function date_locale_menu() {
  $items = array();
  $items['admin/settings/date-time/locale'] = array(
    'title' => 'Locale date settings',
    'description' => 'Configure date formats for each locale',
    'type' => MENU_LOCAL_TASK,
    'page callback' => 'drupal_get_form',
    'page arguments' => array('date_locale_format_form'),
    'access arguments' => array('administer site configuration'),
    'weight' => 1,
  );
  return $items;
}

/**
 * Select locale date format details from database.
 *
 * @param $languages
 *   An array of language codes.
 * @return
 *   An array of date formats.
 */
function date_locale_get_locale_date_format($languages) {
  $formats = array();

  // Get list of different format types.
  $format_types = date_get_format_types();
  $short_default = variable_get('date_format_short', 'm/d/Y - H:i');

  // Loop through each language until we find one with some date formats
  // configured.
  foreach ($languages as $language) {
    $date_formats = date_format_locale($language);
    if (!empty($date_formats)) {
      // We have locale-specific date formats, so check for their types.  If
      // we're missing a type, use the default setting instead.
      foreach ($format_types as $type => $type_info) {
        if (isset($date_formats[$type])) {
          $format = $date_formats[$type];

          // If format exists for this language, use it.
          if (!empty($format)) {
            $formats['date_format_' . $type] = $format;
          }
          // Otherwise get default variable setting.  If this is not set, default
          // to the short format.
          else {
            $formats['date_format_' . $type] = variable_get('date_format_' . $type, $short_default);
          }
        }
      }

      // Return on the first match.
      return $formats;
    }
  }

  // No locale specific formats found, so use defaults.
  $system_types = array('short', 'medium', 'long');
  // Handle system types separately as they have defaults if no variable exists.
  $formats['date_format_short'] = $short_default;
  $formats['date_format_medium'] = variable_get('date_format_medium', 'D, m/d/Y - H:i');
  $formats['date_format_long'] = variable_get('date_format_long', 'l, F j, Y - H:i');

  // For non-system types, get the default setting, otherwise use the short
  // format.
  foreach ($format_types as $type => $type_info) {
    if (!in_array($type, $system_types)) {
      $formats['date_format_' . $type] = variable_get('date_format_' . $type, $short_default);
    }
  }

  return $formats;
}

/**
 * Display list of enabled languages to configure date formats for.
 */
function date_locale_format_form($form_state) {
  $form = array();

  if (!isset($form_state['values'])) {
    $step = 'languages';
  }
  else {
    $step = 'config';
  }
  $form['step'] = array(
    '#type' => 'value',
    '#value' => $step,
  );

  // Form part 1: show language selection.
  if ($step == 'languages') {
    // Get list of languages.
    $languages = locale_language_list('native');

    // If site_country module is enabled, add country specific languages to
    // languages array.
    if (module_exists('site_country')) {
      $country_code = variable_get('site_country_default_country', '');
      if (!empty($country_code)) {
        foreach ($languages as $langcode => $name) {
          $country_language = $langcode . '-' . $country_code;
          if (drupal_strlen($langcode) == 2 && !in_array($country_language, array_keys($languages))) {
            $languages[$country_language] = "$name ($country_code)";
          }
        }
      }
    }

    $form['langcode'] = array(
      '#title' => t('Language'),
      '#type' => 'select',
      '#options' => $languages,
      '#multiple' => FALSE,
    );

    $form['buttons']['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Search'),
      '#submit' => array('date_locale_format_form_language_submit'),
    );

  }

  // Form part 2: show date formats for this language.
  else {
    // Add Drupal core's system.js and js settings.
    date_api_add_system_javascript();
    $languages = locale_language_list('native');
    $langcode = $form_state['values']['langcode'];
    $language_name = $languages[$langcode];

    // Display the current language name.
    $form['language_information'] = array(
      '#value' => t('Date format settings for %language_name', array('%language_name' => $language_name)),
      '#prefix' =>'<p style="font-size: 1.2em;">',
      '#suffix' =>'</p>',
    );

    // Get list of date format types.
    $types = date_get_format_types();

    // Get list of available formats.
    $formats = date_get_formats();
    $choices = array();
    foreach ($formats as $type => $list) {
      foreach ($list as $f => $format) {
        $choices[$f] = date_format_date(date_now(), 'custom', $f);
      }
    }

    // Get configured formats for each language.
    $locale_formats = date_format_locale($langcode);
    // Display a form field for each format type.
    foreach ($types as $type => $type_info) {
      if (!empty($locale_formats) && in_array($type, array_keys($locale_formats))) {
        $default = $locale_formats[$type];
      }
      else {
        $default = variable_get('date_format_' . $type, array_shift(array_keys($formats)));
      }
      include_once('./'. drupal_get_path('module', 'date_api') .'/date_api.admin.inc');
      date_api_date_format_select_field($form, $type, $type_info, $default, $choices);
    }

    $form['buttons']['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Save'),
      '#submit' => array('date_locale_format_form_formats_submit'),
    );
    $form['buttons']['cancel'] = array(
      '#type' => 'submit',
      '#value' => t('Cancel'),
      '#submit' => array('date_locale_format_form_formats_cancel'),
    );
  }

  return $form;
}

/**
 * Submit handler for choosing a language on the date_locale_format_form.
 *
 * @param $form
 *   Array, containing the form structure.
 * @param &$form_state
 *   The 'rebuild' key inside $form_state['rebuild'] structure, overrides the
 *   'redirect' key: when it is set to TRUE, the form will be rebuilt from
 *   scratch and displayed on screen.
 */
function date_locale_format_form_language_submit($form, &$form_state) {
  $form_state['rebuild'] = TRUE;
  $form_state['storage']['langcode'] = $form_state['values']['langcode'];
}

/**
 * Submit handler for choosing a language on the date_locale_format_form.
 */
function date_locale_format_form_formats_submit($form, &$form_state) {
  $langcode = $form_state['storage']['langcode'];

  // Get list of date format types.
  $types = date_get_format_types();
  foreach ($types as $type => $type_info) {
    $format = $form_state['values']['date_format_' . $type];
    if ($format == 'custom') {
      $format = $form_state['values']['date_format_' . $type . '_custom'];
    }
    date_locale_locale_format_save($langcode, $type, $format);
  }
  drupal_set_message(t('Configuration saved.'));
  $form_state['storage'] = FALSE;
  $form_state['rebuild'] = FALSE;
  $form_state['redirect'] = 'admin/settings/date-time/locale';
}

/**
 * 'Cancel' button handler for choosing a language on the
 * date_locale_format_form.
 */
function date_locale_format_form_formats_cancel($form, &$form_state) {
  $form_state['storage'] = FALSE;
  $form_state['rebuild'] = FALSE;
  $form_state['redirect'] = 'admin/settings/date-time/locale';
}

/**
 * Save locale specific date formats to the database.
 *
 * @param $langcode
 *   Language code, can be 2 characters, e.g. 'en' or 5 characters, e.g.
 *   'en-CA'.
 * @param $type
 *   Date format type, e.g. 'short', 'medium'.
 * @param $format
 *   The date format string.
 */
function date_locale_locale_format_save($langcode, $type, $format) {
  $locale_format = array();
  $locale_format['language'] = $langcode;
  $locale_format['type'] = $type;
  $locale_format['format'] = $format;

  $is_existing = db_result(db_query("SELECT COUNT(*) FROM {date_format_locale} WHERE language = '%s' AND type = '%s'", $langcode, $type));
  if ($is_existing) {
    $keys = array('type', 'language');
    drupal_write_record('date_format_locale', $locale_format, $keys);
  }
  else {
    drupal_write_record('date_format_locale', $locale_format);
  }

}
