<?php
/**
 * @file
 * Adds a Markdown feed processor to the Feeds module.
 */

/**
 * Implements hook_menu().
 */
function groups_feeds_menu() {
  $items['feed/groups.json'] = array(
    'title' => 'Export groups data',
    'description' => 'Export groups data in json format',
    'page callback' => 'groups_feeds_json_export_groups',
    'access callback' => TRUE,
    'file' => 'groups_feeds.groups_json.inc',
  );
  $items['node/%node/sync'] = array(
    'title' => 'Sync Settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('groups_feeds_sync_settings', 1),
    'access callback' => 'groups_feeds_sync_access',
    'access arguments' => array(1),
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

/**
 * Implements a hook_access() callback.
 *
 * Allow override sync settings for group administrator,
 * ambassador and community_manager roles.
 */
function groups_feeds_sync_access($group_node) {
  global $user;
  if ((empty($group_node)) || ($group_node->type != 'group')) {
    return FALSE;
  }
  // allow modify sync settings for group administrator
  if (og_user_access('node', $group_node->nid, 'administer group')) {
    return TRUE;
  }
  // allow override sync settings for amabassadors and community manageres
  if ((in_array("ambassador", $user->roles)) || (in_array("community_manager", $user->roles))) {
    return TRUE;
  }
  return FALSE;
}

/**
 * Sync settings form callback.
 */
function groups_feeds_sync_settings($formid, $form_state, $group_node) {
  $nid = $group_node->nid;
  $meetup_url = NULL;
  foreach ($group_node->field_resource_links[LANGUAGE_NONE] as $resource) {
    if ($resource['key'] == '5') {
      $meetup_url = $resource['value'];
    }
  }
  $form['nid'] = array('#type' => 'value', '#value' => $nid);
  $form['description'] = array(
    '#markup' => '<p>' . t('Synchronization settings for group data. '). '</p>',
  );
  $url = 'https://git.openstack.org/cgit/openstack-infra/groups-static-pages';
  $form['sync_groups'] = array(
    '#type' => 'checkbox',
    '#prefix' =>
      '<h3>'.t('OpenStack static pages repository').'</h3>'.
      '<div class="sync-link"><span class="label label-default">'.l($url, $url).'</span></div>',
    '#title' => 'Import group data from groups.json',
    '#default_value' => variable_get('groups_sync_group_'.$nid, TRUE),
  );
  if (!empty($meetup_url)) {
    // show meetup sync only for groups with meetup link
    $form['sync_events'] = array(
      '#type' => 'checkbox',
      '#prefix' => '<h3>'.t('Meetup.com synchronization').'</h3>'.
        '<div class="sync-link"><span class="label label-default">'.l($meetup_url, $meetup_url).'</span></div>',
      '#title' => 'Import event calendar from meetup.com',
      '#default_value' => variable_get('groups_sync_event_'.$nid, TRUE),
    );
    $form['sync_meetup'] = array(
      '#type' => 'checkbox',
      '#title' => 'Import group stats from meetup.com',
      '#default_value' => variable_get('groups_sync_meetup_'.$nid, TRUE),
    );
  }
  $form['actions']['#type'] = 'actions';
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save configuration'),
  );
  return $form;
}

/**
 * Implements hook_form_submit().
 */
function groups_feeds_sync_settings_submit($form, &$form_state) {
  $nid = $form_state['values']['nid'];
  if (!empty($nid)) {
    if (isset($form_state['values']['sync_events'])) {
      variable_set('groups_sync_event_'.$nid, $form_state['values']['sync_events']);
    }
    if (isset($form_state['values']['sync_groups'])) {
      variable_set('groups_sync_group_'.$nid, $form_state['values']['sync_groups']);
    }
    if (isset($form_state['values']['sync_meetup'])) {
      variable_set('groups_sync_meetup_'.$nid, $form_state['values']['sync_meetup']);
    }
  }
}

/**
 * Implements hook_feeds_plugins().
 */
function groups_feeds_feeds_plugins() {
  $info = array();
  $info['MarkdownParser'] = array(
    'name' => 'Markdown parser',
    'description' => 'Parses markdowns with jekyll like yaml header.',
    'handler' => array(
      'parent' => 'FeedsParser',
      'class' => 'FeedsMarkdownParser',
      'file' => 'FeedsMarkdownParser.inc',
      'path' => drupal_get_path('module', 'groups_feeds'),
    ),
  );
  return $info;
}

/**
 * Implements hook_ctools_plugin_api().
 */
function groups_feeds_ctools_plugin_api($owner, $api) {
  if ($owner == 'feeds' && $api == 'plugins') {
    return array('version' => 1);
  }
  if ($owner == 'feeds' && $api == 'feeds_importer_default') {
    return array('version' => 1);
  }
}

/**
 * Implements hook_cronapi()
 *
 * Define groups_feeds module's scheduled jobs.
 */
function groups_feeds_cronapi($op, $job = NULL) {
  $items['user_groups_import'] = array(
    'description' => 'Import user group data from groups.json of openstack-infra/groups-static-pages repo',
    'rule'        => '0 * * * *',
    'callback'    => 'groups_feeds_user_groups_import',
    'arguments'   => array(),
    'file'        => 'groups_feeds_user_groups.inc',
    'file path'   => drupal_get_path('module', 'groups_feeds').'/includes',
  );
  $items['static_pages_import'] = array(
    'description' => 'Import static page content from openstack-infra/groups-static-pages repo',
    'rule'        => '*/5 * * * *',
    'callback'    => 'groups_feeds_static_pages_import',
    'arguments'   => array(),
    'file'        => 'groups_feeds_static_pages.inc',
    'file path'   => drupal_get_path('module', 'groups_feeds').'/includes',
  );
  $items['meetup_events_import'] = array(
    'description' => 'Import events from iCal feeds of meetup.com.',
    'rule'        => '0 * * * *',
    'callback'    => 'groups_feeds_meetup_events_import',
    'arguments'   => array(),
    'file'        => 'groups_feeds_meetup_events.inc',
    'file path'   => drupal_get_path('module', 'groups_feeds').'/includes',
  );
  $items['meetup_groups_import'] = array(
    'description' => 'Import groups data from meetup.com (requires API key).',
    'rule'        => '0 2 * * *',
    'callback'    => 'groups_feeds_meetup_import',
    'arguments'   => array(),
    'file'        => 'groups_feeds_meetup_groups.inc',
    'file path'   => drupal_get_path('module', 'groups_feeds').'/includes',
  );
  return $items;
}

/**
 * Helper callback to clean up feedSource object.
 *
 * reset states and drupal status messages.
 */
function _groups_feeds_cleanup(&$feedSource) {
    // Clean up states.
    $feedSource->state(FEEDS_FETCH);
    $feedSource->state(FEEDS_PROCESS);
    $feedSource->state(FEEDS_PROCESS_CLEAR);

    // Clear messages from Feeds.
    drupal_get_messages('status');
}

/**
 * Join two url parts trimming the last path separator properly.
 *
 * @param  $base
 *   base url.
 * @param  $path
 *   fragment to be append.
 * @return
 *   Concated url fragments.
 */
function _groups_feeds_join_url($base, $path) {
  $url = rtrim($base, '/');
  $url .= $path;
  return $url;
}

/**
 * Implement hook_feeds_importer_default()
 *
 * Add static page importer
 */
function groups_feeds_feeds_importer_default() {
  module_load_include('inc', 'groups_feeds', 'includes/groups_feeds_meetup');
  module_load_include('inc', 'groups_feeds', 'includes/groups_feeds_meetup_events');
  module_load_include('inc', 'groups_feeds', 'includes/groups_feeds_static_pages');
  module_load_include('inc', 'groups_feeds', 'includes/groups_feeds_user_groups');
  $export = array();
  $export['staticpages'] = groups_feeds_static_pages_importer();
  $export['ical_feed_importer'] = groups_feeds_meetup_ical_importer();
  $export['user_group_feed_importer'] = groups_feeds_groups_importer();
  return $export;
}

/**
 * List of meetup.com links registered for
 * user groups.
 */
function groups_feeds_get_meetup_links() {
  $result = db_select('node', 'n')
    ->fields('n')->condition('status', 1)
    ->condition('type', 'group', '=')
    ->execute();
  $meetup_links = array();
  foreach ($result as $record) {
    $node = node_load($record->nid);
    $resource_links = isset($node->field_resource_links['und']) ?
      $node->field_resource_links['und'] : NULL;
    if (isset($resource_links)) {
      foreach ($resource_links as $resource_link) {
        $value = $resource_link['value'];
        if ((strpos($value, 'http://www.meetup.com') === 0) ||
            (strpos($value, 'https://www.meetup.com') === 0)) {
          $meetup_links[] = array(
            'nid' => $record->nid,
            'url' => $value);
        }
      }
    }
  }
  return $meetup_links;
}

/**
 * Implements hook_node_presave().
 *
 * Fix $node->title assignment failure in case of
 * page content type, and assign title field's value
 * into $node->title attribute.
 *
 * @param  class $node  node prepared to save
 */
function groups_feeds_node_presave($node) {
  if (($node->type == 'page') || ($node->type == 'event')) {
    // set title attribute of node
    $node->title = $node->title_field['und'][0]['value'];
  }
}

/**
 * Implements hook_node_insert()
 *
 * Create a menu entry for page content type
 * based on path and node title.
 *
 * @param  class $node  inserted node object
 */
function groups_feeds_node_insert($node) {
  if ($node->type == 'page') {
    // assign node menu automatically from path
    $node->menu = array(
      'link_title' => $node->title,
      'description' => '',
      'menu_name' => 'menu-content-menu',
      'plid' => 0,
      'enabled' => 1,
      'weight' => 20,
    );
  }
}

/**
 * Implements hooks_feeds_presave()
 */
function groups_feeds_feeds_presave($source, $entity, $item) {
  static $list_lookup;
  if ($list_lookup == null) {
    $list_lookup = field_property_list_reverse_lookup();
  }
  if (($entity->feeds_item->entity_type == 'node') &&
    ($entity->feeds_item->id == 'user_group_feed_importer')) {
    $location = $item['jsonpath_parser:1'];
    $entity->field_group_location[LANGUAGE_NONE][0] = $location;
    // publish imported node as a default
    $entity->status = 1;
    // update attributes
    $attributes = $item['jsonpath_parser:2'];
    if (isset($attributes)) {
      $attr = array();
      foreach ($attributes as $attribute) {
        $key = key($attribute);
        $value = $attribute[$key];
        if ($list_lookup[$key] != NULL) {
          $attr[] = array(
            'key' => $list_lookup[$key],
            'value' => $value
          );
        }
      }
      $entity->field_resource_links['und'] = $attr;
    }
    // update geolocation when lat / lng != 0
    if (($location['lat'] != 0) && ($location['lng'] != 0)) {
      geophp_load();
      $geom = new Point($location['lng'], $location['lat']);
      $geofield = geofield_get_values_from_geometry($geom);
      $geofield['geom'] = 'POINT (' . $location['lng'] . ' ' . $location['lat'] . ')';
      $entity->field_geofield = array('und'=>array($geofield));
    }
    // skip group import where groups_sync_group_<nid> is disabled. Defaults to sync.
    if (!$entity->is_new) {
      $entity->feeds_item->skip = variable_get('groups_sync_group_'.$entity->nid, TRUE) == FALSE;
    }
  }
  if (($entity->feeds_item->entity_type == 'node') &&
    ($entity->feeds_item->id == 'ical_feed_importer')) {
    // assign group node id to the event
    $config = $source->getConfig();
    if (isset($config['FeedsHTTPFetcher']['nid'])) {
      $entity->og_group_ref[LANGUAGE_NONE][0]['target_id'] = $config['FeedsHTTPFetcher']['nid'];
    }
    if ((isset($entity->field_address[LANGUAGE_NONE][0]['data'])) &&
      (!empty($entity->field_address[LANGUAGE_NONE][0]['data']))) {
      // map location data into field_address and field_venue_name
      module_load_include('inc', 'groups_feeds', 'includes/groups_feeds_meetup_events');
      $field_address = &$entity->field_address[LANGUAGE_NONE][0];
      $location_map = _parse_meetup_location($field_address['data']);
      foreach ($location_map as $k => $v) {
        switch ($k) {
          case 'country':
            $field_address['country'] = _country_code_by_name($v);
            break;
          case 'city':
            $field_address['locality'] = $v;
            break;
          case 'address':
            $field_address['thoroughfare'] = $v;
            break;
          case 'venue':
            $entity->field_venue_name[LANGUAGE_NONE][0]['value'] = $v;
            $entity->field_venue_name[LANGUAGE_NONE][0]['format'] = 'plain_text';
            break;
        }
      }
    }
  }
}

function groups_feeds_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
  foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
    $info = field_info_field($name);
    if (($info['field_name'] == 'field_group_location') || ($info['field_name'] == 'field_resource_links')) {
      $targets[$name] = array(
        'name' => check_plain($instance['label']),
        'callback'    => 'groups_feeds_set_target_entity_reference',
        'description' => t(''),
      );
    }
  }
}

function groups_feeds_set_target_entity_reference($source, $entity, $target, $value, $mapping) {
  // @todo: implement dummy callback
}

/**
 * Return the raw meetup name from a meetup.com url.
 */
function _groups_feeds_get_meetup_name($url) {
  return basename(rtrim($url, '/'));
}

/**
 * Invoke a http request with rate limiting
 */
function _groups_feeds_rlimit_request($url, &$wait) {
  sleep($wait);
  $response = drupal_http_request($url);
  $ratelimit_reset = $response->headers['x-ratelimit-reset'];
  $wait = 6; // wait 6 sec between requests;
  return $response;
}

/**
 * Implements hook_meetup_group_import()
 *
 * Map meetup.members to group node.
 */
function groups_feeds_meetup_group_import(&$group_node, $item) {
  // import meetup members
  $group_node->field_meetup_members[LANGUAGE_NONE][0]['value'] = $item->members;
  node_save($group_node);
}
