<?php
/**
 * @file
 * Code for the groups Groups feature.
 */

include_once 'groups_groups.features.inc';
/**
 * @file
 * Groups groups content type related extensions.
 */

/**
 * Implements hook_field_default_field_bases_alter
 *
 * Override field base settings defined in module features.
 */
function groups_groups_field_default_field_bases_alter(&$fields) {
  // Override og_group_ref field's Groups Field Settings -> Entity Selection
  // Organic Group's default filter enlist the groups where the user is
  // a group owner.
  if (isset($fields['og_group_ref'])) {
    $fields['og_group_ref']['settings']['handler'] = 'og';
  }
}

/**
 * Implements hook_field_default_field_instances_alter
 *
 * Override field instance settings defined in commons_groups module.
 */
function groups_groups_field_default_field_instances_alter(&$fields) {
  $commons_groups_entity_types = commons_groups_get_group_content_entity_types();
  if (!empty($commons_groups_entity_types)) {
    foreach ($commons_groups_entity_types as $entity_type => $bundles) {
      foreach(array_keys($bundles) as $bundle) {
        // Set Entity reference widget type to Check boxes on commons
        // entity types including an og_group_ref field.
        if (isset($fields["$entity_type-$bundle-og_group_ref"])) {
          $widget = &$fields["$entity_type-$bundle-og_group_ref"]['settings']['behaviors']['og_widget'];
          $widget['admin']['widget_type'] = 'options_buttons';
          $widget['default']['widget_type'] = 'options_buttons';
        }
      }
    }
  }
}

/**
 * Implement hook_node_prepare
 *
 * Add a default not published status to group content type,
 * so group will be placed at review queue.
 */
function groups_groups_node_prepare($node) {
  if (($node->type == 'group') && (empty($node->nid))) {
    $node->status = NODE_NOT_PUBLISHED;
  }
}

/**
 * Lookup latitude and longitude coordinates by location and country
 * using Google's geocode API.
 *
 * @param  string $location Location (eg. Los Angeles, CA)
 * @param  string $country  Country of the location
 * @return array            lat, lng coordinates
 */
function _groups_groups_lookup_lat_lng($location, $country) {
  $query = array(
    'components' => 'country:'.$country,
    'sensor' => 'false',
  );
  if (isset($location)) {
    $query['address'] = $location;
  }
  watchdog('Groups groups', 'Lookup geolocation data [query=@query]',
    array('@query' => print_r($query, TRUE)), WATCHDOG_DEBUG);
  $url = 'http://maps.googleapis.com/maps/api/geocode/json?' . drupal_http_build_query($query);
  $response = drupal_http_request($url);
  if (empty($response->error)) {
    $data = json_decode($response->data);
    if ($data->status == 'OK') {
      foreach ($data->results as $result) {
        if (!empty($result->formatted_address)) {
          watchdog('Groups groups', 'Lookup geolocation data result @lat;@lng [query=@query]',
            array('@query' => print_r($query, TRUE),
              '@lat' => $result->geometry->location->lat,
              '@lng' => $result->geometry->location->lng), WATCHDOG_DEBUG);
          return array($result->geometry->location->lat, $result->geometry->location->lng);
        }
      }
    }
  }
  throw new Exception(t('Failed to lookup geolocation data [query=@query].', array('@query' => print_r($query, TRUE))));
}

/**
 * Implements hook node presave
 *
 * Update geofield from group location values. Override lat / long values
 * when field_geofield is empty.
 */
function groups_groups_node_presave($node) {
  if (($node->type == 'group') && (empty($node->field_geofield[LANGUAGE_NONE]))) {
    try {
      geophp_load();
      list($lat, $lng) = _groups_groups_lookup_lat_lng(
        $node->field_group_location['und'][0]['location'],
        $node->field_group_location['und'][0]['country']);
      $geom = new Point($lng, $lat);
      $geofield = geofield_get_values_from_geometry($geom);
      $geofield['geom'] = 'POINT (' . $lng . ' ' . $lat . ')';
      $node->field_geofield = array('und'=>array($geofield));
    } catch (Exception $e) {
      watchdog('Groups groups', 'Node presave failed: @err',
        array('@err' => $e->getMessage()), WATCHDOG_ERROR);
    }
  }
}

/**
 * Implements hook_theme()
 *
 * Define theme template for group node form.
 */
function groups_groups_theme() {
  $path = drupal_get_path('module', 'groups_groups').'/templates';
  return array(
    'groups_groups_group_node_form' => array(
      'arguments' => array('form' => NULL),
      'template' => 'groups-groups--group-node-form',
      'render element' => 'form',
      'path' => $path,
    ),
  );
}

/**
 * Implements hook_text_format_alter.
 *
 * Set default text format to markdown for the group/body field.
 */
function groups_groups_text_format_alter(&$element) {
  $bundles = array('group', 'post');
  if ((isset($element['#bundle'])) && (isset($element['#field_name']))) {
    if ((in_array($element['#bundle'], $bundles)) && ($element['#field_name'] == 'body')) {
      // set default value to markdown
      $element['format']['format']['#default_value'] = 'markdown';
      // hide text format filter
      $element['format']['#access'] = FALSE;
    }
  }
}

/**
 * Implements hook_form_alter().
 *
 * Override group node form and alter content forms.
 */
function groups_groups_form_alter(&$form, &$form_state, $form_id) {
  global $user;
  // ensure group is selected for non-administrator users and
  // make the og_group_ref field mandatory.
  $commons_entity_integrations = commons_entity_integration_info();
  if (!empty($commons_entity_integrations['node'])) {
    foreach ($commons_entity_integrations['node'] as $bundle => $options) {
      if ($form_id == $bundle.'_node_form') {
        $is_administrator = in_array('administrator', array_values($user->roles));
        if ($is_administrator == false) {
          $form['og_group_ref'][LANGUAGE_NONE][0]['#required'] = true;
        }
      }
    }
  }
  if ($form_id == 'group_node_form') {
    $node = $form_state['node'];
    $is_administrator = in_array('administrator', array_values($user->roles));
    $is_community_mgr = in_array('community_manager', array_values($user->roles));
    $is_group_admin = og_user_access('node', $node->nid, 'administer group');
    // hide group status field
    $form['field_group_status']['#access'] = $is_administrator;
    // hide location geofield
    $form['field_geofield']['#access'] = $is_administrator;
    // hide privacy settings field
    $form['field_og_subscribe_settings']['#access'] = $is_administrator;
    // hide meetup members field
    $form['field_meetup_members']['#access'] = $is_administrator;
    // hide group logo
    $form['field_group_logo']['#access'] = false;
    // allow ambassador assignment for admin or community managers
    $form['field_ambassadors']['#access'] = $is_community_mgr || $is_administrator;

    // allow group admins to modify timezone field
    $form['field_timezone']['#access'] = $is_community_mgr || $is_group_admin
      || $is_administrator;

    // allow group admins to manage group membership field
    $form['field_group_members']['#access'] = $is_community_mgr || $is_group_admin
      || $is_administrator;
    $form['field_group_members_source']['#access'] = $is_community_mgr || $is_group_admin
      || $is_administrator;

    $form['field_group_location']['und'][0]['location']['#title'] = 'City (optional)';
    // reorder resource links, group location
    $form['field_resource_links']['#weight'] = 21;
    $form['revision_information']['#access'] = $is_administrator;
    $form['topics_wrapper']['#access'] = $is_administrator;
    $form['actions']['preview']['#access'] = false;
    if (!isset($node->nid) || isset($node->is_new)) {
      $form['#theme'] = 'groups_groups_group_node_form';
      $form['actions']['submit']['#value'] = t('Register user group');
      $form['field_resource_links']['#access'] = false;
      $form['accept_terms'] = array(
        '#type' => 'checkbox',
        '#title' => t('I have read and agree the !termsurl and !eventurl', array(
            '!termsurl' => l(t('Code of Conduct'), 'http://www.openstack.org/legal/community-code-of-conduct/'),
            '!eventurl' => l(t('OpenStack Event Policy'), 'http://www.openstack.org/brand/event-policy/'),
          )),
        '#weight' => 22,
      );
       $form['field_group_location']['und'][0]['#title'] = '';
       $form['title_field']['und'][0]['#title'] = 'Name of the User Group';
       $form['body']['und'][0]['#title'] = 'Tell a few words about your User Group';
    }
    $form['#validate'][] = 'groups_groups_group_node_form_validate';
  }
}

/**
 * Group node form validate callback.
 *
 * Validate the Terms and Conditions checkbox status.
 */
function groups_groups_group_node_form_validate($form, &$form_state) {
  if ((isset($form_state['values']['accept_terms'])) && ($form_state['values']['accept_terms'] != 1)) {
    form_set_error('accept_terms', t('You must accept the Terms and Conditions.'));
  }
}

/**
 * Implements hook_og_user_access_alter().
 *
 * Revert the commons_groups_og_user_access_alter() hook, and disable content
 * creation for non-group members on publicly visible groups.
 *
 * @see commons_groups_og_user_access_alter()
 */
function groups_groups_og_user_access_alter(&$perm, $context) {
  $account = $context['account'];
  $group_type = $context['group_type'];
  $group = $context['group'];
  if ($group_type != 'node') {
    return;
  }
  if (og_is_member($group_type, $group->nid, 'user', $account, array(OG_STATE_ACTIVE, OG_STATE_PENDING, OG_STATE_BLOCKED))) {
    // The user is a group member, so comply to the OG permissions.
    return;
  }
  $commons_groups_entity_types = commons_groups_get_group_content_entity_types();
  foreach (array_keys($commons_groups_entity_types['node']) as $type) {
    $perm["create $type content"] = FALSE;
  }
}

/**
 * Implements hook_node_access()
 *
 * Allows to view unpublished group nodes for users with
 * ambassador or community manager role.
 */
function groups_node_access($node, $op, $account) {
  if (is_string($node)) {
    return NODE_ACCESS_IGNORE;
  }
  if ((in_array('ambassador', $account->roles)) ||
     (in_array('community_manager', $account->roles))) {
    if (($node->type == 'group') && ($node->status == 0)) {
      return NODE_ACCESS_ALLOW;
    }
  }
  return NODE_ACCESS_IGNORE;
}
