<?php
/**
 * @file
 * A key/value field implementation where the key is selectable from a
 * drop-down list.
 */

 function field_property_list_key_lookup() {
   return array(
    0 => t('Website'),
    1 => t('IRC Channel'),
    2 => t('Twitter (handle)'),
    3 => t('Twitter hashtag'),
    4 => t('Blog'),
    5 => t('Meetup'),
    6 => t('Google groups'),
    7 => t('Linkedin group'),
    8 => t('Google group'),
    9 => t('Facebook'),
    10 => t('Facebook group'),
    11 => t('Forum'),
    12 => t('E-mail'),
    13 => t('Calendar'),
    14 => t('Weibo'),
    15 => t('Slideshare'),
    16 => t('Mailing list'),
    17 => t('Launchpad)'),
    18 => t('Google plus'),
    19 => t('Coordinators'),
  );
 }

/**
 * Implements hook_field_info().
 *
 * Provides the description of the field.
 */
function field_property_list_field_info() {
  return array(
    'field_property_list' => array(
      'label' => t('Property list'),
      'description' => t('Provide a key/value field implementation.'),
      'default_widget' => 'field_property_list',
      'default_formatter' => 'field_property_list_raw',
    ),
  );
}

/**
 * Implements hook_field_validate().
 */

function field_property_list_field_validate($entity_type, $entity, $field,
  $instance, $langcode, $items, &$errors) {
  // TODO: implement hook_field_validate
}

/**
 * Implements hook_field_is_empty().
 */
function field_property_list_field_is_empty($item, $field) {
  return empty($item['value']);
}

/**
 * Implements hook_field_formatter_info().
 */
function field_property_list_field_formatter_info() {
  return array(
    'field_property_list_raw' => array(
      'label' => t('Raw property list'),
      'field types' => array('field_property_list'),
    ),
  );
}

/**
 * Implements hook_field_formatter_view().
 */
function field_property_list_field_formatter_view($entity_type, $entity, $field,
  $instance, $langcode, $items, $display) {
  $element = array();

  $module_path = drupal_get_path('module', 'field_property_list');
  drupal_add_css($module_path . '/field_property_list.css');

  $key_lookup = field_property_list_key_lookup();

  switch ($display['type']) {
    // This formatter simply outputs the field as text and with a color.
    case 'field_property_list_raw':
      foreach ($items as $delta => $item) {
        if ($item['key'] == '19') {
          // remove email address part from coordinator field
          $value = strip_tags($item['value']);
        } else {
          $value = preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.-]*'.
            '(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $item['value']);
        }
        $element[$delta] = array(
          'title' => array(
            '#type' => 'html_tag',
            '#tag' => 'div',
            '#value' => $key_lookup[$item['key']],
            '#attributes' => array('class' => array('property-title',
              'property-type-'.$item['key'])),
          ),
          'value' => array(
            '#type' => 'html_tag',
            '#tag' => 'div',
            '#value' => $value,
            '#attributes' => array('class' => array('property-value')),
          ),
        );
      }
      break;
  }

  return $element;
}

/**
 * Implements hook_field_widget_info().
 */
function field_property_list_field_widget_info() {
  return array(
    'field_property_list' => array(
      'label' => t('Field property list'),
      'field types' => array('field_property_list'),
    ),
  );
}

/**
 * Implements hook_field_widget_form().
 *
 */
function field_property_list_field_widget_form(&$form, &$form_state, $field,
  $instance, $langcode, $items, $delta, $element) {

  $key = isset($items[$delta]['key']) ? $items[$delta]['key'] : null;
  $value = isset($items[$delta]['value']) ? $items[$delta]['value'] : null;

  $widget = array(
    '#theme_wrappers' => array('container', 'form_element'),
    '#attributes' => array('class' => array('property-list-field-elements', 'container-inline')),
  );

  switch ($instance['widget']['type']) {
    case 'field_property_list':
      $widget += array(
        '#type' => 'fieldset',
        '#delta' => $delta,
      );
      $widget['key'] = array(
        '#type' => 'select',
        '#default_value' => $key,
        '#options' => field_property_list_key_lookup(),
      );
      $widget['value'] = array(
        '#type' => 'textfield',
        '#default_value' => $value,
        '#maxlength' => 256,
      );
      $element['field_remove_item'] = array(
        '#type' => 'button',
        '#value' => t('Remove'),
        '#weight' => 10,
        '#name' => drupal_html_class('op-remove-'. $field['field_name'].'-'.
          $langcode.'-'.$delta),
        '#ajax' => array(
          'callback' => 'field_property_list_field_ajax_callback',
        ),
        '#limit_validation_errors' => array(),
      );
      break;
  }
  return $element + $widget;
}

function field_property_list_field_ajax_callback(&$form, $form_state) {
  $wrapper = '.' . $form['#field_remove_item']['wrapper'];
  $field_name = $form['#field_remove_item']['field_name'];

  return array(
    '#type' => 'ajax',
    '#commands' => array(
      ajax_command_replace($wrapper, render($form[$field_name])),
    ),
  );
}

/**
 * Implements hook_form_alter().
 *
 * Remove field item.
 *
 */

function field_property_list_form_alter(&$form, &$form_state, $form_id) {
  if (isset($form_state['triggering_element']['#parents'][3]) &&
    $form_state['triggering_element']['#parents'][3] == 'field_remove_item') {

    $field_name = $form_state['triggering_element']['#parents'][0];
    $field_language = $form_state['triggering_element']['#parents'][1];
    $field_delta = $form_state['triggering_element']['#parents'][2];

    if ($form[$field_name][$field_language]['#cardinality'] == FIELD_CARDINALITY_UNLIMITED) {
      $form['#field_remove_item'] = array(
        'wrapper' => $form[$field_name]['#attributes']['class'][1],
        'field_name' => $field_name,
      );
      // Remove field item.
      unset($form[$field_name][$field_language][$field_delta]);

      if (!isset($form_state['#field_remove_item'])) {
        $form_state['#field_remove_item'] = array();
      }
      // Memorize this removal.
      $form_state['#field_remove_item'][$field_name][$field_language][] = $field_delta;
    }
  }

  // Remove all items again in case the form submission fails validation.
  if (!empty($form_state['#field_remove_item'])) {
    foreach ($form_state['#field_remove_item'] as $field_name => $field_values) {
      foreach ($field_values as $field_language => $field_deltas) {
        foreach ($field_deltas as $field_delta) {
          if (isset($form[$field_name][$field_language][$field_delta])) {
            unset($form[$field_name][$field_language][$field_delta]);
          }
        }
      }
    }
  }
}
