<?php

/**
 * @file getlocations.module
 * @author Bob Hutchinson http://drupal.org/user/52366
 * @copyright GNU GPL
 *
 * Displays locations on a map.
 * for Drupal 7
 * using version 3 googlemaps API
 */

define('GETLOCATIONS_PATH', drupal_get_path('module', 'getlocations'));
define('GETLOCATIONS_ADMIN_PATH', 'admin/config/services/getlocations');
define('GETLOCATIONS_VERSION', '7.x-1.x');

/**
 * Implements hook_help().
 */
function getlocations_help($path, $arg) {
  switch ($path) {
    case 'admin/help#getlocations':
      $output = '<p>' . t('Displays locations on a map.') . '</p>';
      return $output;
  }
}

/**
 * Implements hook_init().
 */
function getlocations_init() {

  if (module_exists('colorbox')) {
    $getlocations_colorbox = getlocations_colorbox_settings();
    $settings = array('getlocations_colorbox' => $getlocations_colorbox);
    drupal_add_js($settings, 'setting');
    $getlocations_paths = getlocations_paths_get();
    drupal_add_js($getlocations_paths['getlocations_colorbox_path']);
  }

}

/**
 * Implements hook_permission().
 */
function getlocations_permission() {
  $perms = array();
  $perms['access getlocations'] = array(
    'title' => t('Access Getlocations'),
    'description' => t('View and use the Getlocations module.')
  );
  $perms['access user getlocations'] = array(
    'title' => t('Access User locations'),
    'description' => t('View User locations with Getlocation maps.')
  );
  return $perms;
}

/**
 * Implements hook_flush_caches().
 */
function getlocations_flush_caches() {
  if (variable_get('getlocations_flush', 1)) {
    getlocations_regenerate_markers();
  }
}

/**
 * Implements hook_views_api().
 */
function getlocations_views_api() {
  return array(
    'api' => 3,
    'path' => GETLOCATIONS_PATH . '/views',
  );
}

/**
 * Implements hook_menu().
 */
function getlocations_menu() {
  $items = array();

  $items[GETLOCATIONS_ADMIN_PATH] = array(
    'title' => 'Getlocations',
    'description' => 'Configure Getlocations',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('getlocations_settings_form'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'getlocations.admin.inc',
  );

  $items[GETLOCATIONS_ADMIN_PATH . '/base'] = array(
    'title' => 'Base',
    'description' => 'Getlocations base configuration',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('getlocations_settings_form'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'file' => 'getlocations.admin.inc',
    'weight' => 1,
  );

  // getlocations/node/$nid    # show all location on one node
  $items['getlocations/node/%getlocations_id'] = array(
    'title' => 'Get locations',
    'access callback' => 'getlocations_access_location',
    'page callback' => 'getlocations_nodemap',
    'page arguments' => array(2),
    'type' => MENU_CALLBACK,
  );

  if (getlocations_check_entity_type('user') || getlocations_check_entity_type('profile2')) {
    // getlocations/user/$uid    # show all locations for a user
    $items['getlocations/user/%getlocations_id'] = array(
      'title' => 'Get user locations',
      'access callback' => 'getlocations_access_user_location',
      'page callback' => 'getlocations_usermap',
      'page arguments' => array(2),
      'type' => MENU_CALLBACK,
    );
    // getlocations/users    # show all locations for all users
    $items['getlocations/users'] = array(
      'title' => 'View all user locations',
      'access callback' => 'getlocations_access_user_location',
      'page callback' => 'getlocations_usersmap',
      'type' => MENU_CALLBACK,
    );
  }
  if (module_exists('taxonomy')) {
    // getlocations/term/$tid    # show all locations for a term
    $items['getlocations/term/%getlocations_id'] = array(
      'title' => 'Get term locations',
      'access callback' => 'getlocations_access_location',
      'page callback' => 'getlocations_termmap',
      'page arguments' => array(2),
      'type' => MENU_CALLBACK,
    );
  }
  if (module_exists('comment')) {
    if (getlocations_check_entity_type('comment')) {
      // getlocations/comment/$cid    # show all locations for a comment
      $items['getlocations/comment/%getlocations_id'] = array(
        'title' => 'Get comment locations',
        'access callback' => 'getlocations_access_location',
        'page callback' => 'getlocations_commentmap',
        'page arguments' => array(2),
        'type' => MENU_CALLBACK,
      );
    }
  }

  // getlocations/type/$type     # show all locations of nodes of content-type machine name
  $items['getlocations/type/%getlocations_type'] = array(
    'title' => 'Get locations',
    'access callback' => 'getlocations_access_location',
    'page callback' => 'getlocations_typemap',
    'page arguments' => array(2, 3, 4),
    'type' => MENU_CALLBACK,
  );

  // getlocations/lids/1,2,3,4    # show lids
  $items['getlocations/lids/%getlocations_cdints'] = array(
    'title' => 'Get locations',
    'access callback' => 'getlocations_access_location',
    'page callback' => 'getlocations_lids',
    'page arguments' => array(2),
    'type' => MENU_CALLBACK,
  );

  // getlocations/nids/1,2,3,4    # show nids locations
  $items['getlocations/nids/%getlocations_cdints'] = array(
    'title' => 'Get locations',
    'access callback' => 'getlocations_access_location',
    'page callback' => 'getlocations_nids',
    'page arguments' => array(2),
    'type' => MENU_CALLBACK,
  );

  // ajax callbacks
  // getlocations/info?lid     # ajax callback to fetch an address
  $items['getlocations_cb/info'] = array(
    'page callback' => 'getlocations_adinfo',
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );
  // getlocations/lidinfo?lid    # ajax callback to fetch a link to the 'owner'
  $items['getlocations_cb/lidinfo'] = array(
    'page callback' => 'getlocations_lidinfo',
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );

  $items['getlocations_box'] = array(
    'title' => 'Get locations',
    'access arguments' => array('access getlocations'),
    'page callback' => 'getlocations_box',
    'type' => MENU_CALLBACK,
  );
  $items['getlocations/markerinfo'] = array(
    'access callback' => TRUE,
    'page callback' => 'getlocations_markerinfo',
    'type' => MENU_CALLBACK,
  );

  return $items;
}

/**
 * check that the argument is numeric
 *
 * @param int $arg
 *
 * @return argument or FALSE
 */
function getlocations_id_load($arg) {
  return (is_numeric($arg) && $arg > 0 ? $arg : FALSE);
}

/**
 * Check that the node type exists
 *
 * @param string $arg Node type.
 *
 * @return argument or FALSE
 */
function getlocations_type_load($arg) {
  $query = db_select('node_type', 'n')->fields('n', array('type'))->condition('n.type', $arg);
  $row = $query->execute()->fetchAssoc();
  return ((isset($row['type']) && $row['type']) ? $arg : FALSE);
}

/**
 * sanity check on list of nids
 *
 * @param int $arg
 *
 * @return argument or FALSE
 *
 */
function getlocations_cdints_load($arg) {
  $arr = explode(',', $arg);
  foreach ($arr AS $a) {
    if (! is_numeric($a) || $a < 1 ) {
      return FALSE;
    }
  }
  return $arg;
}

/**
 * sanity check on entity type
 *
 * @param string $arg Entity type.
 *
 * @return argument or FALSE
 *
 */
function getlocations_entity_type_load($arg) {
  if (getlocations_check_entity_type($arg)) {
    return $arg;
  }
  return FALSE;
}

/**
 * Access callback: Checks for access permission and if there is a supported locative module installed
 *
 * @return bool
 *
 */
function getlocations_access_location() {
  if (user_access('access getlocations')) {
    $modules = getlocations_supported_modules();
    foreach ($modules AS $module) {
      if (module_exists($module)) {
        return TRUE;
      }
    }
  }
  return FALSE;
}

/**
 * Access callback: Checks for access permission and if there is a supported locative module installed
 *
 * @return bool
 *
 */
function getlocations_access_user_location() {
  if (user_access('access user getlocations') && user_access('access user profiles')) {
    $modules = getlocations_supported_modules();
    foreach ($modules AS $module) {
      if (module_exists($module)) {
        return TRUE;
      }
    }
  }
  return FALSE;
}

/**
 * Page callback: displays a map.
 *
 * @param int $nid
 *
 * @return
 *   Returns a map of locations of a node
 *
 */
function getlocations_nodemap($nid) {

  $vid = getlocations_get_vid($nid);
  $locations = getlocations_load_locations($vid);
  $node = node_load($nid);

  $getlocations_defaults = getlocations_defaults();
  $marker = $getlocations_defaults['node_map_marker'];
  $typemarkers = getlocations_get_markertypes('node');
  if (isset($typemarkers[$node->type]) && $typemarkers[$node->type]) {
    $marker = $typemarkers[$node->type];
  }
  $latlons = array();
  $minmaxes = array('minlat' => 0, 'minlon' => 0, 'maxlat' => 0, 'maxlon' => 0);
  $ct = 0;
  $extra_info = array();
  $sv_info = FALSE;
  $map_info = FALSE;
  $module = getlocations_get_current_supported_module();

  if (count($locations)) {
    // we should loop over them and dump bummers with no lat/lon
    foreach ($locations AS $key => $location) {
      if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
        $ll = explode(',', $latlon);
        $location['latitude'] = $ll[0];
        $location['longitude'] = $ll[1];
        $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
        if (! isset($location['key'])) {
          $location['key'] = '';
        }
        else {
          if ($location['key'] == 'nid') {
            $location['lid'] = $nid;
          }
          elseif ($location['key'] == 'vid') {
            $location['lid'] = $nid;
          }
        }

        // term markers
        $marker = getlocations_get_term_marker($nid, $marker);

        // per location marker
        if (isset($location['marker']) && ! empty($location['marker'])) {
          $marker = $location['marker'];
        }
        $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($node->title), ENT_QUOTES);
        $latlons[$ct] = array($location['latitude'], $location['longitude'], $location['lid'], $name, $marker, $location['key'], '', '');

        $sv_info = FALSE;
        if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
            $sv_info = getlocations_fields_svinfo($location);
          }
          if (getlocations_fields_map_settings_allow()) {
            $map_info = getlocations_fields_mapinfo($location);
          }
        }

        $ct++;
      }
    }
  }
  if ($ct < 2 ) {
    unset($minmaxes);
    $minmaxes = '';
  }

  drupal_set_title(t('View !t locations', array('!t' => $node->title)));

  if ($sv_info) {
    $extra_info = array_merge($extra_info, $sv_info);
  }
  if ($map_info) {
    $extra_info = array_merge($extra_info, $map_info);
  }

  return getlocations_setlocations($latlons, $minmaxes, 'node', $node, $extra_info);

}

/**
 * Page callback: Displays a map.
 *
 * @param int $uid
 *
 * @return
 *   Returns a map of locations of a user
 *
 */
function getlocations_usermap($uid) {

  $getlocations_defaults = getlocations_defaults();

  $marker = $getlocations_defaults['user_map_marker'];
  $locations = getlocations_load_locations($uid, 'uid');
  $account = user_load($uid);
  $latlons = array();
  $minmaxes = array('minlat' => 0, 'minlon' => 0, 'maxlat' => 0, 'maxlon' => 0);
  $ct = 0;
  $extra_info = array();
  $sv_info = FALSE;
  $map_info = FALSE;
  $module = getlocations_get_current_supported_module();

  if (count($locations)) {
    // we should loop over them and dump bummers with no lat/lon
    foreach ($locations AS $key => $location) {
      if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
        $ll = explode(',', $latlon);
        $location['latitude'] = $ll[0];
        $location['longitude'] = $ll[1];
        $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
        if (! isset($location['key'])) {
          $location['key'] = '';
        }
        else {
          $location['lid'] = $uid;
        }
        // per location marker
        if (isset($location['marker']) && ! empty($location['marker'])) {
          $marker = $location['marker'];
        }
        $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($account->name), ENT_QUOTES);
        $latlons[$ct] = array($location['latitude'], $location['longitude'], $location['lid'], $name, $marker, $location['key'], '', '');

        $sv_info = FALSE;
        if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
            $sv_info = getlocations_fields_svinfo($location);
          }
          if (getlocations_fields_map_settings_allow()) {
            $map_info = getlocations_fields_mapinfo($location);
          }
        }

        $ct++;
      }
    }
  }
  if ($ct < 2 ) {
    unset($minmaxes);
    $minmaxes = '';
  }

  drupal_set_title(t('View user !t locations', array('!t' => $account->name)));

  if ($sv_info) {
    $extra_info = array_merge($extra_info, $sv_info);
  }
  if ($map_info) {
    $extra_info = array_merge($extra_info, $map_info);
  }

  return getlocations_setlocations($latlons, $minmaxes, 'user', $account, $extra_info);

}

/**
 * Page callback: Displays a map.
 *
 * @return
 *   Returns a map of locations of all the users
 *
 */
function getlocations_usersmap() {

  $getlocations_defaults = getlocations_defaults();
  $marker = $getlocations_defaults['user_map_marker'];
  $latlons = array();
  $minmaxes = array('minlat' => 0, 'minlon' => 0, 'maxlat' => 0, 'maxlon' => 0);
  $query = db_select('users', 'u')->fields('u', array('uid', 'name'))->condition('u.status', 1);
  $rows = $query->execute();
  $ct = 0;
  foreach ($rows AS $row) {
    $uid = $row->uid;
    $locations = getlocations_load_locations($uid, 'uid');
    if (count($locations)) {
      // we should loop over them and dump bummers with no lat/lon
      foreach ($locations AS $key => $location) {
        if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
          $ll = explode(',', $latlon);
          $location['latitude'] = $ll[0];
          $location['longitude'] = $ll[1];
          $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
          if (! isset($location['key'])) {
            $location['key'] = '';
          }
          else {
            $location['lid'] = $uid;
          }
          // per location marker
          if (isset($location['marker']) && ! empty($location['marker'])) {
            $marker = $location['marker'];
          }
          $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($row->name), ENT_QUOTES);
          $latlons[$ct] = array($location['latitude'], $location['longitude'], $location['lid'], $name, $marker, $location['key'], '', '');
          $ct++;
        }
      }
    }
  }

  if ($ct < 2 ) {
    unset($minmaxes);
    $minmaxes = '';
  }
  return getlocations_setlocations($latlons, $minmaxes, 'users');

}

/**
 * Page callback: Displays a map.
 *
 * @param int $tid
 *
 * @return
 *   Returns a map of locations of a term
 *
 */
function getlocations_termmap($tid) {
  if (module_exists('taxonomy')) {
    $locations = getlocations_load_locations($tid, 'tid');
    $term = taxonomy_term_load($tid);
    $getlocations_defaults = getlocations_defaults();
    $marker = $getlocations_defaults['vocabulary_map_marker'];
    $typemarkers = getlocations_get_markertypes('vocabulary');
    if (isset($typemarkers[$term->vid]) && $typemarkers[$term->vid]) {
      $marker = $typemarkers[$term->vid];
    }
    $latlons = array();
    $minmaxes = array('minlat' => 0, 'minlon' => 0, 'maxlat' => 0, 'maxlon' => 0);
    $ct = 0;
    $extra_info = array();
    $sv_info = FALSE;
    $map_info = FALSE;
    $module = getlocations_get_current_supported_module();

    if (count($locations)) {
      // we should loop over them and dump bummers with no lat/lon
      foreach ($locations AS $key => $location) {
        if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
          $ll = explode(',', $latlon);
          $location['latitude'] = $ll[0];
          $location['longitude'] = $ll[1];
          $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
          if (! isset($location['key'])) {
            $location['key'] = '';
          }
          else {
            $location['lid'] = $tid;
          }
          // per location marker
          if (isset($location['marker']) && ! empty($location['marker'])) {
            $marker = $location['marker'];
          }
          $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($term->name), ENT_QUOTES);
          $latlons[$ct] = array($location['latitude'], $location['longitude'], $location['lid'], $name, $marker, $location['key'], '', '');

          $sv_info = FALSE;
          if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
              $sv_info = getlocations_fields_svinfo($location);
            }
            if (getlocations_fields_map_settings_allow()) {
              $map_info = getlocations_fields_mapinfo($location);
            }
          }

          $ct++;
        }
      }
    }
    if ($ct < 2 ) {
      unset($minmaxes);
      $minmaxes = '';
    }

    drupal_set_title(t('View term !t locations', array('!t' => $term->name)));

    if ($sv_info) {
      $extra_info = array_merge($extra_info, $sv_info);
    }
    if ($map_info) {
      $extra_info = array_merge($extra_info, $map_info);
    }

    return getlocations_setlocations($latlons, $minmaxes, 'term', $term, $extra_info);

  }
}

/**
 * Page callback: Displays a map.
 *
 * @param int $cid
 *
 * @return
 *   Returns a map of locations of a comment
 *
 */
function getlocations_commentmap($cid) {
  if (module_exists('comment')) {
    $locations = getlocations_load_locations($cid, 'cid');
    $comment = comment_load($cid);
    $getlocations_defaults = getlocations_defaults();
    $marker = $getlocations_defaults['comment_map_marker'];
    $latlons = array();
    $minmaxes = array('minlat' => 0, 'minlon' => 0, 'maxlat' => 0, 'maxlon' => 0);
    $ct = 0;
    $extra_info = array();
    $sv_info = FALSE;
    $map_info = FALSE;
    $module = getlocations_get_current_supported_module();

    if (count($locations)) {
      // we should loop over them and dump bummers with no lat/lon
      foreach ($locations AS $key => $location) {
        if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
          $ll = explode(',', $latlon);
          $location['latitude'] = $ll[0];
          $location['longitude'] = $ll[1];
          $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
          if (! isset($location['key'])) {
            $location['key'] = '';
          }
          else {
            $location['lid'] = $cid;
          }
          // per location marker
          if (isset($location['marker']) && ! empty($location['marker'])) {
            $marker = $location['marker'];
          }
          $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($comment->subject), ENT_QUOTES);
          $latlons[$ct] = array($location['latitude'], $location['longitude'], $location['lid'], $name, $marker, $location['key'], '', '');

          $sv_info = FALSE;
          if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
              $sv_info = getlocations_fields_svinfo($location);
            }
            if (getlocations_fields_map_settings_allow()) {
              $map_info = getlocations_fields_mapinfo($location);
            }
          }

          $ct++;
        }
      }
    }
    if ($ct < 2 ) {
      unset($minmaxes);
      $minmaxes = '';
    }

    drupal_set_title(t('View comment !t locations', array('!t' => $comment->subject)));

    if ($sv_info) {
      $extra_info = array_merge($extra_info, $sv_info);
    }
    if ($map_info) {
      $extra_info = array_merge($extra_info, $map_info);
    }

    return getlocations_setlocations($latlons, $minmaxes, 'comment', $comment, $extra_info);

  }
}

/**
 * Page callback: Displays a map.
 *
 * @param string $type
 * A location enabled content type
 *
 * @return
 *   Returns a map of locations of all nodes of content-type $type
 *
 */
function getlocations_typemap($type, $loc_key='', $loc_val = '') {
  $getlocations_defaults = getlocations_defaults();
  $marker = $getlocations_defaults['node_map_marker'];
  $typemarkers = getlocations_get_markertypes('node');
  if (isset($typemarkers[$type]) && $typemarkers[$type]) {
    $marker = $typemarkers[$type];
  }

  $latlons = array();
  $minmaxes = array('minlat' => 0, 'minlon' => 0, 'maxlat' => 0, 'maxlon' => 0);
  $query = db_select('node', 'n')->fields('n', array('nid', 'title'))->condition('n.type', $type);
  $rows = $query->execute();
  $ct = 0;
  $extra_info = array();
  $sv_info = FALSE;
  $map_info = FALSE;
  $module = getlocations_get_current_supported_module();

  foreach ($rows AS $row) {
    $nid = $row->nid;
    $vid = getlocations_get_vid($nid);
    $locations = getlocations_load_locations($vid);
    if (count($locations)) {
      // we should loop over them and dump bummers with no lat/lon
      foreach ($locations AS $key => $location) {
        if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
          $ll = explode(',', $latlon);
          $location['latitude'] = $ll[0];
          $location['longitude'] = $ll[1];
          if ($loc_key && isset($location[$loc_key])) {
            if (drupal_strtolower($location[$loc_key]) != drupal_strtolower($loc_val)) {
              continue;
            }
          }
          $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
          if (! isset($location['key'])) {
            $location['key'] = '';
          }
          else {
            if ($location['key'] == 'nid') {
              $location['lid'] = $nid;
            }
            elseif ($location['key'] == 'vid') {
              $location['lid'] = $vid;
            }
          }

          // term markers
          $marker = getlocations_get_term_marker($nid, $marker);

          // per location marker
          if (isset($location['marker']) && ! empty($location['marker'])) {
            $marker = $location['marker'];
          }
          $name = htmlspecialchars_decode(isset($location['name']) ? strip_tags($location['name']) : strip_tags($row->title), ENT_QUOTES);
          $latlons[$ct] = array($location['latitude'], $location['longitude'], $location['lid'], $name, $marker, $location['key'], '', '');

          $sv_info = FALSE;
          if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
              $sv_info = getlocations_fields_svinfo($location);
            }
            if (getlocations_fields_map_settings_allow()) {
              $map_info = getlocations_fields_mapinfo($location);
            }
          }

          $ct++;
        }
      }
    }
  }
  if ($ct < 2 ) {
    unset($minmaxes);
    $minmaxes = '';
  }

  if ($sv_info) {
    $extra_info = array_merge($extra_info, $sv_info);
  }
  if ($map_info) {
    $extra_info = array_merge($extra_info, $map_info);
  }

  return getlocations_setlocations($latlons, $minmaxes, $type, '', $extra_info);
}

/**
 * Page callback: Displays a map.
 *
 * @param string $lidlist
 * A comma-delimited list of location ids
 *
 * @return
 *   Returns a map of locations.
 *
 */
function getlocations_lids($lidlist) {
  $lidarr = explode(',', $lidlist);
  $locations = array();
  $latlons = array();
  $minmaxes = array('minlat' => 0, 'minlon' => 0, 'maxlat' => 0, 'maxlon' => 0);
  $marker = '';
  $ct = 0;
  $extra_info = array();
  $sv_info = FALSE;
  $map_info = FALSE;
  $module = getlocations_get_current_supported_module();

  foreach ($lidarr AS $lid) {
    $locations[] = getlocations_load_location($lid);
  }
  if (count($locations)) {
    // we should loop over them and dump bummers with no lat/lon
    foreach ($locations AS $key => $location) {
      if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
        $ll = explode(',', $latlon);
        $location['latitude'] = $ll[0];
        $location['longitude'] = $ll[1];
        $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
        $location['key'] = '';
        $name = htmlspecialchars_decode(strip_tags($location['name']), ENT_QUOTES);
        $latlons[$ct] = array($location['latitude'], $location['longitude'], $location['lid'], $name, $location['marker'], $location['key'], '', '');

        $sv_info = FALSE;
        if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
            $sv_info = getlocations_fields_svinfo($location);
          }
          if (getlocations_fields_map_settings_allow()) {
            $map_info = getlocations_fields_mapinfo($location);
          }
        }

        $ct++;
      }
    }
  }
  if ($ct < 2 ) {
    unset($minmaxes);
    $minmaxes = '';
  }

  if ($sv_info) {
    $extra_info = array_merge($extra_info, $sv_info);
  }
  if ($map_info) {
    $extra_info = array_merge($extra_info, $map_info);
  }

  return getlocations_setlocations($latlons, $minmaxes, 'lids', '', $extra_info);

}

/**
 * Page callback: Displays a map.
 *
 * @param string $nidlist
 * A comma-delimited list of node ids
 *
 * @return
 *   Returns a map of locations.
 *
 */
function getlocations_nids($nidlist) {
  $nidarr = explode(',', $nidlist);
  $locations = array();
  $latlons = array();
  $minmaxes = array('minlat' => 0, 'minlon' => 0, 'maxlat' => 0, 'maxlon' => 0);
  $typemarkers = getlocations_get_markertypes('node');
  $ct = 0;
  $extra_info = array();
  $sv_info = FALSE;
  $map_info = FALSE;
  $module = getlocations_get_current_supported_module();

  foreach ($nidarr AS $nid) {
    $vid = getlocations_get_vid($nid);
    $locs = getlocations_load_locations($vid);
    if (count($locs)) {
      foreach ($locs AS $key => $loc) {
        $type = getlocations_get_nodetype($nid);
        if (isset($typemarkers[$type])) {
           $loc['marker'] = $typemarkers[$type];
        }
        $locations[] = $loc;
      }
    }
  }
  if (count($locations)) {
    // we should loop over them and dump bummers with no lat/lon
    foreach ($locations AS $key => $location) {
      if ($latlon = getlocations_latlon_check($location['latitude'] . ',' . $location['longitude'])) {
        $ll = explode(',', $latlon);
        $location['latitude'] = $ll[0];
        $location['longitude'] = $ll[1];
        $minmaxes = getlocations_do_minmaxes($ct, $location, $minmaxes);
        if (! isset($location['key'])) {
          $location['key'] = '';
        }
        else {
          if ($location['key'] == 'nid') {
            $location['lid'] = $nid;
          }
          elseif ($location['key'] == 'vid') {
            $location['lid'] = $vid;
          }
        }
        $name = htmlspecialchars_decode(strip_tags($location['name']), ENT_QUOTES);
        $latlons[$ct] = array($location['latitude'], $location['longitude'], $location['lid'], $name, $location['marker'], $location['key'], '', '');

        $sv_info = FALSE;
        if ($module == 'getlocations_fields' && count($locations) == 1) {
          if (getlocations_fields_streetview_settings_allow()) {
            $sv_info = getlocations_fields_svinfo($location);
          }
          if (getlocations_fields_map_settings_allow()) {
            $map_info = getlocations_fields_mapinfo($location);
          }
        }

        $ct++;
      }
    }
  }
  if ($ct < 2 ) {
    unset($minmaxes);
    $minmaxes = '';
  }

  if ($sv_info) {
    $extra_info = array_merge($extra_info, $sv_info);
  }
  if ($map_info) {
    $extra_info = array_merge($extra_info, $map_info);
  }

  return getlocations_setlocations($latlons, $minmaxes, 'nids', '', $extra_info);
}

/**
 * Set up javascript settings and map
 *
 * @param array $latlons
 * @param array $minmaxes
 * @param string $type
 * @param object $node
 * @param string $width
 * @param string $height
 *
 * @return string themed map html
 */
function getlocations_setlocations($latlons, $minmaxes='', $type='node', $node = '', $extras = '', $width='', $height='') {
  if (! getlocations_defaults_check()) {
    return t('You need to !c first.', array('!c' => l('Configure Getlocations', 'admin/config/services/getlocations')));
  }

  $getlocations_defaults = getlocations_defaults();
  $module = getlocations_get_current_supported_module();

  // sv
  if ($extras) {
    if ($module == 'getlocations_fields') {
      if (getlocations_fields_streetview_settings_allow()) {
        $getlocations_defaults['sv_heading']   = $extras['sv_heading'];
        $getlocations_defaults['sv_zoom']      = $extras['sv_zoom'];
        $getlocations_defaults['sv_pitch']     = $extras['sv_pitch'];
        $getlocations_defaults['sv_showfirst'] = $extras['sv_showfirst'];
        $getlocations_defaults['sv_addresscontrol']         = $extras['sv_addresscontrol'];
        $getlocations_defaults['sv_addresscontrolposition'] = $extras['sv_addresscontrolposition'];
        $getlocations_defaults['sv_pancontrol']             = $extras['sv_pancontrol'];
        $getlocations_defaults['sv_pancontrolposition']     = $extras['sv_pancontrolposition'];
        $getlocations_defaults['sv_zoomcontrol']            = $extras['sv_zoomcontrol'];
        $getlocations_defaults['sv_zoomcontrolposition']    = $extras['sv_zoomcontrolposition'];
        $getlocations_defaults['sv_linkscontrol']           = $extras['sv_linkscontrol'];
        $getlocations_defaults['sv_imagedatecontrol']       = $extras['sv_imagedatecontrol'];
        $getlocations_defaults['sv_scrollwheel']            = $extras['sv_scrollwheel'];
        $getlocations_defaults['sv_clicktogo']              = $extras['sv_clicktogo'];
      }
      if (getlocations_fields_map_settings_allow()) {
        $getlocations_defaults['nodezoom']     = $extras['mapzoom'];
        $getlocations_defaults['maptype']      = $extras['map_maptype'];
        // update baselayers
        $getlocations_defaults['baselayers'][$extras['map_maptype']] = 1;
      }
    }
  }

  $mapid = getlocations_setup_map($getlocations_defaults);
  getlocations_js_settings_do($getlocations_defaults, $latlons, $minmaxes, $mapid);

  if (empty($width)) {
    $width = $getlocations_defaults['width'];
  }
  if (empty($height)) {
    $height = $getlocations_defaults['height'];
  }

  return theme('getlocations_show', array('width' => $width, 'height' => $height, 'defaults' => $getlocations_defaults, 'mapid' => $mapid, 'latlons' => $latlons, 'minmaxes' => $minmaxes, 'type' => $type, 'node' => $node));

}

/**
 * Function to setup the map scripts
 *
 * @param array $defaults
 *   Required. the current settings.
 * Sets up the call to googlemaps, css and the relevant getlocations js in html head
 */
function getlocations_setup_map($defaults, $googleonly = FALSE, $sv = FALSE, $keyonly = FALSE) {
  static $getlocations_mapid = 0;
  // Generate unique Map ID.
  $getlocations_mapid++;
  $mapid = 'key_' . $getlocations_mapid;
  if (! $keyonly) {
    getlocations_setup_js($defaults, $googleonly, $sv);
  }
  return $mapid;
}

/**
 * Function to setup the map scripts
 *
 * @param array $defaults
 *   Required. the current settings.
 * Sets up the call to googlemaps, css and the relevant getlocations js in html head
 */
function getlocations_setup_js($defaults, $googleonly = FALSE, $sv = FALSE) {
  global $language;

  $current_js = drupal_get_js();
  $current_css = drupal_get_css();

  static $getlocations_js_weight = 0;
  $getlocations_js_weight++;
  if (is_numeric($defaults['getlocations_js_weight']) && $defaults['getlocations_js_weight'] != 0) {
    $getlocations_js_weight += $defaults['getlocations_js_weight'];
  }

  $key = variable_get('getlocations_api3_key', '');

  $aggr = (getlocations_aggr_get() ? TRUE : FALSE);

  // v3 googlemaps API
  $query = array();
  if (! empty($key)) {
    $query['key'] = $key;
  }
  $query['sensor'] = (getlocations_is_mobile() ? 'true' : 'false');

  if (isset($language->language)) {
    $query['language'] = $language->language;
  }

  if ($defaults['region_bias']) {
    $query['region'] = $defaults['region_bias'];
  }

  $libraries = array();
  if ($defaults['panoramio_use']) {
    $libraries['panoramio'] = 'panoramio';
  }
  if ($defaults['places'] || module_exists('getlocations_search')) {
    $libraries['places'] = 'places';
  }
  if ($defaults['weather_use']) {
    $libraries['weather'] = 'weather';
  }

  // not active but can be used by other modules
  if ($defaults['geometry']) {
    $libraries['geometry'] = 'geometry';
  }
  if ($defaults['visualization']) {
    $libraries['visualization'] = 'visualization';
  }
  if ($defaults['drawing']) {
    $libraries['drawing'] = 'drawing';
  }
  if ($defaults['adsense']) {
    $libraries['adsense'] = 'adsense';
  }

  // more libraries here

  // compat with getdirections
  if ($defaults['getdirections_enabled']) {
    $getdirections_misc_defaults = getdirections_misc_defaults();
    if (isset($getdirections_misc_defaults['panoramio_use']) && $getdirections_misc_defaults['panoramio_use']) {
      $libraries['panoramio'] = 'panoramio';
    }
    if (isset($getdirections_misc_defaults['weather_use']) && $getdirections_misc_defaults['weather_use']) {
      $libraries['weather'] = 'weather';
    }
  }

  // check for places library
  if (getlocations_places_check()) {
    $libraries['places'] = 'places';
  }

  // load libraries if any
  if (count($libraries)) {
    $query['libraries'] = implode(',', $libraries);
  }

  global $is_https;
  $scheme = ($is_https ? 'https' : 'http');
  $gmapdomain = "maps.googleapis.com/maps/api/js";
  $gmaplink = url($scheme . '://' . $gmapdomain, array('query' => $query));
  if (!stristr($current_js, $scheme . '://' . $gmapdomain)) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'external';
    drupal_add_js($gmaplink, $js_opts);
    $getlocations_js_weight++;
  }
  if ($defaults['use_jsapi']) {
    $jsapilink =  url($scheme . '://' . 'www.google.com/jsapi');
    if (!stristr($current_js, $jsapilink)) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'external';
      drupal_add_js($jsapilink, $js_opts);
      $getlocations_js_weight++;
    }
  }

  if ($googleonly) {
    return;
  }

  $getlocations_paths = getlocations_paths_get();

  if (!stristr($current_css, GETLOCATIONS_PATH . '/getlocations.css')) {
    drupal_add_css(GETLOCATIONS_PATH . '/getlocations.css');
  }

  // streetview only
  if ($sv && module_exists('getlocations_fields')) {
    $getlocations_fields_paths = getlocations_fields_paths_get();
    if (!stristr($current_js, $getlocations_fields_paths['getlocations_fields_streetview_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_fields_paths['getlocations_fields_streetview_path'], $js_opts);
      $getlocations_js_weight++;
    }
    return;
  }

  if (!stristr($current_js, $getlocations_paths['getlocations_icons_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['getlocations_icons_path'], $js_opts);
    $getlocations_js_weight++;
  }

  $markerfile = getlocations_get_markerfile();
  if ($markerfile && !stristr($current_js, $markerfile)) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($markerfile, $js_opts);
    $getlocations_js_weight++;
  }

  if ($defaults['markermanagertype'] == 1 && !stristr($current_js, $getlocations_paths['markermanager_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['markermanager_path'], $js_opts);
    $getlocations_js_weight++;
  }
  elseif ($defaults['markermanagertype'] == 2 && !stristr($current_js, $getlocations_paths['markerclusterer_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['markerclusterer_path'], $js_opts);
    $getlocations_js_weight++;

    if (file_exists(GETLOCATIONS_PATH . '/getlocations.markercluster_override.inc')) {
      module_load_include('inc', 'getlocations', 'getlocations.markercluster_override');
    }
    else {
      module_load_include('inc', 'getlocations', 'getlocations.markercluster');
    }
    $markerclusterer_styles = getlocations_get_markerclusterer_styles();
    $js_opts = array();
    $js_opts['type'] = 'setting';
    drupal_add_js(array('getlocations_markerclusterer' => $markerclusterer_styles), $js_opts);

  }

  if ($defaults['markeraction'] == 2 && !stristr($current_js, $getlocations_paths['infobubble_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['infobubble_path'], $js_opts);
    $getlocations_js_weight++;

    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['infobubble_extended_path'], $js_opts);
    $getlocations_js_weight++;

    if (file_exists($getlocations_paths['infobubble_options_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['infobubble_options_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }
  elseif ($defaults['markeraction'] == 1 && file_exists($getlocations_paths['infowindow_options_path']) && !stristr($current_js, $getlocations_paths['infowindow_options_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['infowindow_options_path'], $js_opts);
    $getlocations_js_weight++;
  }

  // load main getlocations.js
  if (!stristr($current_js, $getlocations_paths['getlocations_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['getlocations_path'], $js_opts);
    $getlocations_js_weight++;
  }

  if ($defaults['polygons_enable']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_polygons_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_polygons_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }
  if ($defaults['rectangles_enable']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_rectangles_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_rectangles_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }
  if ($defaults['circles_enable']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_circles_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_circles_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }
  if ($defaults['polylines_enable']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_polylines_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_polylines_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }
  // search_places
  if ($defaults['search_places']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_search_places_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_search_places_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }

  // categories
  if ($defaults['category_method'] && $defaults['category_showhide_buttons']) {
    if (!stristr($current_js, $getlocations_paths['getlocations_categories_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_categories_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }

  // preview map
  if ($defaults['extcontrol'] == 'preview_map') {
    if (!stristr($current_js, $getlocations_paths['getlocations_preview_path'])) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($getlocations_paths['getlocations_preview_path'], $js_opts);
      $getlocations_js_weight++;
    }
  }

  // geojson
  if ($defaults['geojson_enable'] && $geojson_path = getlocations_get_geojson_path()) {
    if (!stristr($current_js, $geojson_path)) {
      $js_opts = array();
      $js_opts['weight'] = $getlocations_js_weight;
      $js_opts['type'] = 'file';
      $js_opts['preprocess'] = $aggr;
      drupal_add_js($geojson_path, $js_opts);
      $getlocations_js_weight++;
    }
    if ($defaults['geojson_data']) {
      if (!stristr($current_js, $getlocations_paths['getlocations_geojson_path'])) {
        $js_opts = array();
        $js_opts['weight'] = $getlocations_js_weight;
        $js_opts['type'] = 'file';
        $js_opts['preprocess'] = $aggr;
        drupal_add_js($getlocations_paths['getlocations_geojson_path'], $js_opts);
        $getlocations_js_weight++;
      }
    }
  }

  if ($defaults['geo_enable'] && !stristr($current_js, $getlocations_paths['getlocations_geo_path'])) {
    $js_opts = array();
    $js_opts['weight'] = $getlocations_js_weight + 10;
    $js_opts['type'] = 'file';
    $js_opts['preprocess'] = $aggr;
    drupal_add_js($getlocations_paths['getlocations_geo_path'], $js_opts);
    $getlocations_js_weight++;
  }

}

/**
 * Some defaults.
 *
 * @return
 *   Returns the current settings
 */
function getlocations_defaults($reset = FALSE) {
  $module = getlocations_get_current_supported_module();
  $defaults = array(
    'api_version'                   => 3,
    'width'                         => '300px',
    'height'                        => '200px',
    'zoom'                          => 3,
    'minzoom_map'                   => -1,
    'maxzoom_map'                   => -1,
    'controltype'                   => 'small',
    'zoomcontrolposition'           => '',
    'pancontrol'                    => 1,
    'pancontrolposition'            => '',
    'mapcontrolposition'            => '',
    'latlong'                       => '40,0',
    'maptype'                       => 'Map',
    'mtc'                           => 'standard',
    'baselayers' => array(
      'Map'                         => 1,
      'Satellite'                   => 1,
      'Hybrid'                      => 1,
      'Physical'                    => 1,
      'OpenStreetMap'               => 0,
    ),
    'scale'                         => 0,
    'overview'                      => 0,
    'overview_opened'               => 0,
    'scrollwheel'                   => 0,
    'scalecontrolposition'          => '',
    'sv_show'                       => 0, // Pegman
    'svcontrolposition'             => '',
    'sv_showfirst'                  => 0, // Overlay
    'sv_heading'                    => 0,
    'sv_zoom'                       => 1,
    'sv_pitch'                      => 0,
    'sv_enable'                     => 0, // switch set in getlocations_fields, applies to Views
    'sv_addresscontrol'             => 1, // sv overlay controls
    'sv_addresscontrolposition'     => '',
    'sv_pancontrol'                 => 1,
    'sv_pancontrolposition'         => '',
    'sv_zoomcontrol'                => 'default',
    'sv_zoomcontrolposition'        => '',
    'sv_linkscontrol'               => 1,
    'sv_imagedatecontrol'           => 0,
    'sv_scrollwheel'                => 1,
    'sv_clicktogo'                  => 1,
    'trafficinfo'                   => 0,
    'trafficinfo_state'             => 0,
    'bicycleinfo'                   => 0,
    'bicycleinfo_state'             => 0,
    'transitinfo'                   => 0,
    'transitinfo_state'             => 0,
    'panoramio_use'                 => 0,
    'panoramio_show'                => 0,
    'panoramio_state'               => 0,
    'places'                        => 0,
    'poi_show'                      => 1,
    'transit_show'                  => 1,
    'node_map_marker'               => 'drupal',
    'user_map_marker'               => 'drupal',
    'vocabulary_map_marker'         => 'drupal',
    'term_map_marker'               => 'drupal',
    'comment_map_marker'            => 'drupal',
    'input_map_marker'              => 'drupal',
    'markeraction'                  => 0,
    'markeractiontype'              => 1,
    'minzoom'                       => 6,
    'maxzoom'                       => 16,
    'nodezoom'                      => 12,
    'markermanagertype'             => 0,
    'usemarkermanager'              => 0,
    'useclustermanager'             => 0,
    'markerclusterer_style'         => -1,
    'markerclusterer_zoom'          => -1,
    'markerclusterer_size'          => -1,
    'markerclusterer_minsize'       => -1,
    'markerclusterer_title'         => t('Click here to see more'),
    'pansetting'                    => 2,
    'draggable'                     => 1,
    'styles'                        => '',
    'returnlink_page_enable'        => 0,
    'returnlink_page_link'          => t('Return to Page'),
    'returnlink_user_enable'        => 0,
    'returnlink_user_link'          => t('Return to User'),
    'returnlink_term_enable'        => 0,
    'returnlink_term_link'          => t('Return to Term'),
    'returnlink_comment_enable'     => 0,
    'returnlink_comment_link'       => t('Return to Comment'),
    'getlocations_js_weight'        => 0,
    'custom_content_enable'         => 0,
    'custom_content_source'         => '',
    'use_jsapi'                     => 0,
    'preload_data'                  => 0,
    'is_mobile'                     => (getlocations_is_mobile() ? 1 : 0),
    'geometry'                      => 0,
    'visualization'                 => 0,
    'drawing'                       => 0,
    'adsense'                       => 0,
    'weather_use'                   => 0,
    'weather_show'                  => 0,
    'weather_state'                 => 0,
    'weather_temp'                  => 1,
    'weather_speed'                 => 1,
    'weather_label'                 => 0,
    'weather_cloud'                 => 1,
    'weather_cloud_state'           => 0,
    'weather_clickable'             => 1,
    'weather_info'                  => 1,
    'map_backgroundcolor'           => '',
    'show_maplinks'                 => 0,
    'fullscreen'                    => 0,
    'show_bubble_on_one_marker'     => 0,
    'polygons_enable'               => 0,
    'polygons_strokecolor'          => "#FF0000",
    'polygons_strokeopacity'        => "0.8",
    'polygons_strokeweight'         => "3",
    'polygons_fillcolor'            => "#FF0000",
    'polygons_fillopacity'          => "0.35",
    'polygons_coords'               => "",
    'polygons_clickable'            => 0,
    'polygons_message'              => "",
    'rectangles_enable'             => 0,
    'rectangles_strokecolor'        => "#FF0000",
    'rectangles_strokeopacity'      => "0.8",
    'rectangles_strokeweight'       => "3",
    'rectangles_fillcolor'          => "#FF0000",
    'rectangles_fillopacity'        => "0.35",
    'rectangles_coords'             => "",
    'rectangles_clickable'          => 0,
    'rectangles_message'            => "",
    'rectangles_apply'              => 0,
    'rectangles_dist'               => 0,
    'circles_enable'                => 0,
    'circles_strokecolor'           => "#FF0000",
    'circles_strokeopacity'         => "0.8",
    'circles_strokeweight'          => "3",
    'circles_fillcolor'             => "#FF0000",
    'circles_fillopacity'           => "0.35",
    'circles_coords'                => "",
    'circles_clickable'             => 0,
    'circles_message'               => "",
    'circles_radius'                => 0,
    'circles_apply'                 => 0,
    'polylines_enable'              => 0,
    'polylines_strokecolor'         => "#FF0000",
    'polylines_strokeopacity'       => "0.8",
    'polylines_strokeweight'        => "3",
    'polylines_coords'              => "",
    'polylines_clickable'           => 0,
    'polylines_message'             => "",
    'category_method'               => 0,
    'category_term_reference_field' => '',
    'category_showhide_buttons'     => 0,
    'categories'                    => '',
    'kml_group' => array(
      'kml_url'                     => '',
      'kml_url_click'               => 1,
      'kml_url_infowindow'          => 0,
      'kml_url_viewport'            => 1,
      'kml_url_button'              => 0,
      'kml_url_button_label'        => 'Kml Layer',
      'kml_url_button_state'        => 0,
    ),
    'map_resize'                    => 0,
    'region_bias'                   => variable_get('site_default_country', ''),
    'fullscreen_disable'            => 0,
    'fullscreen_controlposition'    => '',
    'search_places'                 => 0,
    'search_places_size'            => 40,
    'search_places_position'        => 'outside_above',
    'search_places_label'           => t('Google Places Search'),
    'search_places_placeholder'     => '',
    'search_places_dd'              => 0,
    'search_places_list'            => 0,
    'getdirections_enabled'         => (module_exists('getdirections') ? 1 : 0),
    'jquery_colorpicker_enabled'    => (module_exists('jquery_colorpicker') ? 1 : 0),
    'geo_enable'                    => 0,
    'extcontrol'                    => '',
    'geojson_enable'                => 0,
    'geojson_data'                  => '',
    'geojson_options'               => '',
    'nokeyboard'                    => 0,
    'nodoubleclickzoom'             => 0,
    'input_map_show'                => 1,
    'highlight_enable'              => 0,
    'highlight_strokecolor'         => "#FF0000",
    'highlight_strokeopacity'       => "0.8",
    'highlight_strokeweight'        => "3",
    'highlight_fillcolor'           => "#FF0000",
    'highlight_fillopacity'         => "0.35",
    'highlight_radius'              => 10,
    'getdirections_link'            => 0,
    'gps_button'                    => 0,
    'gps_button_label'              => '',
    'gps_marker_title'              => '',
    'gps_marker'                    => '',
    'gps_bubble'                    => 0,
    'gps_geocode'                   => 0,
    'gps_center'                    => 0,
    'geolocation_mobile_check'      => 1,
  );
  if ($reset) {
    return $defaults;
  }
  // ease over to new settings. Wed Sep 25 01:09:23 BST 2013
  $getlocations_defaults = variable_get('getlocations_default', $defaults);
  if (isset($getlocations_defaults['behavior'])) {
    foreach ($getlocations_defaults['behavior'] AS $key => $val) {
      $getlocations_defaults[$key] = $val;
    }
    unset($getlocations_defaults['behavior']);
  }
  $newdefaults = getlocations_adjust_vars($defaults, $getlocations_defaults);
  return $newdefaults;
}

/**
 * Function to check if the configuration has been done yet
 *
 * @return
 *   Returns true or false
 */
function getlocations_defaults_check() {
  $check = variable_get('getlocations_default', 'xxx');
  if ($check == 'xxx') {
    return FALSE;
  }
  return TRUE;
}

/**
 * Function to check a lat,lon string
 *
 * @param string $latlon
 *
 * @return
 *   Returns normalized string or false
 */
function getlocations_latlon_check($latlon) {

  if (! empty($latlon)) {
    $ll = explode(',', $latlon);
    $lat = (isset( $ll[0]) ? $ll[0] : FALSE);
    $lon = (isset( $ll[1]) ? $ll[1] : FALSE);
    $lat = trim($lat);
    $lon = trim($lon);

    if ((abs($lat) || abs($lon)) && is_numeric($lat) && is_numeric($lon)) {
      $latregex = "/[-+]{0,1}[0-9]{1,}\.{1}[0-9]{1,}/";
      if (! strpos($lat, '.')) {
        $latregex = "/[-+]{0,1}[0-9]{1,}/";
      }
      $lonregex = "/[-+]{0,1}[0-9]{1,}\.{1}[0-9]{1,}/";
      if (! strpos($lon, '.')) {
        $lonregex = "/[-+]{0,1}[0-9]{1,}/";
      }
      if (preg_match($latregex, $lat) && preg_match($lonregex, $lon)) {
        // Normalize coordinates.
        $lat = getlocations_normalizelat($lat);
        $lon = getlocations_normalizelng($lon);
        return $lat . "," . $lon;
      }
    }
  }
  return FALSE;
}

/**
 * Function to check wether the google places library should be enabled.
 *
 * @return bool
 *
 *
 */
function getlocations_places_check() {
  $found = FALSE;
  if (module_exists('getlocations_fields')) {
    $getlocations_fields_defaults = getlocations_fields_defaults();
    if (isset($getlocations_fields_defaults['use_address']) && $getlocations_fields_defaults['use_address']) {
      $found = TRUE;
    }
  }
  $getlocations_defaults = getlocations_defaults();
  if ($getlocations_defaults['getdirections_enabled']) {
    $getdirections_defaults = getdirections_defaults();
    if (isset($getdirections_defaults['advanced_autocomplete']) && $getdirections_defaults['advanced_autocomplete']) {
      $found = TRUE;
    }
  }
  if (module_exists('getlocations_search')) {
    $getlocations_search_defaults = getlocations_search_defaults();
    if (isset($getlocations_search_defaults['method']) && $getlocations_search_defaults['method'] == 'google_ac') {
      $found = TRUE;
    }
  }
  return $found;
}

/**
 * Function to get the vid from node table.
 *
 * @param int $nid
 *
 * @return
 *   Returns vid.
 */
function getlocations_get_vid($nid) {
  if (is_numeric($nid) && $nid ) {
    $query = db_select('node', 'n')->fields('n', array('vid'))->condition('n.nid', $nid);
    $row = $query->execute()->fetchAssoc();
    return (isset($row['vid']) && $row['vid'] ? $row['vid'] : FALSE);
  }
  return FALSE;
}

/**
 * Function to get the nid from node table.
 *
 * @param int $vid
 *
 * @return
 *   Returns nid.
 */
function getlocations_get_nid($vid) {
  if (is_numeric($vid) && $vid ) {
    $query = db_select('node', 'n')->fields('n', array('nid'))->condition('n.vid', $vid);
    $row = $query->execute()->fetchAssoc();
    return (isset($row['nid']) && $row['nid'] ? $row['nid'] : FALSE);
  }
  return FALSE;
}

/**
 * Function to get nid from getlocations_fields_entities or location_instance table.
 *
 * @param int $lid
 *
 * @return
 *   Returns nid.
 */
function getlocations_get_nid_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')->fields('i', array('nid'))->condition('i.glid', $lid);
    }
    elseif (module_exists('location') && (module_exists('location_cck') || module_exists('location_node'))) {
      $query = db_select('location_instance', 'i')->fields('i', array('nid'))->condition('i.lid', $lid);
    }
    if ($query) {
      $row = $query->execute()->fetchAssoc();
      return (isset($row['nid']) && $row['nid'] ? $row['nid'] : FALSE);
    }
  }
  return FALSE;
}

/**
 * Function to get uid from getlocations_fields_entities or location_instance table.
 *
 * @param int $lid
 *
 * @return
 *   Returns uid.
 */
function getlocations_get_uid_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')->fields('i', array('uid'))->condition('i.glid', $lid);
    }
    elseif (module_exists('location') && module_exists('location_user')) {
      $query = db_select('location_instance', 'i')->fields('i', array('uid'))->condition('i.lid', $lid);
    }
    if ($query) {
      $row = $query->execute()->fetchAssoc();
      return (isset($row['uid']) && $row['uid'] ? $row['uid'] : FALSE);
    }
  }
  return FALSE;
}

/**
 * Function to get tid from getlocations_fields_entities table.
 *
 * @param int $lid
 *
 * @return
 *   Returns tid.
 */
function getlocations_get_tid_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')->fields('i', array('tid'))->condition('i.glid', $lid);
    }
    if ($query) {
      $row = $query->execute()->fetchAssoc();
      return (isset($row['tid']) && $row['tid'] ? $row['tid'] : FALSE);
    }
  }
  return FALSE;
}

/**
 * Function to get cid from getlocations_fields_entities table.
 *
 * @param int $lid
 *
 * @return
 *   Returns cid.
 */
function getlocations_get_cid_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')->fields('i', array('cid'))->condition('i.glid', $lid);
    }
    if ($query) {
      $row = $query->execute()->fetchAssoc();
      return (isset($row['cid']) && $row['cid'] ? $row['cid'] : FALSE);
    }
  }
  return FALSE;
}

/**
 * Function to get entity type from getlocations_fields_entities or location_instance table.
 *
 * @param int $lid
 *
 * @return
 *   Returns entity type.
 */
function getlocations_get_type_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')->fields('i', array('nid', 'uid', 'tid', 'cid'))->condition('i.glid', $lid);
    }
    elseif (module_exists('location') && (module_exists('location_cck') || module_exists('location_node') || module_exists('location_user'))) {
      $query = db_select('location_instance', 'i')->fields('i', array('nid', 'uid'))->condition('i.lid', $lid);
    }
    if ($query) {
      $row = $query->execute()->fetchAssoc();
      $type = '';
      if (isset($row['nid']) && $row['nid'] > 0) {
        $type = 'node';
      }
      elseif (isset($row['uid']) && $row['uid'] > 0) {
        $type = 'user';
      }
      elseif (isset($row['tid']) && $row['tid'] > 0 && module_exists('taxonomy')) {
        $type = 'vocabulary';
      }
      elseif (isset($row['cid']) && $row['cid'] > 0 && module_exists('comment')) {
        $type = 'comment';
      }
      return $type;
    }
  }
  return FALSE;
}

/**
 * Function to get entity path from getlocations_fields_entities or location_instance table.
 *
 * @param int $lid
 *
 * @return
 *   Returns entity path as url.
 */
function getlocations_get_path_from_lid($lid) {
  if (is_numeric($lid) && $lid) {
    $query = FALSE;
    if (module_exists('getlocations_fields')) {
      $query = db_select('getlocations_fields_entities', 'i')->fields('i', array('nid', 'uid', 'tid', 'cid'))->condition('i.glid', $lid);
    }
    elseif (module_exists('location') && (module_exists('location_cck') || module_exists('location_node') || module_exists('location_user'))) {
      $query = db_select('location_instance', 'i')->fields('i', array('nid', 'uid'))->condition('i.lid', $lid);
    }
    if ($query) {
      $row = $query->execute()->fetchAssoc();
      $path = '';
      if (isset($row['nid']) && $row['nid'] > 0) {
        $path = url('node/' . $row['nid']);
      }
      elseif (isset($row['uid']) && $row['uid'] > 0) {
        $path = url('user/' . $row['uid']);
      }
      elseif (isset($row['tid']) && $row['tid'] > 0 && module_exists('taxonomy')) {
        $path = url('taxonomy/term/' . $row['tid']);
      }
      elseif (isset($row['cid']) && $row['cid'] > 0 && module_exists('comment')) {
        $path = url('comment/' . $row['cid']);
      }
      return $path;
    }
  }
  return FALSE;
}

/**
 * Ajax callback
 * Fetches bubble content
 *
 * @see theme_getlocations_adinfo().
 */
function getlocations_adinfo() {

  $lid = $_GET['lid'];
  $lidkey = $_GET['key'];

  $extra = FALSE;
  if (isset($_GET['sdist'])) {
    $extra['sdist'] = $_GET['sdist'];
  }
  if (isset($_GET['gdlink'])) {
    $extra['gdlink'] = $_GET['gdlink'];
  }

  $content = getlocations_getinfo($lid, $lidkey, $extra);
  drupal_json_output(array('content' => $content));

}

/**
 * @param int $lid location id
 * @param string entity id
 * @return string formatted address
 */
function getlocations_getinfo($lid, $lidkey, $extra=FALSE) {

  $content = FALSE;
  if ($lid > 0) {
    if (module_exists('getlocations_fields') || module_exists('location')) {
      $location = getlocations_load_location($lid);
      $location['nid'] = 0;
      $location['uid'] = 0;
      $location['tid'] = 0;
      $location['cid'] = 0;

      $type = getlocations_get_type_from_lid($lid);
      if ($type == 'node') {
        if ($nid = getlocations_get_nid_from_lid($lid)) {
          $location['nid'] = $nid;
        }
      }
      elseif ($type == 'user') {
        if ($uid = getlocations_get_uid_from_lid($lid)) {
          $location['uid'] = $uid;
        }
      }
      elseif ($type == 'vocabulary' && module_exists('taxonomy')) {
        if ($tid = getlocations_get_tid_from_lid($lid)) {
          $location['tid'] = $tid;
        }
      }
      elseif ($type == 'comment' && module_exists('comment')) {
        if ($cid = getlocations_get_cid_from_lid($lid)) {
          $location['cid'] = $cid;
        }
      }
    }
    elseif (module_exists('geofield') || module_exists('geolocation')) {
      $locations = getlocations_load_locations($lid, $lidkey);
      $location = $locations[0];
    }

    if ($extra) {
      if (is_array($extra) && isset($extra['sdist'])) {
        $sdist = $extra['sdist'];
        $arr = explode('|', $sdist);
        $sunit = $arr[0];
        $slat = $arr[1];
        $slon = $arr[2];
        $lat = $location['latitude'];
        $lon = $location['longitude'];
        $latlon_a = array('lat' => $slat, 'lon' => $slon);
        $latlon_b = array('lat' => $lat, 'lon' => $lon);
        $dist = getlocations_distance_between($latlon_a, $latlon_b, $sunit);
        $location['sdist'] = $dist['scalar'];
        $location['sunit'] = $dist['distance_unit'];
      }
      if (is_array($extra) && isset($extra['gdlink'])) {
        $location['getdirections_link'] = $extra['gdlink'];
      }
    }

    $content = theme('getlocations_adinfo', array('location' => $location));
  }
  return $content;

}

/**
 * Ajax callback
 * Provides a link
 *
 * @see theme_getlocations_lidinfo()
 *
 */
function getlocations_lidinfo() {
  $lid = $_GET['lid'];
  $lidkey = $_GET['key'];
  $content = getlocations_getlidinfo($lid, $lidkey);
  drupal_json_output(array('content' => $content));
}

/**
 * @param int $lid location id
 * @param string entity id
 * @return string path
 */
function getlocations_getlidinfo($lid, $lidkey) {
  $content = theme('getlocations_lidinfo', array('lid' => $lid, 'lidkey' => $lidkey));
  return $content;
}

/**
 * Ajax callback
 * provides data for marker colorbox
 *
 * @see template_preprocess_getlocations_marker_box()
 * @see getlocations_marker_box.tpl.php
 */
function getlocations_markerinfo() {
  $linktype = $_GET['lt'];
  $cat =  $_GET['cat'];
  $content = "";
  $icons =   getlocations_get_icondata();
  $data = array();
  $files = array();
  $machine_names = array();
  $display_names = array();
  $positions = array();
  $iconct = 0;
  foreach (array_keys($icons) AS $path) {
    if (preg_match("~^/.*/$~", $path)) {
      continue;
    }
    $files = $icons[$path]['f'];
    $machine_names = $icons[$path]['i'][0][0][0];
    $display_names = $icons[$path]['i'][0][0][1];
    $positions     = $icons[$path]['i'][0][0][2];
    $newpositions = array();
    foreach ($positions AS $pos) {
      if (isset($pos[0])) {
        $newpositions[] = $pos[0];
      }
    }
    $adj = 0;
    foreach ($newpositions AS $pos) {
      // no shadow
      if ($pos < 1) {
        $adj = 1;
      }
      // skip this
      if ($files[$pos] == 'shadow.png') {
        continue;
      }
      $data[$iconct]['path'] = $path . $files[$pos];
      $data[$iconct]['machine_name'] = $machine_names[$pos + $adj];
      $data[$iconct]['display_name'] = $display_names[$pos + $adj];
      $iconct++;
    }
  }
  $content['data'] = $data;
  $content['linktype'] = $linktype;
  $content['cat'] = $cat;
  $output = theme('getlocations_marker_box', array('content' => $content));
  print $output;
  exit;
}

/**
 * Get the list of marker titles.
 * adapted from gmap
 */
function getlocations_get_marker_titles($reset = FALSE) {
  static $titles;

  if (!$reset) {
    if (is_array($titles)) {
      return $titles;
    }

    $cached = cache_get('getlocations_marker_titles', 'cache');
    if (!empty($cached)) {
      $titles = $cached->data;
      if (is_array($titles)) {
        return $titles;
      }
    }
  }

  module_load_include('inc', 'getlocations', 'getlocations.markerinfo');
  $titles = _getlocations_get_marker_titles();
  cache_set('getlocations_marker_titles', $titles, 'cache');
  return $titles;
}

/**
 * Get the JSON icon data for all the default markers.
 * adapted from gmap
 */
function getlocations_get_icondata($reset = FALSE) {
  static $icons;
  if (is_array($icons) && !$reset) {
    return $icons;
  }

  $icons = cache_get('getlocations_icondata');
  if ($icons) {
    $icons = $icons->data;
  }

  if ($reset || !$icons) {
    module_load_include('inc', 'getlocations', 'getlocations.markerinfo');
    $icons = _getlocations_get_icondata();
  }
  if ($icons) {
    cache_set('getlocations_icondata', $icons, 'cache');
  }
  return $icons;
}

/**
 * Regenerate the markerdata file.
 * adapted from gmap
 */
function getlocations_regenerate_markers() {
  // This often fails in cli mode, so bail.
  if (drupal_is_cli()) {
    return;
  }

  $icons = getlocations_get_icondata(TRUE);
  if ($icons) {
    $contents = '';

    $contents .= "// Getlocations marker image data.\n";
    $contents .= "Drupal.getlocations.iconpath = " . drupal_json_encode(base_path()) . ";\n";
    $contents .= "Drupal.getlocations.icondata = " . drupal_json_encode($icons) . ";\n";

    // Create the js/ within the files folder.
    $jspath = getlocations_get_markerfile(TRUE, FALSE);
    $jsfile = getlocations_get_markerfile(FALSE, FALSE);
    if ($jspath && $jsfile && file_prepare_directory($jspath, FILE_CREATE_DIRECTORY) && file_unmanaged_save_data($contents, $jsfile, FILE_EXISTS_REPLACE)) {
      // Also regenerate the cached marker titles array
      getlocations_get_marker_titles(TRUE);
    }
    else {
      // failed
      drupal_set_message(t('Getlocations is unable to save the marker configuration, so the markers will not work. Please check file system permissions of %filepath!', array('%filepath' => $jsfile)), 'error');
      watchdog('getlocations', 'Getlocations write error when saving the marker configuration to %filepath.', array('%filepath' => $jsfile), WATCHDOG_ERROR);
      return FALSE;
    }
  }
  else {
    // no markers found
      drupal_set_message(t('No markers found, you need to install some markers, please see the project page for details.'), 'error');
      watchdog('getlocations', 'No markers found.', array(), WATCHDOG_ERROR);
      return FALSE;
  }
  return TRUE;
}

/**
 * Function to find and return the filesystem path and filename of the markers definition javascript file
 *
 */
function getlocations_get_markerfile($dir=FALSE, $check=TRUE) {

  if (file_default_scheme() != 'public') {
    // private
    $markerpath = '';
    $markerfile = variable_get('getlocations_private_markerfile', '');
    if ($markerfile && preg_match("~^(.*)/getlocations_markers.js~", $markerfile, $matches)) {
      $markerpath = $matches[1];
    }
  }
  else {
    $markerpath = file_stream_wrapper_get_instance_by_scheme(file_default_scheme())->getDirectoryPath() . '/getlocations';
    $markerfile = '';
    if ($markerpath) {
      $markerfile = $markerpath . '/getlocations_markers.js';
    }
  }
  if ($dir && $markerpath) {
    if ($check) {
      if (file_exists($markerpath)) {
        return $markerpath;
      }
    }
    else {
      return $markerpath;
    }
  }
  elseif ($markerfile) {
    if ($check) {
      if (file_exists($markerfile)) {
        return $markerfile;
      }
    }
    else {
      return $markerfile;
    }
  }
  return FALSE;
}

/**
 * hook_getlocations_markerdir()
 * from jhm http://drupal.org/user/15946
 *
 * This hook allows modules or themes to add their own markers
 */
function getlocations_getlocations_markerdir() {
  $markerdir = libraries_get_path('getlocations') . '/markers';
  return $markerdir;
}

/**
 * @param int $ct $location $minmaxes
 *
 * @return
 *   Returns $minmaxes
 *
 */
function getlocations_do_minmaxes($ct, $location, $minmaxes) {
  if ($minmaxes == '') {
    $minmaxes = array('minlat' => 0, 'minlon' => 0, 'maxlat' => 0, 'maxlon' => 0);
  }
  if ($ct) {
    // latitudes
    if ($location['latitude'] > $minmaxes['maxlat']) {
      $minmaxes['maxlat'] = $location['latitude'];
    }
    if ($location['latitude'] < $minmaxes['minlat']) {
      $minmaxes['minlat'] = $location['latitude'];
    }
    // longitudes
    if ($location['longitude'] > $minmaxes['maxlon']) {
      $minmaxes['maxlon'] = $location['longitude'];
    }
    if ($location['longitude'] < $minmaxes['minlon']) {
      $minmaxes['minlon'] = $location['longitude'];
    }
  }
  else {
    $minmaxes['minlat'] = $location['latitude'];
    $minmaxes['minlon'] = $location['longitude'];
    $minmaxes['maxlat'] = $location['latitude'];
    $minmaxes['maxlon'] = $location['longitude'];
  }
  return $minmaxes;
}

/**
 * Function for colorbox and suchlike
 *
 * @return
 *   Returns themed content
 *
 */
function getlocations_box() {

  $a1 = FALSE;
  $a2 = FALSE;
  $a3 = FALSE;
  $a4 = FALSE;

  if (arg(1)) {
    $a1 = arg(1);
  }
  if (arg(2)) {
    $a2 = arg(2);
  }
  if (arg(3)) {
    $a3 = arg(3);
  }
  if (arg(4)) {
    $a4 = arg(4);
  }

  $content = '';

  // $a1 can be node, user, users, type, lids, nids
  if ($a1 == 'node' && $a2) {
    $content .= getlocations_nodemap($a2);
  }
  elseif ($a1 == 'user' && $a2) {
    $content .= getlocations_usermap($a2);
  }
  elseif ($a1 == 'term' && $a2) {
    $content .= getlocations_termmap($a2);
  }
  elseif ($a1 == 'comment' && $a2) {
    $content .= getlocations_commentmap($a2);
  }
  elseif ($a1 == 'users') {
    $content .= getlocations_usersmap();
  }
  elseif ($a1 == 'type' && $a2) {
    $content .= getlocations_typemap($a2, $a3, $a4);
  }
  elseif ($a1 == 'lids' && $a2) {
    $content .= getlocations_lids($a2);
  }
  elseif ($a1 == 'nids' && $a2) {
    $content .= getlocations_nids($a2);
  }

  $output = theme('getlocations_box', array('content' => $content));
  print $output;
  exit;
}

/**
 * Function to fetch node types
 *
 *
 * @return
 *   Returns array of node types supported by the current supported locative module
 *
 */
function getlocations_get_types() {
  $options = array();
  foreach (node_type_get_types() as $type => $object) {
    if (getlocations_check_node($type)) {
      $options[$type] = $object->name;
    }
  }
  return $options;
}

/**
 * Function to check if bundle has a locative field
 *
 * @param string $bundle
 *
 * @return
 *   Returns boolean
 *
 */
function getlocations_check_node($bundle) {

  $module = getlocations_get_current_supported_module();
  if ($module) {
    $query = db_select('field_config', 'f');
    $query->fields('f', array('id'));
    $query->join('field_config_instance', 'i', 'f.id=i.field_id');
    $query->condition('i.bundle', $bundle)
      ->condition('f.module', $module)
      ->condition('i.entity_type', 'node')
      ->condition('f.active', 1);
    $rows = $query->execute();
    $ct = 0;
    foreach ($rows AS $row) {
      $ct++;
    }
    if ($ct) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Function to collect field name
 *
 * @param string $bundle
 * @param string $entity_type
 *
 * @return
 *   Returns field name or FALSE
 *
 */
function getlocations_get_fieldname($bundle, $entity_type='node') {

  $module = getlocations_get_current_supported_module();
  if ($module) {
    $query = db_select('field_config', 'f');
    $query->fields('f', array('field_name'));
    $query->join('field_config_instance', 'i', 'f.id=i.field_id');
    $query->condition('i.bundle', $bundle)
      ->condition('f.module', $module)
      ->condition('i.entity_type', $entity_type)
      ->condition('f.active', 1);
    $rows = $query->execute();
    $ct = 0;
    foreach ($rows AS $row) {
      $data = $row->field_name;
      $ct++;
    }
    if ($ct) {
      return $data;
    }
  }
  return FALSE;
}

/**
 * Function to collect field names
 *
 * @param string $bundle
 * @param string $entity_type
 *
 * @return
 *   Returns field names or FALSE
 *
 */
function getlocations_get_fieldname2($bundle, $entity_type='node') {

  $module = getlocations_get_current_supported_module();
  if ($module) {
    $query = db_select('field_config', 'f');
    $query->fields('f', array('field_name'));
    $query->join('field_config_instance', 'i', 'f.id=i.field_id');
    $query->condition('i.bundle', $bundle)
      ->condition('f.module', $module)
      ->condition('i.entity_type', $entity_type)
      ->condition('f.active', 1);
    $rows = $query->execute();
    $ct = 0;
    foreach ($rows AS $row) {
      $data[$ct] = $row->field_name;
      $ct++;
    }
    if ($ct) {
      return $data;
    }
  }
  return FALSE;
}

/**
 * Function is an entity_type location enabled?
 *
 * @param string $entity_type
 * @param string $bundle
 *
 * @return
 *   Returns boolean
 *
 */
function getlocations_check_entity_type($entity_type = '', $bundle = '') {
  if ($entity_type == 'term') {
    $entity_type = 'taxonomy_term';
  }
  if ($module = getlocations_get_current_supported_module()) {
    $query = db_select('field_config', 'f');
    $query->fields('f', array('id'));
    $query->join('field_config_instance', 'i', 'f.id=i.field_id');
    $query->condition('f.module', $module);
    if ($entity_type) {
      $query->condition('i.entity_type', $entity_type);
    }
    if ($bundle) {
      $query->condition('i.bundle', $bundle);
    }
    $query->condition('f.active', 1);
    $number_of_rows = $query->countQuery()->execute()->fetchField();
    if ($number_of_rows) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Function gets list of vocabularies
 *
 * @return
 *   Returns array
 *
 */
function getlocations_get_vocabularies() {
  if (module_exists('taxonomy')) {
    $vocabularies = taxonomy_get_vocabularies();
    $options = array();
    if (count($vocabularies)) {
      foreach ($vocabularies as $vid => $vocabulary) {
        if (getlocations_check_vocabulary($vocabulary->machine_name)) {
          $options[$vid] = $vocabulary->name;
        }
      }
      return $options;
    }
  }
  return FALSE;
}

/**
 * Function gets list of vocabulary machine names
 *
 * @return
 *   Returns array
 *
 */
function getlocations_get_machine_vocabularies() {
  if (module_exists('taxonomy')) {
    $vocabularies = taxonomy_get_vocabularies();
    $options = array();
    if (count($vocabularies)) {
      foreach ($vocabularies as $vid => $vocabulary) {
        if (getlocations_check_vocabulary($vocabulary->machine_name)) {
          $options[$vid] = $vocabulary->machine_name;
        }
      }
      return $options;
    }
  }
  return FALSE;
}

/**
 * Function to check a vocabulary
 *
 * @return
 *   Returns bool
 *
 */
function getlocations_check_vocabulary($machine_name) {
  if (module_exists('taxonomy')) {
    return getlocations_check_entity_type('taxonomy_term', $machine_name);
  }
  return FALSE;
}

/**
 * Function list of term reference fields
 *
 * @return
 *   Returns array
 *
 */
function getlocations_get_term_reference_fields() {
  $module = 'taxonomy';
  $type = 'taxonomy_term_reference';
  $query = db_select('field_config', 'f');
  $query->fields('f', array('field_name'));
  $query->condition('f.module', $module)
    ->condition('f.type', $type)
    ->condition('f.active', 1);
  $rows = $query->execute();
  $data = array();
  foreach ($rows AS $row) {
    $data[$row->field_name] = $row->field_name;
  }
  return $data;

}

/**
 * Function to fetch list of markers
 *
 * @param string $type
 *
 * @return
 *   Returns list of markers
 *
 */
function getlocations_get_markertypes($type) {

  $getlocations_defaults = getlocations_defaults();

  $markertypes = array();
  if ($type == 'node') {
    $default_marker = $getlocations_defaults['node_map_marker'];
    $getlocations_node_marker = variable_get('getlocations_node_marker', array('enable' => 0));
    if ($getlocations_node_marker['enable']) {
      if ($content_types = getlocations_get_types()) {
        foreach ($content_types AS $content_type => $name ) {
          $field_names = getlocations_get_fieldname2($content_type, 'node');
          foreach ($field_names AS $field_name) {
            if (isset($getlocations_node_marker['content_type'][$content_type]['field_name'][$field_name]['map_marker'])) {
              $markertypes[$content_type] = $getlocations_node_marker['content_type'][$content_type]['field_name'][$field_name]['map_marker'];
            }
            else {
              $markertypes[$content_type] = $default_marker;
            }
          }
        }
      }
    }
    return $markertypes;
  }
  elseif ($type == 'vocabulary' && module_exists('taxonomy')) {
    $default_marker = $getlocations_defaults['vocabulary_map_marker'];
    $vocabularies = getlocations_get_vocabularies();
    $getlocations_vocabulary_marker = variable_get('getlocations_vocabulary_marker', array('enable' => 0));
    foreach ($vocabularies AS $vid => $vocabulary) {
      if ($getlocations_vocabulary_marker['enable'] && isset($getlocations_vocabulary_marker['vocabulary'][$vid]['map_marker'])) {
        $markertypes[$vid] = $getlocations_vocabulary_marker['vocabulary'][$vid]['map_marker'];
      }
      else {
        $markertypes[$vid] = $default_marker;
      }
    }
    return $markertypes;
  }
  elseif ($type == 'term' && module_exists('taxonomy')) {
    $default_marker = $getlocations_defaults['term_map_marker'];
    $getlocations_term_marker = variable_get('getlocations_term_marker', array('enable' => 0, 'vids' => 0, 'max_depth' => ''));
    if ($getlocations_term_marker['enable'] && $getlocations_term_marker['vids'] ) {
      $depth = is_numeric($getlocations_term_marker['max_depth']) && $getlocations_term_marker['max_depth'] > 0 ? $getlocations_term_marker['max_depth'] : NULL;
      $vids = $getlocations_term_marker['vids'];
      foreach ($vids AS $vid) {
        $terms = taxonomy_get_tree($vid, 0, $depth);
        foreach ($terms AS $term) {
          if (isset($getlocations_term_marker['vid'][$vid]['term'][$term->tid]['map_marker'])) {
            $markertypes[$term->tid] = $getlocations_term_marker['vid'][$vid]['term'][$term->tid]['map_marker'];
          }
          else {
            $markertypes[$term->tid] = $default_marker;
          }
        }
      }
    }
    return $markertypes;
  }
  else {
    return FALSE;
  }
}

/**
 * Function to fetch a node type or bundle
 *
 * @param int $nid The node Identifier
 *
 * @return
 *   Returns the bundle name or false
 *
 */
function getlocations_get_nodetype($nid) {
  $query = db_select('node', 'n')->fields('n', array('type'))->condition('n.nid', $nid);
  $row = $query->execute()->fetchAssoc();
  return (isset($row['type']) && $row['type'] ? $row['type'] : FALSE);
}

/**
 * Function sets up javascript settings
 *
 * @param array $defaults
 * @param array $latlons
 * @param array $minmaxes
 * @param string $mapid
 * @param bool $inputmap
 * @param string $extcontrol
 *
 */
function getlocations_js_settings_do($defaults, $latlons, $minmaxes, $mapid, $inputmap = FALSE, $extcontrol = '') {
  global $language, $is_https;
  $lla = explode(',', $defaults['latlong']);
  $lat = $lla[0];
  $lng = $lla[1];
  $settings = array(
    $mapid => array(
      'lat'                       => trim($lat),
      'lng'                       => trim($lng),
      'locale_prefix'             => $language->prefix,
      'zoom'                      => $defaults['zoom'],
      'minzoom_map'               => $defaults['minzoom_map'],
      'maxzoom_map'               => $defaults['maxzoom_map'],
      'maptype'                   => $defaults['maptype'],
      'controltype'               => $defaults['controltype'],
      'mtc'                       => $defaults['mtc'],
      'baselayers'                => $defaults['baselayers'],
      'scale'                     => $defaults['scale'],
      'overview'                  => $defaults['overview'],
      'overview_opened'           => $defaults['overview_opened'],
      'scrollwheel'               => $defaults['scrollwheel'],
      'trafficinfo'               => $defaults['trafficinfo'],
      'trafficinfo_state'         => $defaults['trafficinfo_state'],
      'bicycleinfo'               => $defaults['bicycleinfo'],
      'bicycleinfo_state'         => $defaults['bicycleinfo_state'],
      'transitinfo'               => $defaults['transitinfo'],
      'transitinfo_state'         => $defaults['transitinfo_state'],
      'sv_show'                   => $defaults['sv_show'],
      'sv_showfirst'              => $defaults['sv_showfirst'],
      'sv_heading'                => $defaults['sv_heading'],
      'sv_zoom'                   => $defaults['sv_zoom'],
      'sv_pitch'                  => $defaults['sv_pitch'],
      'pancontrol'                => $defaults['pancontrol'],
      'panoramio_use'             => $defaults['panoramio_use'],
      'panoramio_show'            => $defaults['panoramio_show'],
      'panoramio_state'           => $defaults['panoramio_state'],
      'weather_use'               => $defaults['weather_use'],
      'poi_show'                  => $defaults['poi_show'],
      'transit_show'              => $defaults['transit_show'],
      'map_marker'                => $defaults['node_map_marker'],
      'markeraction'              => $defaults['markeraction'],
      'markeractiontype'          => $defaults['markeractiontype'],
      'minzoom'                   => $defaults['minzoom'],
      'maxzoom'                   => $defaults['maxzoom'],
      'nodezoom'                  => $defaults['nodezoom'],
      'markermanagertype'         => $defaults['markermanagertype'],
      'usemarkermanager'          => $defaults['usemarkermanager'],
      'useclustermanager'         => $defaults['useclustermanager'],
      'markerclusterer_style'     => $defaults['markerclusterer_style'],
      'markerclusterer_zoom'      => $defaults['markerclusterer_zoom'],
      'markerclusterer_size'      => $defaults['markerclusterer_size'],
      'markerclusterer_minsize'   => $defaults['markerclusterer_minsize'],
      'markerclusterer_title'     => $defaults['markerclusterer_title'],
      'pansetting'                => $defaults['pansetting'],
      'draggable'                 => $defaults['draggable'],
      'styles'                    => $defaults['styles'],
      'inputmap'                  => ($inputmap ? 1 : 0),
      'extcontrol'                => $extcontrol,
      'custom_content_enable'     => $defaults['custom_content_enable'],
      'preload_data'              => $defaults['preload_data'],
      'is_mobile'                 => (getlocations_is_mobile() ? 1 : 0),
      'weather_use'               => $defaults['weather_use'],
      'map_backgroundcolor'       => $defaults['map_backgroundcolor'],
      'show_maplinks'             => $defaults['show_maplinks'],
      'js_path'                   => base_path() . GETLOCATIONS_PATH . '/js/',
      'images_path'               => base_path() . GETLOCATIONS_PATH . '/images/',
      'info_path'                 => url("getlocations_cb/info"),
      'lidinfo_path'              => url("getlocations_cb/lidinfo"),
      'fullscreen'                => $defaults['fullscreen'],
      'show_bubble_on_one_marker' => $defaults['show_bubble_on_one_marker'],
      'kml_url'                   => $defaults['kml_group']['kml_url'],
      'fullscreen_disable'        => $defaults['fullscreen_disable'],
      'fullscreen_controlposition' => $defaults['fullscreen_controlposition'],
      'places'                    => $defaults['places'],
      'search_places'             => $defaults['search_places'],
      'getdirections_enabled'     => $defaults['getdirections_enabled'],
      'is_https'                  => ($is_https ? 1 : 0),
      'geojson_enable'            => $defaults['geojson_enable'],
      'nokeyboard'                => $defaults['nokeyboard'],
      'nodoubleclickzoom'         => $defaults['nodoubleclickzoom'],
      'zoomcontrolposition'       => $defaults['zoomcontrolposition'],
      'mapcontrolposition'        => $defaults['mapcontrolposition'],
      'pancontrolposition'        => $defaults['pancontrolposition'],
      'scalecontrolposition'      => $defaults['scalecontrolposition'],
      'svcontrolposition'         => $defaults['svcontrolposition'],
      'sv_addresscontrol'         => $defaults['sv_addresscontrol'], // sv overlay controls
      'sv_addresscontrolposition' => $defaults['sv_addresscontrolposition'],
      'sv_pancontrol'             => $defaults['sv_pancontrol'],
      'sv_pancontrolposition'     => $defaults['sv_pancontrolposition'],
      'sv_zoomcontrol'            => $defaults['sv_zoomcontrol'],
      'sv_zoomcontrolposition'    => $defaults['sv_zoomcontrolposition'],
      'sv_linkscontrol'           => $defaults['sv_linkscontrol'],
      'sv_imagedatecontrol'       => $defaults['sv_imagedatecontrol'],
      'sv_scrollwheel'            => $defaults['sv_scrollwheel'],
      'sv_clicktogo'              => $defaults['sv_clicktogo'],
      'input_map_show'            => $defaults['input_map_show'],
    ),
  );
  // only set these if wanted
  if ($defaults['kml_group']['kml_url']) {
    $settings[$mapid]['kml_url_click']        = $defaults['kml_group']['kml_url_click'];
    $settings[$mapid]['kml_url_infowindow']   = $defaults['kml_group']['kml_url_infowindow'];
    $settings[$mapid]['kml_url_viewport']     = $defaults['kml_group']['kml_url_viewport'];
    $settings[$mapid]['kml_url_button']       = $defaults['kml_group']['kml_url_button'];
    $settings[$mapid]['kml_url_button_label'] = $defaults['kml_group']['kml_url_button_label'];
    $settings[$mapid]['kml_url_button_state'] = $defaults['kml_group']['kml_url_button_state'];
  }
  if ($defaults['weather_use']) {
    $settings[$mapid]['weather_show']        = $defaults['weather_show'];
    $settings[$mapid]['weather_state']       = $defaults['weather_state'];
    $settings[$mapid]['weather_temp']        = $defaults['weather_temp'];
    $settings[$mapid]['weather_speed']       = $defaults['weather_speed'];
    $settings[$mapid]['weather_label']       = $defaults['weather_label'];
    $settings[$mapid]['weather_cloud']       = $defaults['weather_cloud'];
    $settings[$mapid]['weather_cloud_state'] = $defaults['weather_cloud_state'];
    $settings[$mapid]['weather_clickable']   = $defaults['weather_clickable'];
    $settings[$mapid]['weather_info']        = $defaults['weather_info'];
  }
  if ($defaults['search_places']) {
    $settings[$mapid]['search_places_size']        = $defaults['search_places_size'];
    $settings[$mapid]['search_places_position']    = $defaults['search_places_position'];
    $settings[$mapid]['search_places_label']       = $defaults['search_places_label'];
    $settings[$mapid]['search_places_placeholder'] = $defaults['search_places_placeholder'];
    $settings[$mapid]['search_places_dd']          = $defaults['search_places_dd'];
    $settings[$mapid]['search_places_list']        = $defaults['search_places_list'];
  }
  if ($defaults['geojson_enable']) {
    $settings[$mapid]['geojson_data']    = $defaults['geojson_data'];
    $settings[$mapid]['geojson_options'] = $defaults['geojson_options'];
  }

  // categories
  if (isset($defaults['categories'])) {
    $settings[$mapid]['categories'] = $defaults['categories'];
  }
  else {
    $settings[$mapid]['categories'] = array();
  }

  // highlighting
  $settings[$mapid]['highlight_enable'] = $defaults['highlight_enable'];
  if ($defaults['highlight_enable']) {
    if (! preg_match("/^#/", $defaults['highlight_strokecolor'])) {
      $defaults['highlight_strokecolor'] = '#' . $defaults['highlight_strokecolor'];
    }
    if (! preg_match("/^#/", $defaults['highlight_fillcolor'])) {
      $defaults['highlight_fillcolor'] = '#' . $defaults['highlight_fillcolor'];
    }
    $settings[$mapid]['highlight_strokecolor']   = $defaults['highlight_strokecolor'];
    $settings[$mapid]['highlight_strokeopacity'] = $defaults['highlight_strokeopacity'];
    $settings[$mapid]['highlight_strokeweight']  = $defaults['highlight_strokeweight'];
    $settings[$mapid]['highlight_fillcolor']     = $defaults['highlight_fillcolor'];
    $settings[$mapid]['highlight_fillopacity']   = $defaults['highlight_fillopacity'];
    $settings[$mapid]['highlight_radius']        = $defaults['highlight_radius'];
  }
  $settings[$mapid]['getdirections_link']        = $defaults['getdirections_link'];

  drupal_add_js(array('getlocations' => $settings), 'setting');

  if ($defaults['preload_data']) {
    $info = array();
    if (count($latlons)) {
      $ct = 0;
      foreach ($latlons AS $latlon) {
        $info[$ct]['lid'] = 0;
        $info[$ct]['lidkey'] = '';
        $info[$ct]['content'] = '';
        if (isset($latlon[2]) && isset($latlon[5])) {
          $info[$ct]['lid'] = $latlon[2];
          $info[$ct]['lidkey'] = $latlon[5];
          $info[$ct]['content'] = '';
          if ($defaults['markeraction'] == 1 || $defaults['markeraction'] == 2) {
            $extra = FALSE;
            if (isset($defaults['getdirections_link'])) {
              $extra['gdlink'] = $defaults['getdirections_link'];
            }
            $info[$ct]['content'] = getlocations_getinfo($latlon[2], $latlon[5], $extra);
          }
          elseif ($defaults['markeraction'] == 3) {
            $info[$ct]['content'] = getlocations_getlidinfo($latlon[2], $latlon[5]);
          }
        }
        $ct++;
      }
    }
    $info_settings = array(
      $mapid => $info,
    );
    drupal_add_js(array('getlocations_info' => $info_settings), 'setting');
  }

  // polygons
  if ($defaults['polygons_enable'] && ! empty($defaults['polygons_coords'])) {
    $polygons = getlocations_get_polygon_settings($defaults);
    if ($polygons) {
      $polygon_settings = array(
        $mapid => $polygons,
      );
      drupal_add_js(array('getlocations_polygons' => $polygon_settings), 'setting');
    }
  }
  // rectangles
  if ($defaults['rectangles_enable'] && (! empty($defaults['rectangles_coords']) || ($defaults['rectangles_apply'] && $defaults['rectangles_dist']))) {
    if ($defaults['rectangles_apply'] && $defaults['rectangles_dist']) {
      // get latlons and set coords
      $tmp = '';
      foreach ($latlons AS $ll) {
        $lats = getlocations_earth_latitude_range($ll[0], $ll[1], $defaults['rectangles_dist']);
        $lngs = getlocations_earth_longitude_range($ll[0], $ll[1], $defaults['rectangles_dist']);
        $tmp .= $lats[0] . ',' . $lngs[0] . '|' . $lats[1] . ',' . $lngs[1] . "\n";
      }
      if ($tmp) {
        $defaults['rectangles_coords'] = $tmp;
      }
    }
    $rectangles = getlocations_get_rectangle_settings($defaults);
    if ($rectangles) {
      $rectangle_settings = array(
        $mapid => $rectangles,
      );
      drupal_add_js(array('getlocations_rectangles' => $rectangle_settings), 'setting');
    }
  }
  // circles
  if ($defaults['circles_enable'] && $defaults['circles_radius'] > 0 && (! empty($defaults['circles_coords']) || $defaults['circles_apply'])) {
    if ($defaults['circles_apply'] && count($latlons)) {
      // get latlons and set coords
      $tmp = '';
      foreach ($latlons AS $ll) {
        $tmp .= $ll[0] . ',' . $ll[1] . "\n";
      }
      if ($tmp) {
        $defaults['circles_coords'] = $tmp;
      }
    }
    $circles = getlocations_get_circle_settings($defaults);
    if ($circles) {
      $circle_settings = array(
        $mapid => $circles,
      );
      drupal_add_js(array('getlocations_circles' => $circle_settings), 'setting');
    }
  }
  // polylines
  if ($defaults['polylines_enable'] && ! empty($defaults['polylines_coords'])) {
    $polylines = getlocations_get_polyline_settings($defaults);
    if ($polylines) {
      $polyline_settings = array(
        $mapid => $polylines,
      );
      drupal_add_js(array('getlocations_polylines' => $polyline_settings), 'setting');
    }
  }
  // getlocations_gps
  if (module_exists('getlocations_gps') && isset($defaults['gps_button']) && $defaults['gps_button']) {
    $getlocations_gps_defaults = getlocations_gps_defaults($defaults);
    getlocations_gps_js_settings_do($getlocations_gps_defaults, $mapid);
  }

}

/**
 * Function to fetch locations
 *
 * @param int $id The entity identifier
 *
 * @return array $locations
 *
 */
function getlocations_load_locations($id, $key = 'vid') {
  $locations = '';
  if (module_exists('getlocations_fields')) {
    $locations = getlocations_fields_load_locations($id, $key);
  }
  elseif (module_exists('location_cck')) {
    $locations = location_load_locations($id, $key);
  }
  elseif (module_exists('geofield')) {
    $locations = getlocations_other_load_locations($id, $key, 'geofield');
  }
  elseif (module_exists('geolocation')) {
    $locations = getlocations_other_load_locations($id, $key, 'geolocation');
  }
  return $locations;
}

/**
 * Function to fetch a location
 *
 * @param int $lid Location Identifier
 *
 * @return array $location
 *
 */
function getlocations_load_location($lid) {

  $getlocations_defaults = getlocations_defaults();
  $location = '';
  if (module_exists('getlocations_fields')) {
    $location = getlocations_fields_load_location($lid);
    $type = getlocations_get_type_from_lid($lid);
    if (! isset($location['marker']) || empty($location['marker'])) {
      $location['marker'] = $getlocations_defaults[$type . '_map_marker'];
    }
  }
  elseif (module_exists('location_cck')) {
    $location = location_load_location($lid);
    $location['marker'] = $getlocations_defaults['node_map_marker'];
  }
  return $location;
}

/**
 * Function to fetch locations. Supports Geofield and Geolocation modules
 *
 * @param int $id Entity identifier
 * @param string $key Entity key
 * @param string $module Module name
 *
 * @return array $locations
 *
 */
function getlocations_other_load_locations($id, $key = 'vid', $module = '') {
  global $language;

  $locations = array();
  if (empty($module)) {
    return $locations;
  }

  if ($key == 'nid') {
    $entity_type = 'node';
    $obj = node_load($id);
    $location_name = $obj->title;
  }
  elseif ($key == 'vid') {
    $entity_type = 'node';
    $obj = node_load(NULL, $id);
    $location_name = $obj->title;
  }
  elseif ($key == 'uid') {
    $entity_type = 'user';
    $obj = user_load($id);
    $location_name = $obj->name;
  }
  elseif ($key == 'tid') {
    $entity_type = 'taxonomy_term';
    $obj = taxonomy_term_load($id);
    $location_name = $obj->name;
  }
  elseif ($key == 'cid') {
    $entity_type = 'comment';
    $obj = comment_load($id);
    $location_name = $obj->subject;
  }
  // get the field_xxx names
  $objfields = array();
  foreach ($obj AS $k => $therest) {
    if (preg_match("/^field_/", $k)) {
      $objfields[] = $k;
    }
  }
  if (empty($objfields)) {
    return $locations;
  }

  // find a geofield
  if ($module == 'geofield') {
    $type = 'geofield';
    $geofields = getlocations_other_get_fieldname($type, $module, $entity_type);
    if (! empty($geofields)) {
      $geofield = '';
      foreach ($objfields AS $field) {
        if (in_array($field, $geofields)) {
          $geofield = $field;
        }
      }
      if ( empty($geofield)) {
        return $locations;
      }
      // got one
      $geo = $obj->$geofield;
      $geo_keys = array_keys($geo);
      foreach ($geo_keys AS $lang) {
        if ($lang == $language->language || (isset($obj->language) && $lang == $obj->language) || $lang == 'und') {
          $ct = 0;
          foreach ($geo[$lang] AS $g) {
            if (isset($g['lat']) && isset($g['lon'])) {
              if ($latlon = getlocations_latlon_check($g['lat'] . ',' . $g['lon'])) {
                $ll = explode(',', $latlon);
                $locations[$ct]['latitude']  = $ll[0];
                $locations[$ct]['longitude'] = $ll[1];
                $locations[$ct][$key] = $id;
                if ($key == 'vid') {
                  $locations[$ct]['nid'] = getlocations_get_nid($id);
                }
                $locations[$ct]['key'] = $key;
                $ct++;
              }
            }
          }
        }
      }
    }
  }
  elseif ($module == 'geolocation') {
    $type = 'geolocation_latlng';
    $geolocationfields = getlocations_other_get_fieldname($type, $module, $entity_type);
    if (! empty($geolocationfields)) {
      $geolocationfield = '';
      foreach ($objfields AS $field) {
        // test for geolocationfields
        if (in_array($field, $geolocationfields)) {
          $geolocationfield = $field;
        }
      }
      if (empty($geolocationfield)) {
        return $locations;
      }
      // got one
      $geo = $obj->$geolocationfield;
      $geo_keys = array_keys($geo);
      foreach ($geo_keys AS $lang) {
        if ($lang == $language->language || (isset($obj->language) && $lang == $obj->language) || $lang == 'und') {
          $ct = 0;
          foreach ($geo[$lang] AS $g) {
            if (isset($g['lat']) && isset($g['lng'])) {
              if ($latlon = getlocations_latlon_check($g['lat'] . ',' . $g['lng'])) {
                $ll = explode(',', $latlon);
                $locations[$ct]['latitude']  = $ll[0];
                $locations[$ct]['longitude'] = $ll[1];
                $locations[$ct][$key] = $id;
                if ($key == 'vid') {
                  $locations[$ct]['nid'] = getlocations_get_nid($id);
                }
                $locations[$ct]['key'] = $key;
                $locations[$ct]['name'] = $location_name;
                $ct++;
              }
            }
          }
        }
      }
    }
  }

  // addressfield
  if (module_exists('addressfield')) {
    // find an addressfield
    $type = 'addressfield';
    $addressfields = getlocations_other_get_fieldname($type, 'addressfield', $entity_type);
    if (! empty($addressfields)) {
      foreach ($objfields AS $field) {
        if (in_array($field, $addressfields)) {
          $addressfield = $field;
        }
      }
      if (empty($addressfield)) {
        return $locations;
      }
      // got one
      $addr = $obj->$addressfield;
      $addr_keys = array_keys($addr);
      foreach ($addr_keys AS $lang) {
        if ($lang == $language->language || (isset($obj->language) && $lang == $obj->language) || $lang == 'und') {
          $ct = 0;
          foreach ($addr[$lang] AS $a) {
            $locations[$ct] += getlocations_addressfield_convert($a);
            $ct++;
          }
        }
      }
    }
  }

  return $locations;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_other_get_fieldname($type, $module, $entity_type = '') {

  $query = db_select('field_config', 'fc');
  $query->fields('fc', array('field_name'))->distinct();
  $query->join('field_config_instance', 'i', 'fc.id = i.field_id');
  $query->condition('fc.module', $module);
  $query->condition('fc.type', $type);
  $query->condition('fc.active', 1);
  $query->condition('fc.storage_active', 1);
  if (! empty($entity_type)) {
    $query->condition('i.entity_type', $entity_type);
  }
  $rows = $query->execute();
  $field_names = array();
  foreach ($rows AS $row) {
    $field_names[$row->field_name] = $row->field_name;
  }
  return $field_names;
}

/**
 * Some form helper functions
 * for admin and views plugin style
 */
/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_marker($title, $options, $default, $description='') {

  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#options' => $options,
    '#default_value' => $default,
  );
  if ($description) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_tf($title, $default, $description='', $size=60, $maxlength=255, $required=FALSE, $weight='') {

  $element = array(
    '#type' => 'textfield',
    '#title' => $title,
    '#default_value' => $default,
    '#size' => $size,
    '#maxlength' => $maxlength,
  );
  if ($required) {
    $element['#required'] = TRUE;
  }
  if ($description) {
    $element['#description'] = $description;
  }
  if (is_numeric($weight)) {
    $element['#weight'] = $weight;
  }

  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_zoom($title, $default, $description='') {

  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#default_value' => $default,
    '#options' => drupal_map_assoc(range(0, 21)),
  );
  if (! empty($description)) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_zoom_map($title, $default, $description='') {

  $opts = array('-1' => t('Use map type settings')) + drupal_map_assoc(range(0, 21));
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#default_value' => $default,
    '#options' => $opts,
  );
  if (! empty($description)) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_zoom_controltype($default, $title = '') {

  if (empty($title)) {
    $title = t('Zoom Control type');
  }
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#options' => array(
      'none' => t('None'),
      'default' => t('Default'),
      'small' => t('Small'),
      'large' => t('Large'),
    ),
    '#default_value' => $default,
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_checkbox($title, $default, $description='') {

  $element = array(
    '#type' => 'checkbox',
    '#title' => $title,
    '#default_value' => $default,
    '#return_value' => 1,
  );
  if (! empty($description)) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_mtc($default) {

  $element = array(
    '#type' => 'select',
    '#title' => t('Map Control Type'),
    '#options' => array(
      'none' => t('None'),
      'standard' => t('Horizontal bar'),
      'menu' => t('Dropdown'),
    ),
    '#default_value' => $default,
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_maptype($default, $baselayers) {
  $options = array();
  $layers = array(
    'Map' => t('Standard street map'),
    'Satellite' => t('Standard satellite map'),
    'Hybrid' => t('Hybrid satellite map'),
    'Physical' => t('Terrain map'),
    'OpenStreetMap' => t('OpenStreet map'),
  );
  foreach ($layers AS $key => $layer) {
    if ($baselayers[$key]) {
      $options[$key] = $layer;
    }
  }
  $element = array(
    '#type' => 'select',
    '#title' => t('Default map type'),
    '#options' => $options,
    '#default_value' => $default,
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_baselayers($view, $default) {
  // Map Satellite Hybrid Physical
  $title = FALSE;
  if ($view == 'Map') {
    $title = t('Standard street map');
    $description = t('The standard default street map.');
  }
  elseif ($view == 'Satellite') {
    $title = t('Standard satellite map');
    $description = t('Satellite view without street overlay.');
  }
  elseif ($view == 'Hybrid') {
    $title = t('Hybrid satellite map');
    $description = t('Satellite view with street overlay.');
  }
  elseif ($view == 'Physical') {
    $title = t('Terrain map');
    $description = t('Map with physical data (terrain, vegetation.)');
  }
  elseif ($view == 'OpenStreetMap') {
    $title = t('OpenStreet map');
    $description = t('Map from the OpenStreetMap Foundation.');
  }
  if ($title) {
    $element = getlocations_element_map_checkbox($title, $default, $description);
    return $element;
  }
  return FALSE;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_pansetting($default) {

  $element = array(
    '#type' => 'select',
    '#title' => t('Automatic Panning'),
    '#default_value' => $default,
    '#options' => array(0 => t('None'), 1 => t('Pan'), 2 => t('Pan and zoom'), 3 => t('Set Center')),
    '#description' => t("'None' is No panning,") . '<br />' . t("'Pan' keeps the markers in the Viewport,") . '<br />' . t("'Pan and zoom' fits the markers to the Viewport,") . '<br />' . t("'Set Center' places the markers in the middle of the map."),
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_markeraction($default) {

  $element = array(
    '#type' => 'select',
    '#title' => t('Marker action'),
    '#default_value' => $default,
    '#options' => array(
      0 => t('None'),
      1 => t('InfoWindow'),
      2 => t('InfoBubble'),
      3 => t('Link')),
    '#description' => t("'None' is No action,") . '<br />' . t("'InfoWindow' show information in a Google InfoWindow,") . '<br />' . t("'InfoBubble' use InfoBubble instead,") . '<br />' . t("'Link' go to a page."),
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_markeractiontype($default) {

  $element = array(
    '#type' => 'select',
    '#title' => t('Marker action type'),
    '#default_value' => $default,
    '#options' => array(
      1 => t('Click'),
      2 => t('Mouse over')),
    '#description' => t("'Click' is clicking on the marker,") . '<br />' . t("'Mouse over' is holding the mouse over a marker."),
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_markermanagertype($default) {

  $element = array(
    '#type' => 'select',
    '#title' => t('Marker Manager type'),
    '#default_value' => $default,
    '#options' => array(
      0 => t('None'),
      2 => t('Marker Clusterer'),
      1 => t('Marker Manager'),
    ),
    '#description' => t('The type of marker management software to load, if any.'),
  );
  return $element;
}


/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_path($title, $default, $size, $maxlength, $description) {
  $element = getlocations_element_map_tf(
    $title,
    $default,
    $description,
    $size,
    $maxlength,
    TRUE
  );
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_map_limits($default, $title = '', $description = '') {

  if (empty($title)) {
    $title = t('Locations to show');
  }
  if (empty($description)) {
    $description = t('The maximum number of locations to show, sorted by distance');
  }
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#description' => $description,
    '#options' => array(0 => t('All'), 10 => '10', 20 => '20', 30 => '30', 40 => '40', 50 => '50', 75 => '75',
      100 => '100', 150 => '150', 175 => '175', 200 => '200', 250 => '250', 300 => '300', 400 => '400', 500 => '500',
    ),
    '#default_value' => $default,
  );

  return $element;

}

/**
 * @param string $default
 * @param string $title
 * @param array $options
 * @param string $description
 * @param bool $multiple
 * @param int $weight
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_dd($title, $default, $options, $description = '', $multiple = FALSE, $weight = '') {

  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#default_value' => $default,
    '#options' => $options,
  );
  if ($description) {
    $element['#description'] = $description;
  }
  if ($multiple) {
    $element['#multiple'] = TRUE;
    $element['#size'] = min(12, count($options));
  }
  if (is_numeric($weight)) {
    $element['#weight'] = $weight;
  }
  return $element;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form
 *
 */
function getlocations_map_display_basics_form($defaults, $labels = array()) {
  $label = array(
    'width' => t('Default width'),
    'height' => t('Default height'),
    'styles' => t('Default styles'),
    'latlong' => t('Map center'),
    'zoom' => t('Zoom'),
    'minzoom_map' => t('Minimum Zoom'),
    'maxzoom_map' => t('Maximum Zoom'),
  );
  if (isset($labels['width'])) {
    $label['width'] = $labels['width'];
  }
  if (isset($labels['height'])) {
    $label['height'] = $labels['height'];
  }
  if (isset($labels['styles'])) {
    $label['styles'] = $labels['styles'];
  }
  if (isset($labels['latlong'])) {
    $label['latlong'] = $labels['latlong'];
  }
  if (isset($labels['zoom'])) {
    $label['zoom'] = $labels['zoom'];
  }
  if (isset($labels['minzoom_map'])) {
    $label['minzoom_map'] = $labels['minzoom_map'];
  }
  if (isset($labels['maxzoom_map'])) {
    $label['maxzoom_map'] = $labels['maxzoom_map'];
  }

  $form = array();
  $form['width'] = getlocations_element_map_tf(
    $label['width'],
    $defaults['width'],
    t('The default width of a Google map, as a CSS length or percentage. Examples: <em>50px</em>, <em>5em</em>, <em>2.5in</em>, <em>95%</em>'),
    10,
    10,
    TRUE
  );

  $form['height'] = getlocations_element_map_tf(
    $label['height'],
    $defaults['height'],
    t('The default height of a Google map, as a CSS length or percentage. Examples: <em>50px</em>, <em>5em</em>, <em>2.5in</em>, <em>95%</em>'),
    10,
    10,
    TRUE
  );

  // map_resize
  $form['map_resize'] = getlocations_element_map_checkbox(
    t('Automatic map resize'),
    $defaults['map_resize'],
    t('Set the map dimensions to 100% if the browser is on a mobile device.')
  );
  // fullscreen_disable
  $form['fullscreen_disable'] = getlocations_element_map_checkbox(
    t('Disable Fullscreen'),
    $defaults['fullscreen_disable'],
    t('Disable the Fullscreen button if the browser is on a mobile device.')
  );

  $form['styles'] = array(
    '#type' => 'textarea',
    '#title' => $label['styles'],
    '#default_value' => $defaults['styles'],
    '#description' => t('The default styles of a Google map. Use !link for generating your styles', array('!link' => l(t('this wizard'), 'http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html', array('external' => TRUE)))),
  );

  $form['latlong'] = getlocations_element_map_tf(
    $label['latlong'],
    $defaults['latlong'],
    t('The default center coordinates of a Google map, expressed as a decimal latitude and longitude, separated by a comma. This must not be 0,0'),
    40,
    50,
    TRUE
  );

  $form['zoom'] = getlocations_element_map_zoom(
    $label['zoom'],
    $defaults['zoom'],
    t('The default zoom level of a Google map.')
  );
  $form['minzoom_map'] = getlocations_element_map_zoom_map(
    $label['minzoom_map'],
    $defaults['minzoom_map'],
    t('The default Minimum zoom level of a Google map.')
  );
  $form['maxzoom_map'] = getlocations_element_map_zoom_map(
    $label['maxzoom_map'],
    $defaults['maxzoom_map'],
    t('The default Maximum zoom level of a Google map.')
  );

  return $form;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns form
 *
 */
function getlocations_map_display_options_form($defaults, $config = TRUE, $extras = TRUE, $source = '') {

  $controlpositions = getlocations_controlpositions();

  $form = array();
  $form['controltype'] = getlocations_element_map_zoom_controltype($defaults['controltype']);
  $form['controltype']['#suffix'] = '<div id="wrap-getlocations-zoomcontrol">';
  $form['zoomcontrolposition'] = getlocations_element_dd(
    t('Position of Zoom Control'),
    $defaults['zoomcontrolposition'],
    $controlpositions
  );
  $form['zoomcontrolposition']['#suffix'] = '</div>';

  $form['pancontrol'] = getlocations_element_map_checkbox(t('Show Pan control'), $defaults['pancontrol']);
  $form['pancontrol']['#suffix'] = '<div id="wrap-getlocations-pancontrol">';
  $form['pancontrolposition'] = getlocations_element_dd(
    t('Position of Pan Control'),
    $defaults['pancontrolposition'],
    $controlpositions
  );
  $form['pancontrolposition']['#suffix'] = '</div>';

  $form['mtc'] = getlocations_element_map_mtc($defaults['mtc']);
  $form['mtc']['#suffix'] = '<div id="wrap-getlocations-mapcontrol">';
  $form['mapcontrolposition'] = getlocations_element_dd(
    t('Position of Map Control'),
    $defaults['mapcontrolposition'],
    $controlpositions
  );
  $form['mapcontrolposition']['#suffix'] = '</div>';

  // a hack to get this in
  if (! isset($defaults['baselayers']['OpenStreetMap'])) {
    $defaults['baselayers']['OpenStreetMap'] = 0;
  }
  // make sure at least one layer is set
  $found = FALSE;
  foreach ($defaults['baselayers'] AS $key => $value) {
    if ($value) {
      $found = TRUE;
    }
  }
  if (! $found) {
    $defaults['baselayers']['Map'] = 1;
    $defaults['maptype'] = 'Map';
  }

  $form['maptype'] = getlocations_element_map_maptype($defaults['maptype'], $defaults['baselayers']);

  $getlocations_defaults = getlocations_defaults();

  $form['baselayers'] =  array(
    '#type' => 'fieldset',
    '#title' => t('Enable map types'),
    '#description' => t('Select which maps you want to be available.'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  );
  foreach ($defaults['baselayers'] AS $key => $value) {
    $layer = getlocations_element_map_baselayers($key, $value);
    if ($layer) {
      $form['baselayers'][$key] = $layer;
    }
  }

  $form['scale'] = getlocations_element_map_checkbox(
    t('Scale'),
    $defaults['scale'],
    t('Show scale.')
  );
  $form['scale']['#suffix'] = '<div id="wrap-getlocations-scale">';
  $form['scalecontrolposition'] = getlocations_element_dd(
    t('Position of Scale Control'),
    $defaults['scalecontrolposition'],
    $controlpositions
  );
  $form['scalecontrolposition']['#suffix'] = '</div>';

  $form['overview'] = getlocations_element_map_checkbox(
    t('Overview map'),
    $defaults['overview'],
    t('Show overview map.')
  );
  $form['overview']['#suffix'] = '<div id="wrap-getlocations-overview">';
  $form['overview_opened'] = getlocations_element_map_checkbox(
    t('Overview map state'),
    $defaults['overview_opened'],
    t('Show overview map as open by default.')
  );
  $form['overview_opened']['#suffix'] = '</div>';

  $form['scrollwheel'] = getlocations_element_map_checkbox(
    t('Scrollwheel'),
    $defaults['scrollwheel'],
    t('Enable scrollwheel zooming.')
  );

  $form['draggable'] = getlocations_element_map_checkbox(
    t('Draggable'),
    $defaults['draggable'],
    t('Enable dragging the map.')
  );

  $form['nokeyboard'] = getlocations_element_map_checkbox(
    t('Disable keyboard shortcuts'),
    $defaults['nokeyboard'],
    t('Enabling this will disable keyboard shortcuts on the map.')
  );
  $form['nodoubleclickzoom'] = getlocations_element_map_checkbox(
    t('Disable Doubleclick zoom'),
    $defaults['nodoubleclickzoom'],
    t('Enabling this will disable doubleclick zooming on the map.')
  );

  $form['map_backgroundcolor'] = getlocations_element_map_tf(
    t('Map background color'),
    $defaults['map_backgroundcolor'],
    t('Can be a color name or HTML hex, eg #FF0000. Leave empty for the default color.'),
    10
  );

  if ($config) {

    $form['region_bias'] = getlocations_element_dd(
      t('Regional bias'),
      $defaults['region_bias'],
      array('' => t('None')) + getlocations_get_countries_list(),
      t('Bias the maps to a particular country')
    );

    // jquery_colorpicker
    if (module_exists('jquery_colorpicker')) {
      $form['jquery_colorpicker_enabled'] = getlocations_element_map_checkbox(
        t('Use jQuery Colorpicker'),
        $defaults['jquery_colorpicker_enabled'],
        t('Use the jQuery Colorpicker for selecting colors.')
      );
    }
    else {
      $form['jquery_colorpicker_enabled'] = array('#type' => 'value', '#value' => 0);
    }

  }

  if ($extras) {

    // getlocations_gps
    if (module_exists('getlocations_gps')) {
      $form += getlocations_gps_map_display_options_form($defaults);

      $form['geolocation_mobile_check'] = array(
        '#type' => 'checkbox',
        '#title' => t('Enable check for mobiles'),
        '#default_value' => $defaults['geolocation_mobile_check'],
        '#return_value' => 1,
        '#description' => t('Enable geolocation for mobile devices only.'),
      );
    }

    $form['sv_show'] = getlocations_element_map_checkbox(
      t('Show streetview Pegman'),
      $defaults['sv_show']
    );
    $form['sv_show']['#suffix'] = '<div id="wrap-getlocations-sv-show">';
    $form['svcontrolposition'] = getlocations_element_dd(
      t('Position of Pegman'),
      $defaults['svcontrolposition'],
      $controlpositions
    );
    $form['svcontrolposition']['#suffix'] = '</div>';

    $form['show_maplinks'] = getlocations_element_map_checkbox(
      t('Show map links'),
      $defaults['show_maplinks'],
      t('Show a list of links to popup InfoWindow/InfoBubble/Link on the map.')
    );

    $form['show_bubble_on_one_marker'] = getlocations_element_map_checkbox(
      t('Show bubble automatically'),
      $defaults['show_bubble_on_one_marker'],
      t('Have the InfoWindow/InfoBubble popup automatically if there is only one marker on the map.')
    );

    $form['fullscreen'] = getlocations_element_map_checkbox(
      t('Show Fullscreen button'),
      $defaults['fullscreen']
    );
    $form['fullscreen']['#suffix'] = '<div id="wrap-getlocations-fs-show">';
    $form['fullscreen_controlposition'] = getlocations_element_dd(
      t('Position of Fullscreen button'),
      $defaults['fullscreen_controlposition'],
      $controlpositions
    );
    $form['fullscreen_controlposition']['#suffix'] = '</div>';

    $form['trafficinfo'] = getlocations_element_map_checkbox(
      t('Enable Traffic information'),
      $defaults['trafficinfo'],
      t('Google Traffic layer, limited availability.')
    );
    $form['trafficinfo']['#suffix'] = '<div id="wrap-getlocations-trafficinfo">';
    $form['trafficinfo_state'] = getlocations_element_map_checkbox(
      t('Activate Traffic information'),
      $defaults['trafficinfo_state'],
      t('Activate Traffic layer when map is first displayed.')
    );
    $form['trafficinfo_state']['#suffix'] = '</div>';

    $form['bicycleinfo'] = getlocations_element_map_checkbox(
      t('Enable Bicycling information'),
      $defaults['bicycleinfo'],
      t('Google Bicycling layer, limited availability.')
    );
    $form['bicycleinfo']['#suffix'] = '<div id="wrap-getlocations-bicycleinfo">';
    $form['bicycleinfo_state'] = getlocations_element_map_checkbox(
      t('Activate Bicycle information'),
      $defaults['bicycleinfo_state'],
      t('Activate Bicycling layer when map is first displayed.')
    );
    $form['bicycleinfo_state']['#suffix'] = '</div>';

    $form['transitinfo'] = getlocations_element_map_checkbox(
      t('Enable Public transport information'),
      $defaults['transitinfo'],
      t('Google Transit layer, limited availability.')
    );
    $form['transitinfo']['#suffix'] = '<div id="wrap-getlocations-transitinfo">';
    $form['transitinfo_state'] = getlocations_element_map_checkbox(
      t('Activate Public transport information'),
      $defaults['transitinfo_state'],
      t('Activate Transit layer when map is first displayed.')
    );
    $form['transitinfo_state']['#suffix'] = '</div>';

    if ($config) {
      $form['panoramio_use'] = getlocations_element_map_checkbox(
        t('Load Panoramio Library'),
        $defaults['panoramio_use'],
        t('Provide Google panoramio library to all maps.')
      );
      $form['panoramio_use']['#suffix'] = '<div id="wrap-getlocations-panoramio-use">';
      $form['panoramio_show'] = getlocations_element_map_checkbox(
        t('Enable Panoramio'),
        $defaults['panoramio_show'],
        t('Google panoramio picture links.')
      );
      $form['panoramio_show']['#suffix'] = '<div id="wrap-getlocations-panoramio">';
      $form['panoramio_state'] = getlocations_element_map_checkbox(
        t('Activate Panoramio'),
        $defaults['panoramio_state'],
        t('Activate Panoramio when map is first displayed.')
      );
      $form['panoramio_state']['#suffix'] = '</div></div>';
    }
    elseif ($getlocations_defaults['panoramio_use']) {
      $form['panoramio_show'] = getlocations_element_map_checkbox(
        t('Enable Panoramio'),
        $defaults['panoramio_show'],
        t('Google panoramio picture links.')
      );
      $form['panoramio_show']['#suffix'] = '<div id="wrap-getlocations-panoramio">';
      $form['panoramio_state'] = getlocations_element_map_checkbox(
        t('Activate Panoramio'),
        $defaults['panoramio_state'],
        t('Activate Panoramio when map is first displayed.')
      );
      $form['panoramio_state']['#suffix'] = '</div>';
    }
    // weather
    if ($config) {
      $form['weather_use'] = getlocations_element_map_checkbox(
        t('Load Weather Library'),
        $defaults['weather_use'],
        t('Provide Google Weather library to all maps.')
      );
      $form['weather_use']['#suffix'] = '<div id="wrap-getlocations-weather-use">';
      $form['weather_show'] = getlocations_element_map_checkbox(
        t('Enable Weather information'),
        $defaults['weather_show'],
        t('Google Weather information.')
      );
      $form['weather_show']['#suffix'] = '<div id="wrap-getlocations-weather">';
      $form['weather_state'] = getlocations_element_map_checkbox(
        t('Activate Weather information'),
        $defaults['weather_state'],
        t('Activate Weather information when map is first displayed.')
      );

      $form['weather_temp'] = getlocations_element_dd(
        t('Temperature units'),
        $defaults['weather_temp'],
        array(1 => t('Celsius'), 2 => t('Fahrenheit'))
      );
      $form['weather_speed'] = getlocations_element_dd(
        t('Windspeed units'),
        $defaults['weather_speed'],
        array(1 => t('Kilometers per hour'), 2 => t('Meters per second'), 3 => t('Miles per hour'))
      );
      $form['weather_label'] = getlocations_element_dd(
        t('Label colour'),
        $defaults['weather_label'],
        array(0 => t('Auto'),  1 => t('Black'), 2 => t('White'))
      );

      $form['weather_clickable'] = getlocations_element_map_checkbox(
        t('Enable clicking on maps'),
        $defaults['weather_clickable']
      );
      $form['weather_info'] = getlocations_element_map_checkbox(
        t('Enable weather InfoWindows'),
        $defaults['weather_info']
      );
      $form['weather_info']['#suffix'] = '</div>';

      $form['weather_cloud'] = getlocations_element_map_checkbox(
        t('Enable Cloud Layer'),
        $defaults['weather_cloud'],
        t('Google Cloud information.')
      );
      $form['weather_cloud']['#suffix'] = '<div id="wrap-getlocations-weather-cloud">';
      $form['weather_cloud_state'] = getlocations_element_map_checkbox(
        t('Activate Cloud Layer'),
        $defaults['weather_cloud_state'],
        t('Activate Cloud layer when map is first displayed.')
      );
      $form['weather_cloud_state']['#suffix'] = '</div></div>';

    }
    elseif ($getlocations_defaults['weather_use']) {
      $form['weather_show'] = getlocations_element_map_checkbox(
        t('Enable Weather information'),
        $defaults['weather_show'],
        t('Google Weather information.')
      );
      $form['weather_show']['#suffix'] = '<div id="wrap-getlocations-weather">';
      $form['weather_state'] = getlocations_element_map_checkbox(
        t('Activate Weather information'),
        $defaults['weather_state'],
        t('Activate Weather information when map is first displayed.')
      );
      $form['weather_state']['#suffix'] = '</div>';

      $form['weather_cloud'] = getlocations_element_map_checkbox(
        t('Enable Cloud Layer'),
        $defaults['weather_cloud'],
        t('Google cloud information.')
      );
      $form['weather_cloud']['#suffix'] = '<div id="wrap-getlocations-weather-cloud">';
      $form['weather_cloud_state'] = getlocations_element_map_checkbox(
        t('Activate Cloud Layer'),
        $defaults['weather_cloud_state'],
        t('Activate Cloud layer when map is first displayed.')
      );
      $form['weather_cloud_state']['#suffix'] = '</div>';

    }

    $form['poi_show'] = getlocations_element_map_checkbox(
      t('Show Points of Interest'),
      $defaults['poi_show'],
      t('Show Google points of interest icons.')
    );
    $form['transit_show'] = getlocations_element_map_checkbox(
      t('Show Transit Points'),
      $defaults['transit_show'],
      t('Show Google transit points icons.')
    );

    $form += getlocations_shapes_form($defaults, $source);

    $form += getlocations_kml_form($defaults);

    $form += getlocations_geojson_form($defaults);

    $form += getlocations_highlight_form($defaults);

    $form += getlocations_google_places_form($defaults, $config);

    if ($config) {
      $form['places'] = array(
        '#type' => 'value',
        '#value' => $defaults['places'],
      );
    }



  }

  return $form;

}

function getlocations_shapes_form($defaults, $source) {
  $form = array();
  $form['polygons_enable'] = getlocations_element_map_checkbox(
    t('Enable polygons'),
    $defaults['polygons_enable'],
    t('Show polygons if defined.')
  );
  $form['polygons_enable']['#suffix'] = '<div id="wrap-getlocations-polygons">';

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['polygons_strokecolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Polygon line color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['polygons_strokecolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['polygons_strokecolor'] = getlocations_element_map_tf(
      t('Polygon line color'),
      $defaults['polygons_strokecolor'],
      t('HTML hex, eg #FF0000.'),
      10,
      10,
      TRUE
    );
  }

  $form['polygons_strokeopacity'] = getlocations_element_map_tf(
    t('Polygon line opacity'),
    $defaults['polygons_strokeopacity'],
    t('Must be between 0 and 1.'),
    10,
    10,
    TRUE
  );
  $form['polygons_strokeweight'] = getlocations_element_map_tf(
    t('Polygon line thickness'),
    $defaults['polygons_strokeweight'],
    t('Must be an integer.'),
    10,
    10,
    TRUE
  );

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['polygons_fillcolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Polygon fill color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['polygons_fillcolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['polygons_fillcolor'] = getlocations_element_map_tf(
      t('Polygon fill color'),
      $defaults['polygons_fillcolor'],
      t('HTML hex, eg #FF0000.'),
      10,
      10,
      TRUE
    );
  }

  $form['polygons_fillopacity'] = getlocations_element_map_tf(
    t('Polygon fill opacity'),
    $defaults['polygons_fillopacity'],
    t('Must be between 0 and 1.'),
    10,
    10,
    TRUE
  );
  $form['polygons_clickable'] = getlocations_element_map_checkbox(
    t('Clickable'),
    $defaults['polygons_clickable'],
    t('Show Popup on clicking on the polygon.')
  );
  $form['polygons_message'] = array(
    '#type' => 'textarea',
    '#title' => t('Popup message'),
    '#default_value' => $defaults['polygons_message'],
    '#description' => t('The content of the popup.'),
  );

  $form['polygons_coords'] = array(
    '#type' => 'textarea',
    '#title' => t('Polygon Coordinates'),
    '#default_value' => $defaults['polygons_coords'],
    '#description' => t('A pipe delimited list of latitude,longitude pairs, one polygon per line. You must have at least 3 pairs for each polygon.'),
  );
  $form['polygons_coords']['#suffix'] = '</div>';

  $form['rectangles_enable'] = getlocations_element_map_checkbox(
    t('Enable rectangles'),
    $defaults['rectangles_enable'],
    t('Show rectangles if defined.')
  );
  $form['rectangles_enable']['#suffix'] = '<div id="wrap-getlocations-rectangles">';

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['rectangles_strokecolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Rectangle line color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['rectangles_strokecolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['rectangles_strokecolor'] = getlocations_element_map_tf(
      t('Rectangle line color'),
      $defaults['rectangles_strokecolor'],
      t('HTML hex, eg #FF0000.'),
      10,
      10,
      TRUE
    );
  }

  $form['rectangles_strokeopacity'] = getlocations_element_map_tf(
    t('Rectangle line opacity'),
    $defaults['rectangles_strokeopacity'],
    t('Must be between 0 and 1.'),
    10,
    10,
    TRUE
  );
  $form['rectangles_strokeweight'] = getlocations_element_map_tf(
    t('Rectangle line thickness'),
    $defaults['rectangles_strokeweight'],
    t('Must be an integer.'),
    10,
    10,
    TRUE
  );

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['rectangles_fillcolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Rectangle fill color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['rectangles_fillcolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['rectangles_fillcolor'] = getlocations_element_map_tf(
      t('Rectangle fill color'),
      $defaults['rectangles_fillcolor'],
      t('HTML hex, eg #FF0000.'),
      10,
      10,
      TRUE
    );
  }

  $form['rectangles_fillopacity'] = getlocations_element_map_tf(
    t('Rectangle fill opacity'),
    $defaults['rectangles_fillopacity'],
    t('Must be between 0 and 1.'),
    10,
    10,
    TRUE
  );
  $form['rectangles_clickable'] = getlocations_element_map_checkbox(
    t('Clickable'),
    $defaults['rectangles_clickable'],
    t('Show Popup on clicking on the rectangle.')
  );
  $form['rectangles_message'] = array(
    '#type' => 'textarea',
    '#title' => t('Popup message'),
    '#default_value' => $defaults['rectangles_message'],
    '#description' => t('The content of the popup.'),
  );

  if ($source == 'getlocations_search') {
    $form['rectangles_apply'] = array('#type' => 'value', '#value' => 0);
    $form['rectangles_dist'] = array('#type' => 'value', '#value' => 0);
  }
  else {
    $form['rectangles_apply'] = getlocations_element_map_checkbox(
      t('Apply a rectangle to all locations'),
      $defaults['rectangles_apply'],
      t('Draw a rectangle centered on all locations being displayed. These coordinates will be used instead of the ones below.')
    );
    $form['rectangles_dist'] = getlocations_element_map_tf(
      t('Rectangle distance'),
      $defaults['rectangles_dist'],
      t("The distance from the center of the rectangle to the edge in meters on the Earth's surface. This will only be used if Apply a rectangle is enabled."),
      10,
      10,
      FALSE
    );
  }

  $form['rectangles_coords'] = array(
    '#type' => 'textarea',
    '#title' => t('Rectangle Coordinates'),
    '#default_value' => $defaults['rectangles_coords'],
    '#description' => t('A pipe delimited list of latitude,longitude pairs, one rectangle per line. You must have exactly 2 pairs for each rectangle, south-west and north-east corners.'),
  );
  $form['rectangles_coords']['#suffix'] = '</div>';

  $form['circles_enable'] = getlocations_element_map_checkbox(
    t('Enable circles'),
    $defaults['circles_enable'],
    t('Show circles if defined.')
  );
  $form['circles_enable']['#suffix'] = '<div id="wrap-getlocations-circles">';

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['circles_strokecolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Circle line color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['circles_strokecolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['circles_strokecolor'] = getlocations_element_map_tf(
      t('Circle line color'),
      $defaults['circles_strokecolor'],
      t('HTML hex, eg #FF0000.'),
      10,
      10,
      TRUE
    );
  }

  $form['circles_strokeopacity'] = getlocations_element_map_tf(
    t('Circle line opacity'),
    $defaults['circles_strokeopacity'],
    t('Must be between 0 and 1.'),
    10,
    10,
    TRUE
  );
  $form['circles_strokeweight'] = getlocations_element_map_tf(
    t('Circle line thickness'),
    $defaults['circles_strokeweight'],
    t('Must be an integer.'),
    10,
    10,
    TRUE
  );

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['circles_fillcolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Circle fill color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['circles_fillcolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['circles_fillcolor'] = getlocations_element_map_tf(
      t('Circle fill color'),
      $defaults['circles_fillcolor'],
      t('HTML hex, eg #FF0000.'),
      10,
      10,
      TRUE
    );
  }

  $form['circles_fillopacity'] = getlocations_element_map_tf(
    t('Circle fill opacity'),
    $defaults['circles_fillopacity'],
    t('Must be between 0 and 1.'),
    10,
    10,
    TRUE
  );
  $form['circles_radius'] = getlocations_element_map_tf(
    t('Circle radius'),
    $defaults['circles_radius'],
    t("The radius in meters on the Earth's surface."),
    10,
    10,
    TRUE
  );
  $form['circles_clickable'] = getlocations_element_map_checkbox(
    t('Clickable'),
    $defaults['circles_clickable'],
    t('Show Popup on clicking on the circle.')
  );
  $form['circles_message'] = array(
    '#type' => 'textarea',
    '#title' => t('Popup message'),
    '#default_value' => $defaults['circles_message'],
    '#description' => t('The content of the popup.'),
  );

  if ($source == 'getlocations_search') {
    $form['circles_apply'] = array('#type' => 'value', '#value' => 0);
  }
  else {
    $form['circles_apply'] = getlocations_element_map_checkbox(
      t('Apply a circle to all locations'),
      $defaults['circles_apply'],
      t('Draw a circle centered on all locations being displayed. These coordinates will be used instead of the ones below.')
    );
  }

  $form['circles_coords'] = array(
    '#type' => 'textarea',
    '#title' => t('Circle Center'),
    '#default_value' => $defaults['circles_coords'],
    '#description' => t('A latitude,longitude pair, one circle per line.'),
  );
  $form['circles_coords']['#suffix'] = '</div>';

  $form['polylines_enable'] = getlocations_element_map_checkbox(
    t('Enable polylines'),
    $defaults['polylines_enable'],
    t('Show polylines if defined.')
  );
  $form['polylines_enable']['#suffix'] = '<div id="wrap-getlocations-polylines">';

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['polylines_strokecolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Polyline line color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['polylines_strokecolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['polylines_strokecolor'] = getlocations_element_map_tf(
      t('Polyline line color'),
      $defaults['polylines_strokecolor'],
      t('HTML hex, eg #FF0000.'),
      10,
      10,
      TRUE
    );
  }

  $form['polylines_strokeopacity'] = getlocations_element_map_tf(
    t('Polyline line opacity'),
    $defaults['polylines_strokeopacity'],
    t('Must be between 0 and 1.'),
    10,
    10,
    TRUE
  );
  $form['polylines_strokeweight'] = getlocations_element_map_tf(
    t('Polyline line thickness'),
    $defaults['polylines_strokeweight'],
    t('Must be an integer.'),
    10,
    10,
    TRUE
  );
  $form['polylines_clickable'] = getlocations_element_map_checkbox(
    t('Clickable'),
    $defaults['polylines_clickable'],
    t('Show Popup on clicking on the polyline.')
  );
  $form['polylines_message'] = array(
    '#type' => 'textarea',
    '#title' => t('Popup message'),
    '#default_value' => $defaults['polylines_message'],
    '#description' => t('The content of the popup.'),
  );

  $form['polylines_coords'] = array(
    '#type' => 'textarea',
    '#title' => t('Polyline Coordinates'),
    '#default_value' => $defaults['polylines_coords'],
    '#description' => t('A pipe delimited list of latitude,longitude pairs, one set of polylines per line. You must have at least 2 pairs for each set.'),
  );
  $form['polylines_coords']['#suffix'] = '</div>';

  return $form;
}

function getlocations_geojson_form($defaults) {
  // geojson

  $form = array();
  if (getlocations_get_geojson_path()) {
    $form['geojson_enable'] = getlocations_element_map_checkbox(
      t('Enable GeoJSON library'),
      $defaults['geojson_enable'],
      t('Show GeoJSON data if defined')
    );
    $form['geojson_enable']['#suffix'] = '<div id="wrap-getlocations-geojson-enable">';
    $form['geojson_data'] = array(
      '#type' => 'textarea',
      '#title' => t('GeoJSON data'),
      '#default_value' => $defaults['geojson_data'],
      '#description' => t('A GeoJSON object. For more information about GeoJSON see !u', array('!u' => l(t('geojson.org'), 'http://www.geojson.org/', array('attributes' => array('target' => '_blank'))))),
    );
    $form['geojson_options'] = array(
      '#type' => 'textarea',
      '#title' => t('GeoJSON options'),
      '#default_value' => $defaults['geojson_options'],
      '#description' => t('A JSON object.'),
    );
    $form['geojson_options']['#suffix'] = '</div>';
  }
  else {
    $form['geojson_enable'] = array('#type' => 'value', '#value' => 0);
    $form['geojson_data'] = array('#type' => 'value', '#value' => '');
    $form['geojson_options'] = array('#type' => 'value', '#value' => '');
  }
  return $form;

}

function getlocations_kml_form($defaults) {
  // KML
  $form = array();
  $form['kml_group'] = array(
    '#type' => 'fieldset',
    '#title' => t('Kml file'),
    '#description' => t('Attach a kml file.'),
    '#collapsible' => TRUE,
    '#collapsed' => (empty($defaults['kml_group']['kml_url']) ? TRUE : FALSE ),
    '#tree' => TRUE,
  );
  $form['kml_group']['kml_url'] = getlocations_element_map_tf(
    t('Kml url'),
    $defaults['kml_group']['kml_url'],
    t('A full url to a publicly accessible kml file.')
  );
  $form['kml_group']['kml_url_click'] = getlocations_element_map_checkbox(
    t('Kml layer clickable'),
    $defaults['kml_group']['kml_url_click']
  );
  $form['kml_group']['kml_url_infowindow'] = getlocations_element_map_checkbox(
    t('Suppress Kml layer InfoWindows'),
    $defaults['kml_group']['kml_url_infowindow']
  );
  $form['kml_group']['kml_url_viewport'] = getlocations_element_map_checkbox(
    t('Preserve viewport'),
    $defaults['kml_group']['kml_url_viewport']
  );
  $form['kml_group']['kml_url_button'] = getlocations_element_map_checkbox(
    t('Show toggle button'),
    $defaults['kml_group']['kml_url_button']
  );
  $form['kml_group']['kml_url_button_label'] = getlocations_element_map_tf(
    t('Label for toggle button'),
    $defaults['kml_group']['kml_url_button_label'],
    '',
    30
  );
  $form['kml_group']['kml_url_button_state'] = getlocations_element_map_checkbox(
    t('Activate Kml layer'),
    $defaults['kml_group']['kml_url_button_state'],
    t('Activate Kml layer when map is first displayed.')
  );

  return $form;
}

function getlocations_highlight_form($defaults) {
  // marker highlighting
  $form = array();
  $form['highlight_enable'] = getlocations_element_map_checkbox(
    t('Enable Marker highlighting'),
    $defaults['highlight_enable'],
    t('Highlight a marker with a circle on mouseover')
  );
  $form['highlight_enable']['#suffix'] = '<div id="wrap-getlocations-highlight">';
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['highlight_strokecolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Highlight Circle line color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['highlight_strokecolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['highlight_strokecolor'] = getlocations_element_map_tf(
      t('Highlight Circle line color'),
      $defaults['highlight_strokecolor'],
      t('HTML hex, eg #FF0000.'),
      10,
      10,
      TRUE
    );
  }

  $form['highlight_strokeopacity'] = getlocations_element_map_tf(
    t('Highlight Circle line opacity'),
    $defaults['highlight_strokeopacity'],
    t('Must be between 0 and 1.'),
    10,
    10,
    TRUE
  );
  $form['highlight_strokeweight'] = getlocations_element_map_tf(
    t('Highlight Circle line thickness'),
    $defaults['highlight_strokeweight'],
    t('Must be an integer.'),
    10,
    10,
    TRUE
  );

  // jquery_colorpicker
  if (module_exists('jquery_colorpicker') && $defaults['jquery_colorpicker_enabled']) {
    $form['highlight_fillcolor'] = array(
      '#type' => 'jquery_colorpicker',
      '#title' => t('Highlight Circle fill color'),
      '#default_value' => preg_replace("/^#/", '', $defaults['highlight_fillcolor']),
      '#description' => t('Click on the Colorpicker icon to select a color'),
    );
  }
  else {
    $form['highlight_fillcolor'] = getlocations_element_map_tf(
      t('Highlight Circle fill color'),
      $defaults['highlight_fillcolor'],
      t('HTML hex, eg #FF0000.'),
      10,
      10,
      TRUE
    );
  }

  $form['highlight_fillopacity'] = getlocations_element_map_tf(
    t('Highlight Circle fill opacity'),
    $defaults['highlight_fillopacity'],
    t('Must be between 0 and 1.'),
    10,
    10,
    TRUE
  );
  $form['highlight_radius'] = getlocations_element_map_tf(
    t('Highlight Circle size'),
    $defaults['highlight_radius'],
    t("The size of the highlight circle, 10 or 20 recommended."),
    5,
    5,
    TRUE
  );
  $form['highlight_radius']['#suffix'] = '</div>';
  return $form;
}

function getlocations_google_places_form($defaults, $config) {
  // search_places
  $form = array();
  // enable
  $desc = t('Provide a textfield to query Google Places Search.');
  if ($config) {
    $desc .= ' ' . t('This will be enabled for all maps if enabled here.');
  }
  $form['search_places'] = getlocations_element_map_checkbox(
    t('Enable Google Places Search'),
    $defaults['search_places'],
    $desc
  );
  $form['search_places']['#suffix'] = '<div id="wrap-getlocations-search-places">';
  // size
  $form['search_places_size'] = getlocations_element_map_tf(
    t('Textbox width'),
    $defaults['search_places_size'],
    t('The width of the Google Places Search textbox. Must be a positive number.'),
    10,
    10,
    TRUE
  );
  // placement
  $pos = array(
    'outside_above' => t('Above the map'),
    'outside_below' => t('Below the map'),
  );
  $form['search_places_position'] = getlocations_element_dd(
    t('Textbox Position'),
    $defaults['search_places_position'],
    $pos,
    t('The position of the Google Places Search textbox.')
  );
  // label
  $form['search_places_label'] = getlocations_element_map_tf(
    t('Textbox label'),
    $defaults['search_places_label'],
    t('The label for the Google Places Search textbox.'),
    30,
    40
  );
  // placeholder
  $form['search_places_placeholder'] = getlocations_element_map_tf(
    t('Text in Textbox'),
    $defaults['search_places_placeholder'],
    t('The text inside the Google Places Search textbox. Leave empty for the default.'),
    30,
    40
  );
  // list
  $form['search_places_list'] = getlocations_element_map_checkbox(
    t('Provide a List of what was found linked to a bubble'),
    $defaults['search_places_list']
  );
  // dropdown
  $form['search_places_dd'] = getlocations_element_map_checkbox(
    t('Provide a Dropdown instead of a Textbox for Google Places Search'),
    $defaults['search_places_dd']
  );
  $form['search_places_dd']['#suffix'] = '</div>';

  return $form;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns array of javascript paths
 *
 */
function getlocations_paths_get($reset = FALSE, $min = FALSE) {
  if ($min) {
    $defaults = array(
      'infobubble_path'                 => GETLOCATIONS_PATH . '/js/infobubble.min.js',
      'infobubble_options_path'         => GETLOCATIONS_PATH . '/js/infobubble_options.js',
      'infobubble_extended_path'        => GETLOCATIONS_PATH . '/js/infobubble_extended.min.js',
      'markermanager_path'              => GETLOCATIONS_PATH . '/js/markermanager_packed.js',
      'markerclusterer_path'            => GETLOCATIONS_PATH . '/js/markerclusterer_packed.js',
      'infowindow_options_path'         => GETLOCATIONS_PATH . '/js/infowindow_options.js',
      'getlocations_path'               => GETLOCATIONS_PATH . '/js/getlocations.min.js',
      'getlocations_polygons_path'      => GETLOCATIONS_PATH . '/js/getlocations_polygons.min.js',
      'getlocations_rectangles_path'    => GETLOCATIONS_PATH . '/js/getlocations_rectangles.min.js',
      'getlocations_circles_path'       => GETLOCATIONS_PATH . '/js/getlocations_circles.min.js',
      'getlocations_polylines_path'     => GETLOCATIONS_PATH . '/js/getlocations_polylines.min.js',
      'getlocations_categories_path'    => GETLOCATIONS_PATH . '/js/getlocations_categories.min.js',
      'getlocations_search_places_path' => GETLOCATIONS_PATH . '/js/getlocations_search_places.min.js',
      'getlocations_geo_path'           => GETLOCATIONS_PATH . '/js/getlocations_geo.min.js',
      'getlocations_preview_path'       => GETLOCATIONS_PATH . '/js/getlocations_preview.min.js',
      'getlocations_geojson_path'       => GETLOCATIONS_PATH . '/js/getlocations_geojson.min.js',
      'getlocations_admin_path'         => GETLOCATIONS_PATH . '/js/getlocations_admin.min.js',
      'getlocations_box_path'           => GETLOCATIONS_PATH . '/js/getlocations_box.min.js',
      'getlocations_colorbox_path'      => GETLOCATIONS_PATH . '/js/getlocations_colorbox.min.js',
      'getlocations_marker_box_path'    => GETLOCATIONS_PATH . '/js/getlocations_marker_box.min.js',
      'getlocations_views_path'         => GETLOCATIONS_PATH . '/js/getlocations_views.min.js',
      'getlocations_icons_path'         => GETLOCATIONS_PATH . '/js/icons.min.js',
    );
  }
  else {
    $defaults = array(
      'infobubble_path'                 => GETLOCATIONS_PATH . '/js/infobubble.js',
      'infobubble_options_path'         => GETLOCATIONS_PATH . '/js/infobubble_options.js',
      'infobubble_extended_path'        => GETLOCATIONS_PATH . '/js/infobubble_extended.js',
      'markermanager_path'              => GETLOCATIONS_PATH . '/js/markermanager.js',
      'markerclusterer_path'            => GETLOCATIONS_PATH . '/js/markerclusterer.js',
      'infowindow_options_path'         => GETLOCATIONS_PATH . '/js/infowindow_options.js',
      'getlocations_path'               => GETLOCATIONS_PATH . '/js/getlocations.js',
      'getlocations_polygons_path'      => GETLOCATIONS_PATH . '/js/getlocations_polygons.js',
      'getlocations_rectangles_path'    => GETLOCATIONS_PATH . '/js/getlocations_rectangles.js',
      'getlocations_circles_path'       => GETLOCATIONS_PATH . '/js/getlocations_circles.js',
      'getlocations_polylines_path'     => GETLOCATIONS_PATH . '/js/getlocations_polylines.js',
      'getlocations_categories_path'    => GETLOCATIONS_PATH . '/js/getlocations_categories.js',
      'getlocations_search_places_path' => GETLOCATIONS_PATH . '/js/getlocations_search_places.js',
      'getlocations_geo_path'           => GETLOCATIONS_PATH . '/js/getlocations_geo.js',
      'getlocations_preview_path'       => GETLOCATIONS_PATH . '/js/getlocations_preview.js',
      'getlocations_geojson_path'       => GETLOCATIONS_PATH . '/js/getlocations_geojson.js',
      'getlocations_admin_path'         => GETLOCATIONS_PATH . '/js/getlocations_admin.js',
      'getlocations_box_path'           => GETLOCATIONS_PATH . '/js/getlocations_box.js',
      'getlocations_colorbox_path'      => GETLOCATIONS_PATH . '/js/getlocations_colorbox.js',
      'getlocations_marker_box_path'    => GETLOCATIONS_PATH . '/js/getlocations_marker_box.js',
      'getlocations_views_path'         => GETLOCATIONS_PATH . '/js/getlocations_views.js',
      'getlocations_icons_path'         => GETLOCATIONS_PATH . '/js/icons.js',
    );

  }

  if ($reset || $min) {
    $getlocations_paths = $defaults;
  }
  else {
    $settings = variable_get('getlocations_paths', $defaults);
    $getlocations_paths = getlocations_adjust_vars($defaults, $settings);
  }

  return $getlocations_paths;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_markerpicker_link($id, $cat, $infoimg='') {
  if (module_exists('colorbox')) {
    $getlocations_colorbox = getlocations_colorbox_settings();
    if ($getlocations_colorbox['marker_enable']) {
      $boxwidth = $getlocations_colorbox['marker_width'];
      $boxheight = $getlocations_colorbox['marker_height'];
      if (empty($infoimg)) {
        $infoimg = '<img class="getlocations_infoimg" src="' . base_path() . GETLOCATIONS_PATH . '/images/info.png' . '" title="' . t('Click here to select an icon from a colorbox') . '" >';
      }
      $link = l($infoimg, 'getlocations/markerinfo', array(
          'attributes' => array(
            'class' => 'colorbox-load',
          ),
          'html' => TRUE,
          'query' => array('width' => $boxwidth, 'height' => $boxheight, 'iframe' => 'true', 'lt' => $id, 'cat' => $cat),
        )
      );
      return $link;
    }
  }
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_colorbox_settings() {
  $colorbox_defaults = array(
    'enable' => 0,
    'width' => 600,
    'height' => 600,
    'marker_enable' => 0,
    'marker_width' => 600,
    'marker_height' => 600,
  );
  $colorbox_settings =  variable_get('getlocations_colorbox', $colorbox_defaults);
  $getlocations_colorbox = getlocations_adjust_vars($colorbox_defaults, $colorbox_settings);
  return $getlocations_colorbox;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_polygon_settings($defaults) {
  $coords = preg_replace("/\r/", '', $defaults['polygons_coords']);
  $coords_arr = preg_split("/\n/", $coords);
  $lla = array();
  $polygons = array();
  $ct = 0;

  if (! preg_match("/^#/",  $defaults['polygons_strokecolor'])) {
    $defaults['polygons_strokecolor'] = '#' . $defaults['polygons_strokecolor'];
  }
  if (! preg_match("/^#/",  $defaults['polygons_fillcolor'])) {
    $defaults['polygons_fillcolor'] = '#' . $defaults['polygons_fillcolor'];
  }

  foreach ($coords_arr AS $line) {
    $lla = array();
    // set defaults

    $polygons['polygons'][$ct]['strokeColor']   = $defaults['polygons_strokecolor'];
    $polygons['polygons'][$ct]['strokeOpacity'] = $defaults['polygons_strokeopacity'];
    $polygons['polygons'][$ct]['strokeWeight']  = $defaults['polygons_strokeweight'];
    $polygons['polygons'][$ct]['fillColor']     = $defaults['polygons_fillcolor'];
    $polygons['polygons'][$ct]['fillOpacity']   = $defaults['polygons_fillopacity'];
    $polygons['polygons'][$ct]['clickable']     = $defaults['polygons_clickable'];
    $polygons['polygons'][$ct]['message']       = $defaults['polygons_message'];

    $linebits = explode("|", $line);
    foreach ($linebits AS $linebit) {
      if ($latlon = getlocations_latlon_check($linebit)) {
        $lla[] = $latlon;
      }
      else {
        // not a latlon so could be a setting
        if (preg_match("/strokeColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['strokeColor'] = trim($m);
        }
        elseif (preg_match("/strokeOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['strokeOpacity'] = trim($m);
        }
        elseif (preg_match("/strokeWeight:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['strokeWeight'] = trim($m);
        }
        elseif (preg_match("/fillColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['fillColor'] = trim($m);
        }
        elseif (preg_match("/fillOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['fillOpacity'] = trim($m);
        }
        elseif (preg_match("/clickable:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['clickable'] = trim($m);
        }
        elseif (preg_match("/message:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polygons['polygons'][$ct]['message'] = trim($m);
        }
      }
    }
    if (count($lla) > 2) {
      $polygons['polygons'][$ct]['coords'] = implode("|", $lla);
    }
    $ct++;
  }
  return $polygons;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_rectangle_settings($defaults) {
  $coords = preg_replace("/\r/", '', $defaults['rectangles_coords']);
  $coords_arr = preg_split("/\n/", $coords);
  $lla = array();
  $rectangles = array();
  $ct = 0;

  if (! preg_match("/^#/",  $defaults['rectangles_strokecolor'])) {
    $defaults['rectangles_strokecolor'] = '#' . $defaults['rectangles_strokecolor'];
  }
  if (! preg_match("/^#/",  $defaults['rectangles_fillcolor'])) {
    $defaults['rectangles_fillcolor'] = '#' . $defaults['rectangles_fillcolor'];
  }

  foreach ($coords_arr AS $line) {
    $lla = array();
    // set defaults
    $rectangles['rectangles'][$ct]['strokeColor']   = $defaults['rectangles_strokecolor'];
    $rectangles['rectangles'][$ct]['strokeOpacity'] = $defaults['rectangles_strokeopacity'];
    $rectangles['rectangles'][$ct]['strokeWeight']  = $defaults['rectangles_strokeweight'];
    $rectangles['rectangles'][$ct]['fillColor']     = $defaults['rectangles_fillcolor'];
    $rectangles['rectangles'][$ct]['fillOpacity']   = $defaults['rectangles_fillopacity'];
    $rectangles['rectangles'][$ct]['clickable']     = $defaults['rectangles_clickable'];
    $rectangles['rectangles'][$ct]['message']       = $defaults['rectangles_message'];

    $linebits = explode("|", $line);
    foreach ($linebits AS $linebit) {
      if ($latlon = getlocations_latlon_check($linebit)) {
        $lla[] = $latlon;
      }
      else {
        // not a latlon so could be a setting
        if (preg_match("/strokeColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['strokeColor'] = trim($m);
        }
        elseif (preg_match("/strokeOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['strokeOpacity'] = trim($m);
        }
        elseif (preg_match("/strokeWeight:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['strokeWeight'] = trim($m);
        }
        elseif (preg_match("/fillColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['fillColor'] = trim($m);
        }
        elseif (preg_match("/fillOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['fillOpacity'] = trim($m);
        }
        elseif (preg_match("/clickable:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['clickable'] = trim($m);
        }
        elseif (preg_match("/message:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $rectangles['rectangles'][$ct]['message'] = trim($m);
        }
      }
    }
    if (count($lla) == 2) {
      $rectangles['rectangles'][$ct]['coords'] = implode("|", $lla);
    }
    $ct++;
  }
  return $rectangles;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_circle_settings($defaults) {
  $coords = preg_replace("/\r/", '', $defaults['circles_coords']);
  $coords_arr = preg_split("/\n/", $coords);
  $lla = array();
  $circles = array();
  $ct = 0;

  if (! preg_match("/^#/",  $defaults['circles_strokecolor'])) {
    $defaults['circles_strokecolor'] = '#' . $defaults['circles_strokecolor'];
  }
  if (! preg_match("/^#/",  $defaults['circles_fillcolor'])) {
    $defaults['circles_fillcolor'] = '#' . $defaults['circles_fillcolor'];
  }

  foreach ($coords_arr AS $line) {
    $lla = array();
    // set defaults
    $circles['circles'][$ct]['strokeColor']   = $defaults['circles_strokecolor'];
    $circles['circles'][$ct]['strokeOpacity'] = $defaults['circles_strokeopacity'];
    $circles['circles'][$ct]['strokeWeight']  = $defaults['circles_strokeweight'];
    $circles['circles'][$ct]['fillColor']     = $defaults['circles_fillcolor'];
    $circles['circles'][$ct]['fillOpacity']   = $defaults['circles_fillopacity'];
    $circles['circles'][$ct]['clickable']     = $defaults['circles_clickable'];
    $circles['circles'][$ct]['message']       = $defaults['circles_message'];
    $circles['circles'][$ct]['radius']        = $defaults['circles_radius'];

    $linebits = explode("|", $line);
    foreach ($linebits AS $linebit) {
      if ($latlon = getlocations_latlon_check($linebit)) {
        $lla[] = $latlon;
      }
      else {
        // not a latlon so could be a setting
        if (preg_match("/strokeColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['strokeColor'] = trim($m);
        }
        elseif (preg_match("/strokeOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['strokeOpacity'] = trim($m);
        }
        elseif (preg_match("/strokeWeight:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['strokeWeight'] = trim($m);
        }
        elseif (preg_match("/fillColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['fillColor'] = trim($m);
        }
        elseif (preg_match("/fillOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['fillOpacity'] = trim($m);
        }
        elseif (preg_match("/clickable:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['clickable'] = trim($m);
        }
        elseif (preg_match("/message:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['message'] = trim($m);
        }
        elseif (preg_match("/radius:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $circles['circles'][$ct]['radius'] = trim($m);
        }
      }
    }
    if (count($lla) == 1) {
      $circles['circles'][$ct]['coords'] = $lla;
    }
    $ct++;
  }
  return $circles;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_polyline_settings($defaults) {
  $coords = preg_replace("/\r/", '', $defaults['polylines_coords']);
  $coords_arr = preg_split("/\n/", $coords);
  $lla = array();
  $polylines = array();
  $ct = 0;

  if (! preg_match("/^#/",  $defaults['polylines_strokecolor'])) {
    $defaults['polylines_strokecolor'] = '#' . $defaults['polylines_strokecolor'];
  }

  foreach ($coords_arr AS $line) {
    $lla = array();
    // set defaults
    $polylines['polylines'][$ct]['strokeColor']   = $defaults['polylines_strokecolor'];
    $polylines['polylines'][$ct]['strokeOpacity'] = $defaults['polylines_strokeopacity'];
    $polylines['polylines'][$ct]['strokeWeight']  = $defaults['polylines_strokeweight'];
    $polylines['polylines'][$ct]['clickable']     = $defaults['polylines_clickable'];
    $polylines['polylines'][$ct]['message']       = $defaults['polylines_message'];

    $linebits = explode("|", $line);
    foreach ($linebits AS $linebit) {
      if ($latlon = getlocations_latlon_check($linebit)) {
        $lla[] = $latlon;
      }
      else {
        // not a latlon so could be a setting
        if (preg_match("/strokeColor:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polylines['polylines'][$ct]['strokeColor'] = trim($m);
        }
        elseif (preg_match("/strokeOpacity:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polylines['polylines'][$ct]['strokeOpacity'] = trim($m);
        }
        elseif (preg_match("/strokeWeight:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polylines['polylines'][$ct]['strokeWeight'] = trim($m);
        }
        elseif (preg_match("/clickable:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polylines['polylines'][$ct]['clickable'] = trim($m);
        }
        elseif (preg_match("/message:(.*)/", $linebit, $match)) {
          $m = $match[1];
          $polylines['polylines'][$ct]['message'] = trim($m);
        }
      }
    }
    if (count($lla) > 1) {
      $polylines['polylines'][$ct]['coords'] = implode("|", $lla);
    }
    $ct++;
  }
  return $polylines;
}

/**
 * Function to get the path to the GeoJSON library
 *
 * @param
 *
 * @return
 *   Returns string or false
 *
 */
function getlocations_get_geojson_path() {
  if ($geojsonpath = libraries_get_path('GeoJSON')) {
    return $geojsonpath . '/GeoJSON.js';
  }
  return FALSE;
}

/**
 * Function to run string through check_plain but then restore apostrophes
 *
 * @param
 *
 * @return
 *   Returns string
 *
 */
function getlocations_apoclean($string) {
  $string = trim($string);
  $string = check_plain($string);
  return htmlspecialchars_decode($string, ENT_QUOTES);
}

/**
 * Recursively merge the defaults with the current settings
 *
 * @param array $defaults
 *
 * @param array $settings
 *
 * @return array The merged settings
 *
 */
function getlocations_adjust_vars($defaults, $settings) {
  $newdefaults = array();
  foreach ($defaults AS $k => $v) {
    if (isset($settings[$k])) {
      if (is_array($v)) {
        $newdefaults[$k] = getlocations_adjust_vars($v, $settings[$k]);
      }
      else {
        $newdefaults[$k] = $settings[$k];
      }
    }
    else {
      $newdefaults[$k] = $v;
    }
  }
  return $newdefaults;
}

/**
 * Fetch fieldnames for a given module and type
 *
 * @param array $module module name
 * @param array $type type name
 *
 * @return array suitable for use in a dropdown.
 */
function getlocations_get_fieldnames($module = 'getlocations_fields', $type = 'getlocations_fields') {

  $field_names = array();
  $query = db_select('field_config', 'f');
  $query->fields('f', array('field_name'));
  $query->join('field_config_instance', 'i', 'f.id=i.field_id');
  $query->condition('f.module', $module)
    ->condition('f.type', $type)
    ->condition('f.active', 1);
  $rows = $query->execute();
  foreach ($rows AS $row) {
    $field_names[$row->field_name] = $row->field_name;
  }
  return $field_names;
}

/**
 * Fetch bundle names for a given module and type
 *
 * @param array $module module name
 * @param array $type type name
 *
 * @return array suitable for use in a dropdown.
 */
function getlocations_get_bundles($module = 'getlocations_fields', $type = 'getlocations_fields') {

  $bundles = array();
  $query = db_select('field_config', 'f');
  $query->fields('i', array('bundle'));
  $query->join('field_config_instance', 'i', 'f.id=i.field_id');
  $query->condition('f.module', $module)
    ->condition('f.type', $type)
    ->condition('f.active', 1);
  $rows = $query->execute();
  foreach ($rows AS $row) {
    $bundles[$row->bundle] = $row->bundle;
  }
  return $bundles;
}

/**
 * Fetch a list of the core Drupal list of countries.
 * from location module
 *
 * @param bool $upper Default uppercase
 *
 * @return array The countries array
 */
function getlocations_get_countries_list($upper = TRUE, $only_continents = '', $only_countries = '') {

  if (module_exists('countries')) {
    $filter = array('enabled' => COUNTRIES_ENABLED);
    if ($only_countries) {
      $only_countries = drupal_strtoupper($only_countries);
      $oc = explode(',', $only_countries);
      if (! empty($oc)) {
        $filter['countries'] = $oc;
      }
    }
    elseif (is_array($only_continents)) {
      $oc = array();
      foreach ($only_continents AS $v) {
        $oc[] = $v;
      }
      if (! empty($oc)) {
        $filter['continents'] = $oc;
      }
    }
    $countries = countries_get_countries('name', $filter);
  }
  else {
    include_once DRUPAL_ROOT . '/includes/locale.inc';
    // Statically cache a version of the core Drupal list of countries
    $countries = &drupal_static(__FUNCTION__);
    if (! isset($countries) || empty($countries)) {
      $countries = country_get_list();
    }
  }
  if (! $upper) {
    $countries = array_change_key_case($countries, CASE_LOWER);
  }

  return $countries;
}

/**
 * Get the full country name
 *
 * @param string $id The two letter iso code of a country
 *
 * @return string Full country name.
 *
 */
function getlocations_get_country_name($id) {
  $countries = getlocations_get_countries_list();
  $id = drupal_strtoupper($id);
  $country = FALSE;
  if (isset($countries[$id])) {
    $country = $countries[$id];
  }
  return $country;
}

/**
 * Get the two letter code for a country
 *
 * @param string $country Full country name.
 *
 * @return string The two letter iso code of a country
 */
function getlocations_get_country_id($country) {
  $id = FALSE;
  $countries = getlocations_get_countries_list();
  foreach ($countries AS $k => $v) {
    if (drupal_strtoupper($country) == drupal_strtoupper($v)) {
      $id = drupal_strtoupper($k);
      break;
    }
  }
  return $id;
}

/**
 * Convert decimal degrees to degrees,minutes,seconds.
 * from location module
 *
 * @param float Decimal degrees
 *
 * @return array degrees,minutes,seconds,sign
 */
function getlocations_dd_to_dms($coord) {
  $negative = ($coord < 0) ? TRUE : FALSE;
  $coord = abs($coord);
  $degrees = floor($coord);
  $coord -= $degrees;
  $coord *= 60;
  $minutes = floor($coord);
  $coord -= $minutes;
  $coord *= 60;
  $seconds = round($coord, 6);
  return array($degrees, $minutes, $seconds, $negative);
}

/**
 * Convert dms string to decimal degrees.
 * Should be reasonably tolerant of sloppy input
 *
 * @param string
 *
 * @return string
 */
function getlocations_dms_to_dd($dms) {
  // If it ends with a word starting with S or W, then it's a negative
  // case insensitive
  $direction = 1;
  preg_match("/\s(\w+)\b$/", $dms, $m);
  if (preg_match("/^s/i", $m[1]) || preg_match("/^w/i", $m[1]) ) {
    $direction = -1;
  }

  $dmsarr = explode(' ', $dms);
  $dmsarr2 = array();
  foreach ($dmsarr AS $v) {
    if ($v) {
      // strip out non-numbers found at the end of the string so we keep '.'
      $tmp = preg_replace("/\D+$/", '', $v);
      $tmp = trim($tmp);
      if ($tmp) {
        $dmsarr2[] = $tmp;
      }
    }
  }
  $dd = FALSE;
  if (count($dmsarr2) == 3) {
    list($degrees, $minutes, $seconds) = $dmsarr2;
    $dd = floatval($degrees + ((($minutes * 60) + ($seconds )) / 3600));
    if ($dd > 0) {
      $dd = $direction * $dd;
    }
  }
  return $dd;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_addressfield_convert($address) {
  $location = theme('getlocations_addressfield_convert', array('address' => $address));
  return $location;
}

/**
 * Make sure a string is a valid css dimension.
 */
/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_dim_check($string) {
  if (!is_string($string) || empty($string)) {
    return FALSE;
  }
  $s = strtolower(trim($string));
  $matches = array();
  if (preg_match('/^([\d.]+)\s*(em|ex|px|in|cm|mm|pt|pc|%)$/', $s, $matches)) {
    return $matches[1] . $matches[2];
  }
  else {
    return FALSE;
  }
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_element_validate_dim($element, &$form_state) {

  $value = FALSE;
  if (isset($element['#value'])) {
    $value = $element['#value'];
  }
  elseif (isset($element['#default_value'])) {
    $value = $element['#default_value'];
  }
  $check = getlocations_dim_check($value);
  if (! $check) {
    form_error($element, t('%name must be valid css.', array('%name' => $element['#title'])));
  }
  else {
    $parents = $element['#parents'];
    // not a good solution
    $tot = count($parents);
    if ($tot == 3) {
      $form_state['values'][$parents[0]][$parents[1]][$parents[2]] = $check;
    }
    elseif ($tot == 5) {
      $form_state['values'][$parents[0]][$parents[1]][$parents[2]][$parents[3]][$parents[4]] = $check;
    }
  }
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_element_validate_latlon($element, &$form_state) {

  $value = FALSE;
  if (isset($element['#value'])) {
    $value = $element['#value'];
  }
  elseif (isset($element['#default_value'])) {
    $value = $element['#default_value'];
  }
  $check = getlocations_latlon_check($value);
  if (! $check) {
    form_error($element, t('%name must be expressed as a decimal latitude and longitude, separated by a comma.', array('%name' => $element['#title'])));
  }
  else {
    $parents = $element['#parents'];
    // not a good solution
    $tot = count($parents);
    if ($tot == 3) {
      $form_state['values'][$parents[0]][$parents[1]][$parents[2]] = $check;
    }
    elseif ($tot == 5) {
      $form_state['values'][$parents[0]][$parents[1]][$parents[2]][$parents[3]][$parents[4]] = $check;
    }
  }
}

/**
 * Calculations functions.
 * from location module
 */

/**
 * License clarification:
 *
 * On Feb 13, 2005, in message <Pine.LNX.4.58.0502131827510.5072@server1.LFW.org>,
 * the creator of these routines, Ka-Ping Yee, authorized these routines to be
 * distributed under the GPL.
 */

/**
 * @file
 * Trigonometry for calculating geographical distances.
 * All function arguments and return values measure distances in metres
 * and angles in degrees.  The ellipsoid model is from the WGS-84 datum.
 * Ka-Ping Yee, 2003-08-11
 */

// This library is an original implementation of UCB CS graduate student, Ka-Ping Yee (http://www.zesty.ca).

define('GETLOCATIONS_EARTH_RADIUS_SEMIMAJOR', 6378137.0);
define('GETLOCATIONS_EARTH_FLATTENING', (1/298.257223563));
define('GETLOCATIONS_EARTH_RADIUS_SEMIMINOR', (6378137.0*(1-(1/298.257223563))));
define('GETLOCATIONS_EARTH_ECCENTRICITY_SQ', (2*(1/298.257223563)-pow((1/298.257223563), 2)));


// Default latitude halfway between north pole and equator
function getlocations_earth_radius($latitude=45) {
  // Estimate the Earth's radius at a given latitude.
  $lat = deg2rad($latitude);
  $x = (cos($lat) / GETLOCATIONS_EARTH_RADIUS_SEMIMAJOR);
  $y = (sin($lat) / GETLOCATIONS_EARTH_RADIUS_SEMIMINOR);
  $return = (1 / (sqrt($x * $x + $y * $y)));
  return $return;
}

/**
 * Returns the SQL fragment needed to add a column called 'distance' to a query. For use in Views distance/proximity calculations
 *
 * @param $latitude    The measurement point
 * @param $longitude   The measurement point
 * @param $tbl_alias   If necessary, the alias name. Used by SQL to clearly identify a field.
 */
function getlocations_earth_distance_sql($latitude, $longitude, $tbl_alias = '') {
  // Make a SQL expression that estimates the distance to the given location.
  $radius = getlocations_earth_radius($latitude);

  // If the table alias is specified, add on the separator.
  $tbl_alias = (empty($tbl_alias) ? '' : $tbl_alias . '.');

  $latfield = $tbl_alias . 'latitude';
  $lonfield = $tbl_alias . 'longitude';

  // all calcs in mysql
  #$sql = "(IFNULL(ACOS(COS(RADIANS($latitude)) * COS(RADIANS($latfield)) * (COS(RADIANS($longitude)) * COS(RADIANS($lonfield)) + SIN(RADIANS($longitude)) * SIN(RADIANS($lonfield))) + SIN(RADIANS($latitude)) * SIN(RADIANS($latfield))), 0.00000) * $radius)";
  // some calcs predone in php
  $long = deg2rad($longitude);
  $lat = deg2rad($latitude);
  $coslong = cos($long);
  $coslat = cos($lat);
  $sinlong = sin($long);
  $sinlat = sin($lat);
  $sql = "(IFNULL(ACOS($coslat * COS(RADIANS($latfield)) * ($coslong*COS(RADIANS($lonfield)) + $sinlong * SIN(RADIANS($lonfield))) + $sinlat * SIN(RADIANS($latfield))), 0.00000) * $radius)";

  return $sql;
}

/**
 * @param float $longitude1
 *
 * @param float $latitude1
 *
 * @param float $longitude2
 *
 * @param float $latitude2
 *
 * @return
 *   Returns distance in meters
 *
 */
function getlocations_earth_distance($longitude1, $latitude1, $longitude2, $latitude2) {
  $longitude1 = floatval($longitude1);
  $latitude1 = floatval($latitude1);
  $longitude2 = floatval($longitude2);
  $latitude2 = floatval($latitude2);

  // Estimate the earth-surface distance between two locations.
  $long1 = deg2rad($longitude1);
  $lat1 = deg2rad($latitude1);
  $long2 = deg2rad($longitude2);
  $lat2 = deg2rad($latitude2);
  $radius = getlocations_earth_radius(($latitude1 + $latitude2) / 2);
  $cosangle = cos($lat1) * cos($lat2) * (cos($long1) * cos($long2) + sin($long1) * sin($long2)) + sin($lat1) * sin($lat2);
  return acos($cosangle) * $radius;
}

/**
 * This function uses earth_asin_safe so is not accurate for all possible
 *   parameter combinations. This means this function doesn't work properly
 *   for high distance values. This function needs to be re-written to work properly for
 *   larger distance values. See http://drupal.org/node/821628
 *
 * http://drupal.org/node/471040 provides a fix, this has been applied here.
 *
 */
function getlocations_earth_longitude_range($latitude, $longitude, $distance) {
  // Estimate the min and max longitudes within $distance of a given location.
  if (! $distance > 0) {
    $distance = 1;
  }
  $long = deg2rad($longitude);
  $lat = deg2rad($latitude);
  $radius = getlocations_earth_radius($latitude) * cos($lat);

  if ($radius > 0) {
    $angle = abs($distance / $radius );
    $angle = min($angle, pi());
  }
  else {
    $angle = pi();
  }
  $minlong = $long - $angle;
  $maxlong = $long + $angle;
  if ($minlong < -pi()) {
    $minlong = $minlong + pi()*2;
  }
  if ($maxlong > pi()) {
    $maxlong = $maxlong - pi()*2;
  }
  return array(rad2deg($minlong), rad2deg($maxlong));
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_earth_latitude_range($latitude, $longitude, $distance) {
  // Estimate the min and max latitudes within $distance of a given location.
  $long = deg2rad($longitude);
  $lat = deg2rad($latitude);
  $radius = getlocations_earth_radius($latitude);

  $angle = $distance / $radius;
  $minlat = $lat - $angle;
  $maxlat = $lat + $angle;
  $rightangle = pi()/2;
  if ($minlat < -$rightangle) { // wrapped around the south pole
    $overshoot = -$minlat - $rightangle;
    $minlat = -$rightangle + $overshoot;
    if ($minlat > $maxlat) {
      $maxlat = $minlat;
    }
    $minlat = -$rightangle;
  }
  if ($maxlat > $rightangle) { // wrapped around the north pole
    $overshoot = $maxlat - $rightangle;
    $maxlat = $rightangle - $overshoot;
    if ($maxlat < $minlat) {
      $minlat = $maxlat;
    }
    $maxlat = $rightangle;
  }
  return array(rad2deg($minlat), rad2deg($maxlat));
}

/**
 * This is a helper function to avoid errors when using the asin() PHP function.
 * asin is only real for values between -1 and 1.
 * If a value outside that range is given it returns NAN (not a number), which
 * we don't want to happen.
 * So this just rounds values outside this range to -1 or 1 first.
 *
 * This means that calculations done using this function with $x outside the range
 * will not be accurate.  The alternative though is getting NAN, which is an error
 * and won't give accurate results anyway.
 */
#function getlocations_earth_asin_safe($x) {
#  return asin(max(-1, min($x, 1)));
#}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_search_distance_sql($latitude, $longitude, $searchdistance, $tbl_alias = '') {
  $radius = getlocations_earth_radius($latitude);
  $tbl_alias = empty($tbl_alias) ? $tbl_alias : ($tbl_alias . '.');
  $latfield = $tbl_alias . 'latitude';
  $lonfield = $tbl_alias . 'longitude';

  // all calcs in mysql
  #$sql = "(IFNULL(ACOS((SIN(RADIANS($latitude)) * SIN(RADIANS($latfield)) + (COS(RADIANS($latitude)) * COS(RADIANS($latfield)) * COS(RADIANS($lonfield) - RADIANS($longitude))))), 0.00000) * $radius) BETWEEN 0 AND $searchdistance ";
  // some calcs predone in php
  $lat = deg2rad($latitude);
  $long = deg2rad($longitude);
  #$coslong = cos($long);
  $coslat = cos($lat);
  #$sinlong = sin($long);
  $sinlat = sin($lat);
  $sql = "(IFNULL(ACOS(($sinlat * SIN(RADIANS($latfield)) + ($coslat * COS(RADIANS($latfield)) * COS(RADIANS($lonfield) - $long )))), 0.00000) * $radius)";
  if ($searchdistance > 0) {
    $sql .= " BETWEEN 0 AND $searchdistance";
  }

  return $sql;
}


/**
 * @param $distance
 *   A number in either kilometers, meters, miles, yards or nautical miles.
 *
 * @param $distance_unit
 *   String (optional). in either kilometers (km), meters (m), miles (mi), yards (yd) or nautical miles (nmi).
 *
 * @return
 *   A floating point number where the number in meters after the initially passed scalar has been round()'d
 */
function getlocations_convert_distance_to_meters($distance, $distance_unit = 'km') {
  if (!is_numeric($distance) || ! $distance > 0) {
    return NULL;
  }
  $units = array(
    'km'  => 1000.0,
    'm'   => 1.0,
    'mi'  => 1609.344,
    'yd'  => 0.9144,
    'nmi' => 1852.0
  );
  if (! in_array($distance_unit, array_keys($units))) {
    $distance_unit = 'km';
  }
  $conv = $units[$distance_unit];
  // Convert distance to meters
  $retval = round(floatval($distance) * $conv, 2);
  return $retval;
}

/**
 * @param $meters
 *   The distance in meters.
 *
 * @param $distance_unit
 *   String (optional). in either kilometers (km), meters (m), miles (mi), yards (yd) or nautical miles (nmi).
 *
 * @return
 *   A floating point number where the converted number has been round()'d
 */
function getlocations_convert_meters_to_distance($meters, $distance_unit = 'km') {
  if (!is_numeric($meters) || ! $meters > 0) {
    return NULL;
  }
  $units = array(
    'km'  => 0.001,
    'm'   => 1.0,
    'mi'  => 0.000621371,
    'yd'  => 1.093613298,
    'nmi' => 0.000539957
  );
  if (! in_array($distance_unit, array_keys($units))) {
    $distance_unit = 'km';
  }
  $conv = $units[$distance_unit];
  // Convert meters to display units. formatting in theme_getlocations_fields_distance();
  $retval = ($meters * $conv);
  return $retval;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_unit_names($unit = '', $type = 'plural') {
  $units_plural = array(
    'km'  => t('Kilometers'),
    'm'   => t('Meters'),
    'mi'  => t('Miles'),
    'yd'  => t('Yards'),
    'nmi' => t('Nautical miles'),
  );
  $units_plurals = array(
    'km'  => t('Kilometer(s)'),
    'm'   => t('Meter(s)'),
    'mi'  => t('Mile(s)'),
    'yd'  => t('Yard(s)'),
    'nmi' => t('Nautical mile(s)'),
  );
  $units = array(
    'km'  => t('Kilometer'),
    'm'   => t('Meter'),
    'mi'  => t('Mile'),
    'yd'  => t('Yard'),
    'nmi' => t('Nautical mile'),
  );
  // for dropdown
  $return = FALSE;
  if (empty($unit)) {
    if ($type == 'plural') {
      $return = $units_plural;
    }
    elseif ($type == 'plurals') {
      $return = $units_plurals;
    }
    else {
      $return = $units;
    }
  }
  else {
    // if $unit is supplied, return display name
    if (! in_array($unit, array_keys($units))) {
      $unit = 'km';
    }
    if ($type == 'plural') {
      $return = $units_plural[$unit];
    }
    elseif ($type == 'plurals') {
      $return = $units_plurals[$unit];
    }
    else {
      $return = $units[$unit];
    }
  }
  return $return;
}

// form elements
/**
 * @param string $default
 * @param string $title
 * @param string $description
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_distance_unit($default, $title = '', $description = '') {
  if (empty($title)) {
    $title = t('Units');
  }
  $units = getlocations_get_unit_names();
  $element = array(
    '#type' => 'select',
    '#title' => $title,
    '#options' => $units,
    '#default_value' => $default,
  );
  if (! empty($description)) {
    $element['#description'] = $description;
  }
  return $element;

}

/**
 * @param string $default
 * @param string $title
 * @param string $description
 *
 * @return
 *   Returns form element
 *
 */
function getlocations_element_search_distance($default, $title = '', $description = '') {
  if (empty($title)) {
    $title = t('Distance');
  }
  $element = array(
    '#type' => 'textfield',
    '#title' => $title,
    '#default_value' => $default,
    '#size' => 10,
    '#required' => TRUE,
  );
  if (! empty($description)) {
    $element['#description'] = $description;
  }
  return $element;
}

/**
 * Normalizes a latitude to the [-90,90] range. Latitudes above 90 or
 * below -90 are capped, not wrapped.
 * @param {Number} lat The latitude to normalize, in degrees.
 * @type Number
 * @return Returns the latitude, fit within the [-90,90] range.
 */
function getlocations_normalizelat($lat) {
  return max(-90, min(90, $lat));
}

/**
 * Normalizes a longitude to the [-180,180] range. Longitudes above 180
 * or below -180 are wrapped.
 * @param {Number} lng The longitude to normalize, in degrees.
 * @type Number
 * @return Returns the longitude, fit within the [-180,180] range.
 */
function getlocations_normalizelng($lng) {
  if ($lng % 360 == 180) {
      return 180;
    }
    while ($lng > 180) {
      $lng -= 360;
    }
    while ($lng < -180) {
      $lng += 360;
    }
    return $lng;
}

/**
 * Function
 *
 * @param bool $override
 *
 * @return
 *   Returns TRUE if user agent says its a mobile device
 *
 */
function getlocations_is_mobile($override = FALSE) {
  if ($override) {
    return TRUE;
  }
  $getlocations_ua = getlocations_ua_get();
  $str = "/" . $getlocations_ua['ua_string'] . "/i";
  $is_mobile = FALSE;
  $ua = $_SERVER['HTTP_USER_AGENT'];
  if (preg_match($str, $ua)) {
    $is_mobile = TRUE;
  }
  return $is_mobile;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_ua_get() {
  $default = array('ua_string' => "iphone|ipad|android|blackberry|blazer|bolt|symbian|mobile safari|fennec|gobrowser|iemobile|maemo browser|profile midp|minimo|kindle|opera mini|opera mobi|skyfire|teashark|uzardweb");
  $getlocations_ua = variable_get('getlocations_ua', $default);
  return $getlocations_ua;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_aggr_get() {
  $getlocations_aggr = variable_get('getlocations_aggr', 1);
  return $getlocations_aggr;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_term_marker($nid, $marker) {
  $getlocations_defaults = getlocations_defaults();
  // term markers
  $getlocations_term_marker = variable_get('getlocations_term_marker', array('enable' => 0, 'vids' => 0, 'max_depth' => ''));
  if ($getlocations_term_marker['enable'] && $getlocations_term_marker['vids']) {
    $vids = $getlocations_term_marker['vids'];
    foreach ($vids AS $vid) {
      $results = db_query('SELECT i.tid FROM {taxonomy_index} i JOIN {taxonomy_term_data} d ON i.tid=d.tid WHERE i.nid = :nid AND d.vid =:vid', array(':nid' => $nid, ':vid' => $vid));
      $record = $results->fetchObject();
      if ($record) {
        $marker = (isset($getlocations_term_marker['vid'][$vid]['term'][$record->tid]['map_marker']) ? $getlocations_term_marker['vid'][$vid]['term'][$record->tid]['map_marker'] : $getlocations_defaults['term_map_marker']);
      }
    }
  }
  return $marker;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_supported_modules() {
  return array(
    'getlocations_fields',
    'geofield',
    'geolocation',
    'location_cck'
  );
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_get_current_supported_module() {
  $modules = getlocations_supported_modules();
  foreach ($modules AS $module) {
    if (module_exists($module)) {
      return $module;
    }
  }
  return FALSE;
}

/**
 * Function
 *
 * @param
 *
 * @return
 *   Returns
 *
 */
function getlocations_controlpositions($dd = TRUE) {
    if ($dd) {
      $controlpositions = array(
        ''   => t('Default'),
        'tl' => t('Top Left'),
        'tc' => t('Top Center'),
        'tr' => t('Top Right'),
        'rt' => t('Right Top'),
        'rc' => t('Right Center'),
        'rb' => t('Right Bottom'),
        'br' => t('Bottom Right'),
        'bc' => t('Bottom Center'),
        'bl' => t('Bottom Left'),
        'lb' => t('Left Bottom'),
        'lc' => t('Left Center'),
        'lt' => t('Left Top'),
      );
    }
    else {
      $controlpositions = array('tl', 'tc', 'tr', 'rt', 'rc', 'rb', 'br', 'bc', 'bl', 'lb', 'lc', 'lt');
    }
    return $controlpositions;
}

/**
 * Allows for aliases in entity types
 *
 */
function getlocations_get_entity_type_from_path($path) {
  $entity_type = $path;
  // getlocations path => entity_type
  $aliases = array(
    'term' => 'taxonomy_term',
  );
  if (isset($aliases[$path])) {
    $entity_type = $aliases[$path];
  }

  return $entity_type;
}

/**
 * Given two points in lat/lon form, returns the distance between them.
 * @param $latlon_a
 *   An associative array where
 *      'lon' => is a floating point of the longitude coordinate for the point given by latlonA
 *      'lat' => is a floating point of the latitude coordinate for the point given by latlonB
 * @param $latlon_b
 *      Another point formatted like $latlon_b
 * @param $distance_unit
 *      A string that is one of 'km', 'm', 'mi', 'yd', 'nmi'.
 *      Defaults to 'km'
 * @return
 *    NULL if sense can't be made of the parameters.
 *    An associative array where
 *      'scalar' => Is the distance between the two lat/lon parameter points
 *      'distance_unit' => Is the unit of distance being represented by 'scalar'.
 *
 */
function getlocations_distance_between($latlon_a = array(), $latlon_b = array(), $distance_unit = 'km') {
  if (!isset($latlon_a['lon']) || !isset($latlon_a['lat']) || !isset($latlon_b['lon']) || !isset($latlon_b['lat'])) {
    return NULL;
  }

  $meters = getlocations_earth_distance($latlon_a['lon'], $latlon_a['lat'], $latlon_b['lon'], $latlon_b['lat']);
  $distance = getlocations_convert_meters_to_distance($meters, $distance_unit);
  return array('scalar' => $distance, 'distance_unit' => $distance_unit);
}


/***********************************************************/
// these functions currently not in use
function getlocations_earth_xyz($longitude, $latitude, $height = 0) {
  // Convert longitude and latitude to earth-centered earth-fixed coordinates.
  // X axis is 0 long, 0 lat; Y axis is 90 deg E; Z axis is north pole.

  $long = deg2rad($longitude);
  $lat = deg2rad($latitude);

  $coslong = cos($long);
  $coslat = cos($lat);
  $sinlong = sin($long);
  $sinlat = sin($lat);
  $radius = (GETLOCATIONS_EARTH_RADIUS_SEMIMAJOR / sqrt(1 - GETLOCATIONS_EARTH_ECCENTRICITY_SQ * $sinlat * $sinlat));
  $x = ($radius + $height) * $coslat * $coslong;
  $y = ($radius + $height) * $coslat * $sinlong;
  $z = (($radius * (1 - GETLOCATIONS_EARTH_ECCENTRICITY_SQ ) + $height) * $sinlat);
  return array($x, $y, $z);
}

function getlocations_earth_arclength($angle, $latitude=37.9) {
  // Convert a given angle to earth-surface distance.
  return deg2rad($angle) * getlocations_earth_radius($latitude);
}

function getlocations_get_exact_distance_sql($latitude, $longitude, $tbl_alias = '') {
  $radius = getlocations_earth_radius($latitude);
  $tbl_alias = empty($tbl_alias) ? $tbl_alias : ($tbl_alias . '.');
  $latfield = $tbl_alias . 'latitude';
  $lonfield = $tbl_alias . 'longitude';

  // all calcs in mysql
  #$sql = "(IFNULL(ACOS((SIN(RADIANS($latitude)) * SIN(RADIANS($latfield))) + (COS(RADIANS($latitude)) * COS(RADIANS($latfield)) * COS(RADIANS($longitude - $lonfield)))), 0.00000) * $radius)";
  // some calcs predone in php
  $lat = deg2rad($latitude);
  $long = deg2rad($longitude);
  #$coslong = cos($long);
  $coslat = cos($lat);
  #$sinlong = sin($long);
  $sinlat = sin($lat);
  $sql = "(IFNULL(ACOS(($sinlat * SIN(RADIANS($latfield))) + ($coslat * COS(RADIANS($latfield)) * COS(RADIANS($longitude - $lonfield)))), 0.00000) * $radius)";
  return $sql;
}

// Theming functions

/**
 * Implements hook_theme().
 *
 * This lets us tell Drupal about our theme functions and their arguments.
 */
function getlocations_theme() {
  return array(
    'getlocations_show' => array(
      'variables' => array(
        'width' => '',
        'height' => '',
        'defaults' => '',
        'mapid' => '',
        'latlons' => '',
        'minmaxes' => '',
        'type' => '',
        'node' => '',
      ),
    ),
    'getlocations_adinfo' => array(
      'variables' => array(
        'location' => NULL,
      ),
    ),
    'getlocations_box' => array(
      'variables' => array(
        'content' => NULL,
      ),
      'template' => 'getlocations_box',
    ),
    'getlocations_marker_box' => array(
      'variables' => array(
        'content' => NULL,
      ),
      'template' => 'getlocations_marker_box',
    ),
    'getlocations_settings_form' => array(
      'render element' => 'form',
    ),
    'getlocations_plugin_style_map_options_form' => array(
      'render element' => 'form',
    ),
    'getlocations_plugin_style_streetview_options_form' => array(
      'render element' => 'form',
    ),
    'getlocations_latitude_dms' => array(
      'variables' => array(
        'latitude' => '',
      ),
    ),
    'getlocations_longitude_dms' => array(
      'variables' => array(
        'longitude' => '',
      ),
    ),
    'getlocations_addressfield_convert' => array(
      'variables' => array(
        'address' => array(),
      ),
    ),
    'getlocations_lidinfo' => array(
      'variables' =>array(
        'lid' => '',
        'lidkey' => '',
      ),
    ),
  );
}

/**
 * Returns HTML for a map.
 *
 * All the map displays pass through here.
 *
 * @param array $variables
 *   An associative array containing:
 *   - width: The width of the map.
 *   - height: The height of the map.
 *   - defaults: The settings to be applied to the map, links, buttons and form elements.
 *   - mapid: The unique identifier for the map.
 *   - type: The entity type, eg node, user, term or comment.
 *   - node: The entity object.
 *
 * @return string $output
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_show($variables) {
  $width = $variables['width'];
  $height = $variables['height'];
  $defaults = $variables['defaults'];
  $mapid = $variables['mapid'];
  $type = $variables['type'];
  $node = $variables['node'];

  $latlons = $variables['latlons'];
  $minmaxes = $variables['minmaxes'];
  $datanum = count($latlons);

  $output = '';
  $returnlink = FALSE;
  // return link
  if ($type == 'node' && $defaults['returnlink_page_enable']) {
    if (is_object($node)) {
      $linktext = $defaults['returnlink_page_link'];
      if ( preg_match("/%t/", $linktext)) {
        $linktext = preg_replace("/%t/", $node->title, $linktext);
      }
      $l = l($linktext, 'node/' . $node->nid);
      $returnlink = '<div class="getlocations_returnlink">' . $l . '</div>';
    }
  }
  elseif ($type == 'user' && $defaults['returnlink_user_enable']) {
    if (is_object($node)) {
      $linktext = $defaults['returnlink_user_link'];
      if ( preg_match("/%n/", $linktext)) {
        $linktext = preg_replace("/%n/", $node->name, $linktext);
      }
      $l = l($linktext, 'user/' . $node->uid);
      $returnlink = '<div class="getlocations_returnlink">' . $l . '</div>';
    }
  }
  elseif ($type == 'term' && $defaults['returnlink_term_enable'] && module_exists('taxonomy')) {
    if (is_object($node)) {
      $linktext = $defaults['returnlink_term_link'];
      if ( preg_match("/%n/", $linktext)) {
        $linktext = preg_replace("/%n/", $node->name, $linktext);
      }
      $l = l($linktext, 'taxonomy/term/' . $node->tid);
      $returnlink = '<div class="getlocations_returnlink">' . $l . '</div>';
    }
  }
  elseif ($type == 'comment' && $defaults['returnlink_comment_enable'] && module_exists('comment')) {
    if (is_object($node)) {
      $linktext = $defaults['returnlink_comment_link'];
      if ( preg_match("/%n/", $linktext)) {
        $linktext = preg_replace("/%n/", $node->subject, $linktext);
      }
      $l = l($linktext, 'comment/' . $node->cid);
      $returnlink = '<div class="getlocations_returnlink">' . $l . '</div>';
    }
  }
  if ($returnlink) {
    $output .= $returnlink;
  }

  if ($defaults['map_resize'] && getlocations_is_mobile()) {
    $width = '100%';
    #$height = '100%';
  }

  // show maplinks if enabled
  if ($defaults['show_maplinks']) {
    $output .= '<a id="maptop_' . $mapid . '" name="maptop_' . $mapid . '"></a>';
  }
  // search_places
  $sp = '';
  if ($defaults['search_places']) {

    $sp .= '<div class="search_places_input_wrapper">';
    if ($defaults['search_places_label']) {
      $sp .= '<label for="search_places_select_' . $mapid . '">' . $defaults['search_places_label'] . '</label>';
    }

    if ($defaults['search_places_dd']) {
      // alternative dropdown
      $sp_opts = array(
      'accounting'              => t('Accounting'),
      'airport'                 => t('Airport'),
      'amusement_park'          => t('Amusement park'),
      'aquarium'                => t('Aquarium'),
      'art_gallery'             => t('Art gallery'),
      'atm'                     => t('ATM'),
      'bakery'                  => t('Bakery'),
      'bank'                    => t('Bank'),
      'bar'                     => t('Bar'),
      'beauty_salon'            => t('Beauty salon'),
      'bicycle_store'           => t('Bicycle store'),
      'book_store'              => t('Book store'),
      'bowling_alley'           => t('Bowling alley'),
      'bus_station'             => t('Bus station'),
      'cafe'                    => t('Cafe'),
      'campground'              => t('Campground'),
      'car_dealer'              => t('Car dealer'),
      'car_rental'              => t('Car rental'),
      'car_repair'              => t('Car repair'),
      'car_wash'                => t('Car wash'),
      'casino'                  => t('Casino'),
      'cemetery'                => t('Cemetery'),
      'church'                  => t('Church'),
      'city_hall'               => t('City hall'),
      'clothing_store'          => t('Clothing store'),
      'convenience_store'       => t('Convenience store'),
      'courthouse'              => t('Courthouse'),
      'dentist'                 => t('Dentist'),
      'department_store'        => t('Department store'),
      'doctor'                  => t('Doctor'),
      'electrician'             => t('Electrician'),
      'electronics_store'       => t('Electronics store'),
      'embassy'                 => t('Embassy'),
      'establishment'           => t('Establishment'),
      'finance'                 => t('Finance'),
      'fire_station'            => t('Fire station'),
      'florist'                 => t('Florist'),
      'food'                    => t('Food'),
      'funeral_home'            => t('Funeral home'),
      'furniture_store'         => t('Furniture store'),
      'gas_station'             => t('Gas station'),
      'general_contractor'      => t('General contractor'),
      'grocery_or_supermarket'  => t('Grocery or supermarket'),
      'gym'                     => t('Gym'),
      'hair_care'               => t('Hair care'),
      'hardware_store'          => t('Hardware store'),
      'health'                  => t('Health'),
      'hindu_temple'            => t('Hindu temple'),
      'home_goods_store'        => t('Home goods store'),
      'hospital'                => t('Hospital'),
      'insurance_agency'        => t('Insurance agency'),
      'jewelry_store'           => t('Jewelry store'),
      'laundry'                 => t('Laundry'),
      'lawyer'                  => t('Lawyer'),
      'library'                 => t('Library'),
      'liquor_store'            => t('Liquor store'),
      'local_government_office' => t('Local government office'),
      'locksmith'               => t('Locksmith'),
      'lodging'                 => t('Lodging'),
      'meal_delivery'           => t('Meal delivery'),
      'meal_takeaway'           => t('Meal takeaway'),
      'mosque'                  => t('Mosque'),
      'movie_rental'            => t('Movie rental'),
      'movie_theater'           => t('Movie theater'),
      'moving_company'          => t('Moving company'),
      'museum'                  => t('Museum'),
      'night_club'              => t('Night club'),
      'painter'                 => t('Painter'),
      'park'                    => t('Park'),
      'parking'                 => t('Parking'),
      'pet_store'               => t('Pet store'),
      'pharmacy'                => t('Pharmacy'),
      'physiotherapist'         => t('Physiotherapist'),
      'place_of_worship'        => t('Place of worship'),
      'plumber'                 => t('Plumber'),
      'police'                  => t('Police'),
      'post_office'             => t('Post office'),
      'real_estate_agency'      => t('Real estate agency'),
      'restaurant'              => t('Restaurant'),
      'roofing_contractor'      => t('Roofing contractor'),
      'rv_park'                 => t('RV park'),
      'school'                  => t('School'),
      'shoe_store'              => t('Shoe store'),
      'shopping_mall'           => t('Shopping mall'),
      'spa'                     => t('Spa'),
      'stadium'                 => t('Stadium'),
      'storage'                 => t('Storage'),
      'store'                   => t('Store'),
      'subway_station'          => t('Subway station'),
      'synagogue'               => t('Synagogue'),
      'taxi_stand'              => t('Taxi stand'),
      'train_station'           => t('Train station'),
      'travel_agency'           => t('Travel agency'),
      'university'              => t('University'),
      'veterinary_care'         => t('Veterinary care'),
      'zoo'                     => t('Zoo'),
      );

      $sp .= '<select id="search_places_select_' . $mapid . '" class="form-select" >';
      foreach ($sp_opts AS $k_opt => $opt) {
        $sel = '';
        if ($k_opt == 'establishment') {
          $sel = 'selected';
        }
        $sp .= '<option value="' . $k_opt . '" ' . $sel . '>' . $opt . '</option>';
      }
      $sp .= '</select>';
      $sp .= '&nbsp;&nbsp;<input type="button" value="' . t('Go') . '" id="search_places_go_btn_' . $mapid . '" class="form-submit" />';
      $sp .= '&nbsp;&nbsp;<input type="button" value="' . t('Reset') . '" onClick="Drupal.getlocations_search_places_clearmarkers(\'' . $mapid . '\', true)"  class="form-submit" />';
      $sp .= '</div>';
    }
    else {
      $placeholder = '';
      if ($defaults['search_places_placeholder']) {
        $placeholder = 'placeholder="' . $defaults['search_places_placeholder'] . '"';
      }
      $sp .= '<input type="text" id="search_places_input_' . $mapid . '" size="' . $defaults['search_places_size'] . '" class="form-text" ' . $placeholder . ' />';
      $sp .= '&nbsp;&nbsp;<input type="button" value="' . t('Reset') . '" onClick="Drupal.getlocations_search_places_clearmarkers(\'' . $mapid . '\', true)"  class="form-submit" />';
      $sp .= '</div>';
    }
    if ($defaults['search_places_list']) {
      $sp .= '<div class="sp_listing_wrapper"><h4>' . t('Google Places search results') . '</h4><div class="sp_listing"><ul class="sp_ul" id="search_places_results_' . $mapid . '"></ul></div></div>';
    }
  }
  if ($defaults['search_places'] && $defaults['search_places_position'] == 'outside_above') {
    $output .= $sp;
  }

  // type class
  $class = '';
  if ($type) {
    $class = ' getlocations_' . $type;
  }

  // wrap the map
  $output .= '<div class="getlocations_map_wrapper_inner' . $class . '">';
  $output .= '<div id="getlocations_map_wrapper_' . $mapid . '"  style="width: ' . $width . '; height: ' . $height . '" >';
  $output .= '<div class="getlocations_map_canvas" id="getlocations_map_canvas_' . $mapid . '" style="width: 100%; height: 100%" ></div>';
  $output .= '</div>';
  $output .= '</div>'; // getlocations_map_wrapper_inner


  // give each map its own data
  $localdata = json_encode(array(
    'datanum'  => $datanum,
    'latlons'  => $latlons,
    'minmaxes' => $minmaxes
  ));
  $output .= "\n" . '<script type="text/javascript">' . "\n" . '<!--//--><![CDATA[//><!--' . "\n";
  $output .= 'getlocations_data["' . $mapid . '"] = ' . $localdata . ';' . "\n";
  $output .= '//--><!]]>' . "\n" . '</script>' . "\n";


  // show maplinks if enabled
  if ($defaults['show_maplinks']) {
    $output .= '<div class="getlocations_map_links" id="getlocations_map_links_' . $mapid . '" ><ul></ul></div>';
  }
  // buttons
  $buttons = array();
  if ($defaults['trafficinfo']) {
    $buttons[] = '<input type="button" value="' . t('Traffic Info !t', array('!t' => ($defaults['trafficinfo_state'] ? t('Off') : t('On')))) . '" title="' . t('Limited Availability') . '" id="getlocations_toggleTraffic_' . $mapid . '" class="form-submit" />';
  }
  if ($defaults['bicycleinfo']) {
    $buttons[] = '<input type="button" value="' . t('Bicycle Info !t', array('!t' => ($defaults['bicycleinfo_state'] ? t('Off') : t('On')))) . '" title="' . t('Limited Availability') . '" id="getlocations_toggleBicycle_' . $mapid . '" class="form-submit" />';
  }
  if ($defaults['transitinfo']) {
    $buttons[] = '<input type="button" value="' . t('Transit Info !t', array('!t' => ($defaults['transitinfo_state'] ? t('Off') : t('On')))) . '" title="' . t('Limited Availability') . '" id="getlocations_toggleTransit_' . $mapid . '" class="form-submit" />';
  }
  if ($defaults['panoramio_use'] && $defaults['panoramio_show']) {
    $buttons[] = '<input type="button" value="' . t('Panoramio !t', array('!t' => ($defaults['panoramio_state'] ? t('Off') : t('On')))) . '" id="getlocations_togglePanoramio_' . $mapid . '" class="form-submit" />';
  }
  if ($defaults['weather_use']) {
    if ($defaults['weather_show']) {
      $buttons[] = '<input type="button" value="' . t('Weather !t', array('!t' => ($defaults['weather_state'] ? t('Off') : t('On')))) . '" id="getlocations_toggleWeather_' . $mapid . '" class="form-submit" />';
    }
    if ($defaults['weather_cloud']) {
      $buttons[] = '<input type="button" value="' . t('Clouds !t', array('!t' => ($defaults['weather_cloud_state'] ? t('Off') : t('On')))) . '" id="getlocations_toggleCloud_' . $mapid . '" class="form-submit" />';
    }
  }

  // categories
  if (isset($defaults['category_showhide_buttons']) && $defaults['category_showhide_buttons']) {
    if (isset($defaults['categories']) && $defaults['categories']) {
      foreach ($defaults['categories'] AS $cat => $label) {
        $buttons[] = '<input type="button" value="' . t('!cat Off', array('!cat' => $label)) . '" id="getlocations_toggle_' . $cat . '_' . $mapid . '" class="form-submit" />';
      }
    }
  }

  // KML
  if ($defaults['kml_group']['kml_url'] && $defaults['kml_group']['kml_url_button']) {
    $kmlbuttonlabel = t('Kml Layer');
    if ($defaults['kml_group']['kml_url_button_label']) {
      $kmlbuttonlabel = $defaults['kml_group']['kml_url_button_label'];
    }
    $kmlbuttonlabel .= ' ' . ($defaults['kml_group']['kml_url_button_state'] ? t('Off') : t('On'));
    $buttons[] = '<input type="button" value="' . $kmlbuttonlabel . '" id="getlocations_toggleKmlLayer_' . $mapid . '" class="form-submit"  />';
  }

  if (module_exists('getlocations_search')) {
    // search area shape
    if (isset($defaults['search_radshape_toggle']) && $defaults['search_radshape_toggle'] && $defaults['search_radshape_enable']) {
      $buttons[] = '<input type="button" value="' . t('Search area !t', array('!t' => ($defaults['search_radshape_toggle_active'] ? t('Off') : t('On')))) . '" id="getlocations_search_toggleShape_' . $mapid . '" class="form-submit" />';
    }
    // search marker toggle button
    if (isset($defaults['do_search_marker']) && $defaults['do_search_marker'] && $defaults['search_marker_toggle']) {
      $buttons[] = '<input type="button" value="' . t('Marker !t', array('!t' => ($defaults['search_marker_toggle_active'] ? t('Off') : t('On')))) . '" id="getlocations_search_toggleMarker_' . $mapid . '" class="form-submit" />';
    }
  }

  // getlocations_gps
  $geolocation_mobile_check = ($defaults['geolocation_mobile_check'] ? FALSE : TRUE);
  if (getlocations_is_mobile($geolocation_mobile_check) && module_exists('getlocations_gps') && isset($defaults['gps_button']) && $defaults['gps_button']) {
    $buttons[] = '<input type="button" value="' . $defaults['gps_button_label'] . '" id="getlocations_gps_show_' . $mapid . '" class="form-submit"  /><div class="getlocations_gps_throbber getlocations_gps_throbber_inactive" id="getlocations_gps_throbber_' . $mapid . '">&nbsp;&nbsp;&nbsp;&nbsp;</div>';
  }

  if (count($buttons)) {
    $output .= '<div class="getlocations_map_buttons container-inline">';
    $output .= implode('&nbsp;', $buttons);
    $output .= '</div>';
  }

  // search_places
  if ($defaults['search_places'] && $defaults['search_places_position'] == 'outside_below') {
    $output .= $sp;
  }

  return $output;
}

/**
 * Returns HTML of a location's vcard, requested by ajax.
 *
 * @param array $variables
 *   An associative array containing:
 *   - location: The information pertaining to the address to be formatted.
 *
 * @return string $output
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_adinfo($variables) {
  $location = $variables['location'];
  $output = '';

  $output .= '<div class="location vcard">';

  // this logic gives the location name field precedence over the node title
  // similarly for users, terms and comments
  $link = FALSE;
  $l =  FALSE;
  if (isset($location['nid']) && $location['nid'] > 0) {
    if (! empty($location['name'])) {
      $link = $location['name'];
    }
    else {
      $node = node_load($location['nid']);
      $link = $node->title;
    }
    $l = l($link, 'node/' . $location['nid'], array('attributes' => array('class' => array('getlocations_infolink'), 'target' => '_parent')));
  }
  elseif (isset($location['uid']) && $location['uid'] > 0) {
    if (! empty($location['name'])) {
      $link = $location['name'];
    }
    else {
      $account = user_load($location['uid']);
      $link = $account->name;
    }
    $l = l($link, 'user/' . $location['uid'], array('attributes' => array('class' => array('getlocations_infolink'), 'target' => '_parent')));
  }
  elseif (isset($location['tid']) && $location['tid'] > 0 && module_exists('taxonomy')) {
    if (! empty($location['name'])) {
      $link = $location['name'];
    }
    else {
      $term = taxonomy_term_load($location['tid']);
      $link = $term->name;
    }
    $l = l($link, 'taxonomy/term/' . $location['tid'], array('attributes' => array('class' => array('getlocations_infolink'), 'target' => '_parent')));
  }
  elseif (isset($location['cid']) && $location['cid'] > 0 && module_exists('comment')) {
    if (! empty($location['name'])) {
      $link = $location['name'];
    }
    else {
      $comment = comment_load($location['cid']);
      $link = $comment->subject;
    }
    $l = l($link, 'comment/' . $location['cid'], array('attributes' => array('class' => array('getlocations_infolink'), 'target' => '_parent')));
  }
  if ($l) {
    $output .= '<h4>' . $l . '</h4>';
  }

  $output .= '<div class="adr">';
  if (! empty($location['street'])) {
    $output .= '<div class="street-address">' . $location['street'];
    if (! empty($location['additional'])) {
      $output .= "&nbsp;" . '<span class="extended-address">' . $location['additional'] . '</span>';
    }
    $output .= '</div>';
  }
  if (! empty($location['city'])) {
    $output .= '<span class="locality">' . $location['city'] . '</span>';
    if (! empty($location['province_name'])) {
      $output .= ",&nbsp;";
    }
    elseif (! empty($location['province'])) {
      $output .= ",&nbsp;";
    }
    else {
      $output .= "&nbsp;";
    }
  }
  if (isset($location['province_name']) && ! empty($location['province_name'])) {
    $output .= '<span class="region">' . $location['province_name'] . '</span>';
    if (! empty($location['postal_code'])) {
      $output .= "&nbsp;";
    }
  }
  elseif (isset($location['province']) && ! empty($location['province'])) {
    $output .= '<span class="region">' . $location['province'] . '</span>';
    if (! empty($location['postal_code'])) {
      $output .= "&nbsp;";
    }
  }
  if (! empty($location['postal_code'])) {
    $output .= '<span class="postal-code">' . drupal_strtoupper($location['postal_code']) . '</span>';
  }
  if (isset($location['country_name']) && ! empty($location['country_name'])) {
    $output .= '<div class="country-name">' . $location['country_name'] . '</div>';
  }
  elseif (isset($location['country']) && ! empty($location['country'])) {
    $output .= '<div class="country-name">' . $location['country'] . '</div>';
  }
  $output .= '</div>';
  if (isset($location['sdist'])) {
    if ($location['sdist'] <> 1) {
      $unit_disp = getlocations_get_unit_names($location['sunit']);
    }
    else {
      $unit_disp = getlocations_get_unit_names($location['sunit'], 'single');
    }
    $output .= '<div class="search-distance">' . number_format(floatval($location['sdist']), 2) . "&nbsp;" . $unit_disp . '</div>';
  }

  if (module_exists('getdirections') && isset($location['getdirections_link']) && $location['getdirections_link']) {
    $gdlink = '';
    if (isset($location['nid']) && $location['nid']) {
      $gdlink = l(t('Directions'), 'getdirections/location/to/' . $location['nid'], array('attributes' => array('class' => array('getlocations_infolink'), 'target' => '_parent')));
    }
    elseif (isset($location['uid']) && $location['uid']) {
      $gdlink = l(t('Directions'), 'getdirections/location_user/to/' . $location['uid'], array('attributes' => array('class' => array('getlocations_infolink'), 'target' => '_parent')));
    }
    elseif (isset($location['cid']) && $location['cid'] && getdirections_check_entity_type('comment')) {
      $gdlink = l(t('Directions'), 'getdirections/location_comment/to/' . $location['cid'], array('attributes' => array('class' => array('getlocations_infolink'), 'target' => '_parent')));
    }
    elseif (isset($location['tid']) && $location['tid'] && getdirections_get_vocabularies()) {
      $gdlink = l(t('Directions'), 'getdirections/location_term/to/' . $location['tid'], array('attributes' => array('class' => array('getlocations_infolink'), 'target' => '_parent')));
    }
    if ($gdlink) {
      $output .= '<div class="getdirections-link">' . $gdlink . '</div>';
    }
  }


  $output .= '</div>';

  return $output;
}

/**
 * Prepares variables for getlocations_box.tpl.php
 *
 * @param array $variables
 *   An associative array containing all the elements to construct an HTML document
 *   suitable for use in a colorbox.
 *
 */
function template_preprocess_getlocations_box(&$variables) {

  if (module_exists('admin_menu')) {
    admin_menu_suppress();
  }
  $getlocations_paths = getlocations_paths_get();
  drupal_add_js($getlocations_paths['getlocations_box_path']);

  // Construct page title
  if (drupal_get_title()) {
    $head_title = array(strip_tags(drupal_get_title()), variable_get('site_name', 'Drupal'));
  }
  else {
    $head_title = array(variable_get('site_name', 'Drupal'));
    if (variable_get('site_slogan', '')) {
      $head_title[] = variable_get('site_slogan', '');
    }
  }
  $variables['head_title'] = implode(' | ', $head_title);
  $variables['base_path'] = base_path();
  $variables['head'] = drupal_get_html_head();
  $variables['language'] = $GLOBALS['language'];
  $variables['language']->dir = $GLOBALS['language']->direction ? 'rtl' : 'ltr';
  $variables['css'] = drupal_add_css();
  $variables['styles'] = drupal_get_css();
  $variables['scripts'] = drupal_get_js();
  $variables['title'] = drupal_get_title();
  // Closure should be filled last.
  $variables['closure'] = theme('closure');
  // Compile a list of classes that are going to be applied to the body element.
  // This allows advanced theming based on context (home page, node of certain type, etc.).
  $body_classes = array();
  // Add a class that tells us whether we're on the front page or not.
  $body_classes[] = $variables['is_front'] ? 'front' : 'not-front';
  // Add a class that tells us whether the page is viewed by an authenticated user or not.
  $body_classes[] = $variables['logged_in'] ? 'logged-in' : 'not-logged-in';
  $body_classes[] = 'no-sidebars';
  // Implode with spaces.
  $variables['body_classes'] = implode(' ', $body_classes);

}

/**
 * Prepares variables for getlocations_marker_box.tpl.php
 *
 * @param array $variables
 *   An associative array containing all the elements to construct an HTML document
 *   suitable for use in a colorbox.
 *
 */
function template_preprocess_getlocations_marker_box(&$variables) {

  if (module_exists('admin_menu')) {
    admin_menu_suppress();
  }
  $getlocations_paths = getlocations_paths_get();
  drupal_add_js($getlocations_paths['getlocations_marker_box_path']);

  $head_title = t('Getlocations markers');
  $variables['head_title'] = $head_title;
  $variables['base_path'] = base_path();
  $variables['head'] = drupal_get_html_head();
  $variables['language'] = $GLOBALS['language'];
  $variables['language']->dir = $GLOBALS['language']->direction ? 'rtl' : 'ltr';
  $variables['css'] = drupal_add_css();
  $variables['styles'] = drupal_get_css();
  $variables['scripts'] = drupal_get_js();
  $variables['title'] = $head_title;

  // Closure should be filled last.
  $variables['closure'] = theme('closure');
  // Compile a list of classes that are going to be applied to the body element.
  // This allows advanced theming based on context (home page, node of certain type, etc.).
  $body_classes = array();
  // Add a class that tells us whether we're on the front page or not.
  $body_classes[] = $variables['is_front'] ? 'front' : 'not-front';
  // Add a class that tells us whether the page is viewed by an authenticated user or not.
  $body_classes[] = $variables['logged_in'] ? 'logged-in' : 'not-logged-in';
  $body_classes[] = 'no-sidebars';
  // Implode with spaces.
  $variables['body_classes'] = implode(' ', $body_classes);

}

/**
 * Returns HTML of the getlocations settings form.
 *
 * @param array $variables
 *   An associative array containing:
 *   - form: The form array.
 *
 * @return string The rendered form
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_settings_form($variables) {

  $form = $variables['form'];

  $output = '';
  $form['getlocations_default']['returnlink_page_link']['#prefix'] = '<div id="wrap-page-link">';
  $form['getlocations_default']['returnlink_page_link']['#suffix'] = '</div>';
  if (isset($form['getlocations_default']['returnlink_user_link'])) {
    $form['getlocations_default']['returnlink_user_link']['#prefix'] = '<div id="wrap-user-link">';
    $form['getlocations_default']['returnlink_user_link']['#suffix'] = '</div>';
  }
  if (isset($form['getlocations_default']['returnlink_term_link'])) {
    $form['getlocations_default']['returnlink_term_link']['#prefix'] = '<div id="wrap-term-link">';
    $form['getlocations_default']['returnlink_term_link']['#suffix'] = '</div>';
  }
  if (isset($form['getlocations_default']['returnlink_comment_link'])) {
    $form['getlocations_default']['returnlink_comment_link']['#prefix'] = '<div id="wrap-comment-link">';
    $form['getlocations_default']['returnlink_comment_link']['#suffix'] = '</div>';
  }
  if (isset($form['getlocations_colorbox']['width']) && isset($form['getlocations_colorbox']['height'])) {
    $form['getlocations_colorbox']['width']['#prefix'] = '<div id="wrap-getlocations-colorbox">';
    $form['getlocations_colorbox']['height']['#suffix'] = '</div>';
  }
  if (isset($form['getlocations_colorbox']['marker_width']) && isset($form['getlocations_colorbox']['marker_height'])) {
    $form['getlocations_colorbox']['marker_width']['#prefix'] = '<div id="wrap-getlocations-marker-colorbox">';
    $form['getlocations_colorbox']['marker_height']['#suffix'] = '</div>';
  }

  // marker colorbox
  if (module_exists('colorbox')) {
    $getlocations_colorbox = getlocations_colorbox_settings();
    if ($getlocations_colorbox['marker_enable']) {
      $link = getlocations_markerpicker_link($form['getlocations_default']['node_map_marker']['#id'], 'n');
      $form['getlocations_default']['node_map_marker']['#field_suffix'] = '&nbsp;' . $link;

      if (isset($form['getlocations_default']['user_map_marker'])) {
        $link = getlocations_markerpicker_link($form['getlocations_default']['user_map_marker']['#id'], 'u');
        $form['getlocations_default']['user_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
      if (module_exists('taxonomy')) {
        if (isset($form['getlocations_default']['vocabulary_map_marker'])) {
          $link = getlocations_markerpicker_link($form['getlocations_default']['vocabulary_map_marker']['#id'], 'v');
          $form['getlocations_default']['vocabulary_map_marker']['#field_suffix'] = '&nbsp;' . $link;
        }
        if (isset($form['getlocations_default']['term_map_marker'])) {
          $link = getlocations_markerpicker_link($form['getlocations_default']['term_map_marker']['#id'], 'v');
          $form['getlocations_default']['term_map_marker']['#field_suffix'] = '&nbsp;' . $link;
        }
      }
      if (isset($form['getlocations_default']['comment_map_marker'])) {
        $link = getlocations_markerpicker_link($form['getlocations_default']['comment_map_marker']['#id'], 'c');
        $form['getlocations_default']['comment_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
      if (module_exists('getlocations_fields')) {
        $link = getlocations_markerpicker_link($form['getlocations_default']['input_map_marker']['#id'], 'i');
        $form['getlocations_default']['input_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }

      if ($types = getlocations_get_types()) {
        foreach ($types AS $type => $name) {
          $field_names = getlocations_get_fieldname2($type, 'node');
          foreach ($field_names AS $field_name) {
            if (isset($form['getlocations_node_marker']['content_type'][$type]['field_name'][$field_name]['map_marker'])) {
              $link = getlocations_markerpicker_link($form['getlocations_node_marker']['content_type'][$type]['field_name'][$field_name]['map_marker']['#id'], 'n');
              $form['getlocations_node_marker']['content_type'][$type]['field_name'][$field_name]['map_marker']['#field_suffix'] = '&nbsp;' . $link;
            }
          }
        }
      }
      if (module_exists('taxonomy')) {
        if ($types = getlocations_get_vocabularies()) {
          foreach ($types AS $type => $name) {
            if (isset($form['getlocations_vocabulary_marker']['vocabulary'][$type]['map_marker'])) {
              $link = getlocations_markerpicker_link($form['getlocations_vocabulary_marker']['vocabulary'][$type]['map_marker']['#id'], 'v');
              $form['getlocations_vocabulary_marker']['vocabulary'][$type]['map_marker']['#field_suffix'] = '&nbsp;' . $link;
            }
          }
        }

        // term
        $getlocations_term_marker = variable_get('getlocations_term_marker', array('enable' => 0, 'vids' => 0, 'max_depth' => ''));
        if ($getlocations_term_marker['enable'] && $getlocations_term_marker['vids']) {
          $depth = is_numeric($getlocations_term_marker['max_depth']) && $getlocations_term_marker['max_depth'] > 0 ? $getlocations_term_marker['max_depth'] : NULL;
          $vids = $getlocations_term_marker['vids'];
          foreach ($vids AS $vid) {
            $terms = taxonomy_get_tree($vid, 0, $depth);
            $tct = 0;
            foreach ($terms AS $term) {
              $tid = $term->tid;
              if (isset($form['getlocations_term_marker']['vid'][$vid]['term'][$tid]['map_marker'])) {
                $link = getlocations_markerpicker_link($form['getlocations_term_marker']['vid'][$vid]['term'][$tid]['map_marker']['#id'], 'n');
                $form['getlocations_term_marker']['vid'][$vid]['term'][$tid]['map_marker']['#field_suffix'] = '&nbsp;' . $link;
                if (! $tct) {
                  $v = taxonomy_vocabulary_load($vid);
                  $vocab_name = $v->name;
                  $form['getlocations_term_marker']['vid'][$vid]['term'][$tid]['map_marker']['#prefix'] = t('Terms for %name', array('%name' => $vocab_name));
                }
              }
              $tct++;
            }
          }
        }
      }
    }
  }

  $form['getlocations_default']['useclustermanager']['#prefix'] = '<div id="wrap-getlocations-clusteropts">';
  $form['getlocations_default']['markerclusterer_minsize']['#suffix'] = '</div>';

  $form['getlocations_default']['usemarkermanager']['#prefix'] = '<div id="wrap-getlocations-markeropts">';
  $form['getlocations_default']['maxzoom']['#suffix'] = '</div>';

  // preview
  $getlocations_defaults = getlocations_defaults();
  $getlocations_defaults['extcontrol'] = 'preview_map';
  $mapid = getlocations_setup_map($getlocations_defaults);
  $minmaxes = '';
  $latlons = array();
  getlocations_js_settings_do($getlocations_defaults, $latlons, $minmaxes, $mapid, FALSE, $getlocations_defaults['extcontrol']);
  $preview_map = theme('getlocations_show', array('width' => $getlocations_defaults['width'] , 'height' => $getlocations_defaults['height'] , 'defaults' => $getlocations_defaults, 'mapid' => $mapid, 'latlons' => $latlons, 'minmaxes' => $minmaxes, 'type' => '', 'node' => ''));
  $form['getlocations_preview']['preview_map']['#markup'] = '<div id="getlocations_preview_map">' . $preview_map . '</div>';

  $output .= drupal_render_children($form);
  return $output;
}

/**
 * Returns HTML of the getlocations plugin_style_map_options form.
 *
 * @param array $variables
 *   An associative array containing:
 *   - form: The form array.
 *
 * @return string The rendered form
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_plugin_style_map_options_form($variables) {
  $form = $variables['form'];

  if (module_exists('colorbox')) {
    $getlocations_colorbox = getlocations_colorbox_settings();
    if ($getlocations_colorbox['marker_enable']) {
      if (isset($form['node_map_marker'])) {
        $link = getlocations_markerpicker_link($form['node_map_marker']['#id'], 'n');
        $form['node_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
      $getlocations_node_marker = variable_get('getlocations_node_marker', array('enable' => 0));
      if ($getlocations_node_marker['enable']) {
        if ($types = getlocations_get_types()) {
          foreach ($types AS $type => $name) {
            $field_names = getlocations_get_fieldname2($type, 'node');
            foreach ($field_names AS $field_name) {
              $mkey = 'node_marker__' . strtolower($type) . '__' . $field_name;
              $link = getlocations_markerpicker_link($form[$mkey]['#id'], 'n');
              $form[$mkey]['#field_suffix'] = '&nbsp;' . $link;
            }
          }
        }
      }
      if (isset($form['user_map_marker'])) {
        $link = getlocations_markerpicker_link($form['user_map_marker']['#id'], 'n');
        $form['user_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }

      if (module_exists('taxonomy')) {
        if (isset($form['vocabulary_map_marker'])) {
          $link = getlocations_markerpicker_link($form['vocabulary_map_marker']['#id'], 'v');
          $form['vocabulary_map_marker']['#field_suffix'] = '&nbsp;' . $link;
        }
        $getlocations_vocabulary_marker = variable_get('getlocations_vocabulary_marker', array('enable' => 0));
        if ($getlocations_vocabulary_marker['enable']) {
          foreach ($types AS $type => $name) {
            $field_name = getlocations_get_fieldname($type, 'taxonomy_term');
            $mkey = 'vocabulary_marker_' . $field_name;
            $link = getlocations_markerpicker_link($form[$mkey]['#id'], 'n');
            $form[$mkey]['#field_suffix'] = '&nbsp;' . $link;
          }
        }
        if (isset($form['term_map_marker'])) {
          $link = getlocations_markerpicker_link($form['term_map_marker']['#id'], 'v');
          $form['term_map_marker']['#field_suffix'] = '&nbsp;' . $link;
        }
        $getlocations_term_marker = variable_get('getlocations_term_marker', array('enable' => 0, 'vids' => 0, 'max_depth' => ''));
        if ($getlocations_term_marker['enable'] && $getlocations_term_marker['vids']) {
          $depth = is_numeric($getlocations_term_marker['max_depth']) && $getlocations_term_marker['max_depth'] > 0 ? $getlocations_term_marker['max_depth'] : NULL;
          $vids = $getlocations_term_marker['vids'];
          foreach ($vids AS $vid) {
            $terms = taxonomy_get_tree($vid, 0, $depth);
            foreach ($terms AS $term) {
              $name = $term->name;
              $tid = $term->tid;
              $mkey = 'term_marker_' . $tid;
              $link = getlocations_markerpicker_link($form[$mkey]['#id'], 'n');
              $form[$mkey]['#field_suffix'] = '&nbsp;' . $link;
            }
          }
        }
      }

      if (isset($form['comment_map_marker'])) {
        $link = getlocations_markerpicker_link($form['comment_map_marker']['#id'], 'n');
        $form['comment_map_marker']['#field_suffix'] = '&nbsp;' . $link;
      }
    }
  }

  $output = drupal_render_children($form);
  return $output;

}

/**
 * Returns HTML of the getlocations plugin_style_streetview_options form.
 *
 * @param array $variables
 *   An associative array containing:
 *   - form: The form array.
 *
 * @return string The rendered form
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_plugin_style_streetview_options_form($variables) {
  $form = $variables['form'];


  $output = drupal_render_children($form);
  return $output;
}

/**
 * Returns HTML of a latitude in decimal degress expressed in degrees, minutes and seconds.
 *
 * from location module
 *
 * @param array $variables
 *   An associative array containing:
 *   - latitude: A latitude in decimal degrees.
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_latitude_dms($variables) {
  $latitude = $variables['latitude'];
  $output = '';
  list($degrees, $minutes, $seconds, $negative) = getlocations_dd_to_dms($latitude);
  $output .= $degrees . "&deg; " . $minutes . "&#39; " . $seconds . "&#34; ";
  if (!$negative) {
    $output .= 'N';
  }
  else {
    $output .= 'S';
  }
  return $output;
}

/**
 * Returns HTML of a longitude in decimal degress expressed in degrees, minutes and seconds.
 *
 * from location module
 *
 * @param array $variables
 *   An associative array containing:
 *   - longitude: A longitude in decimal degrees.
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_longitude_dms($variables) {
  $longitude = $variables['longitude'];
  $output = '';
  list($degrees, $minutes, $seconds, $negative) = getlocations_dd_to_dms($longitude);
  $output .= $degrees . "&deg; " . $minutes . "&#39; " . $seconds . "&#34; ";
  if (!$negative) {
    $output .= 'E';
  }
  else {
    $output .= 'W';
  }
  return $output;
}

/**
 * Returns an array of an address from the addressfield module converted for use in getlocations.
 *
 * from location module
 *
 * @param array $variables
 *   An associative array containing:
 *   - address: an array of address components.
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_addressfield_convert($variables) {
  $address = $variables['address'];
  $location = array();
  if (is_array($address) && ! empty($address)) {
    $name = array();
    if (isset($address['name_line']) && $address['name_line']) {
      $name[] = $address['name_line'];
    }
    if (isset($address['first_name']) && $address['first_name']) {
      if (isset($address['last_name']) && $address['last_name']) {
        $name[] = $address['first_name'] . ' ' . $address['last_name'];
      }
      else {
        $name[] = $address['first_name'];
      }
    }
    elseif (isset($address['last_name']) && $address['last_name']) {
      $name[] = $address['last_name'];
    }
    if (isset($address['organisation_name']) && $address['organisation_name']) {
      $name[] = $address['organisation_name'];
    }
    $location['name'] = (count($name) ? implode(", ", $name) : '');

    $location['street'] = (isset($address['thoroughfare']) ? $address['thoroughfare'] : '');
    $additional = array();
    if (isset($address['premise']) && $address['premise']) {
      $additional[] = $address['premise'];
    }
    if (isset($address['sub_premise']) && $address['sub_premise']) {
      $additional[] = $address['sub_premise'];
    }
    $location['additional'] = (count($additional) ? implode(", ", $additional) : '');
    $city = array();
    if (isset($address['dependent_locality']) && $address['dependent_locality']) {
      $city[] = $address['dependent_locality'];
    }
    if (isset($address['locality']) && $address['locality']) {
      $city[] = $address['locality'];
    }
    $location['city'] = (count($city) ? implode(", ", $city) : '');
    $admin_area = array();
    if (isset($address['sub_administrative_area']) && $address['sub_administrative_area']) {
      $admin_area[] = $address['sub_administrative_area'];
    }
    if (isset($address['administrative_area']) && $address['administrative_area']) {
      $admin_area[] = $address['administrative_area'];
    }
    $location['province_name'] = (count($admin_area) ? implode(", ", $admin_area) :'');
    $location['postal_code'] = (isset($address['postal_code']) ? drupal_strtoupper($address['postal_code']) : '');
    $location['country_name'] = (isset($address['country_name']) ? $address['country_name'] : $address['country']);
    $location['country'] = $address['country'];
  }
  return $location;

}

/**
 * Returns HTML of a url, requested by ajax.
 *
 * @param array $variables
 *   An associative array containing:
 *   - lid: The location identifier or glid.
 *   - lidkey: The entity identifier type
 *
 * @return string $output
 *
 * @ingroup themeable
 *
 */
function theme_getlocations_lidinfo($variables) {
  $lid = $variables['lid'];
  $lidkey = $variables['lidkey'];

  $output = FALSE;
  if ($lid > 0) {
    if (module_exists('getlocations_fields') || module_exists('location')) {
      $path = getlocations_get_path_from_lid($lid);
      if ($path) {
        $output = $path;
      }
    }
    elseif (module_exists('geofield') || module_exists('geolocation') ) {
      if ($lidkey == 'nid') {
        $path = url('node/' . $lid);
      }
      elseif ($lidkey == 'vid') {
        $nid = getlocations_get_nid($lid);
        $path = url('node/' . $nid);
      }
      elseif ($lidkey == 'uid') {
        $path = url('user/' . $lid);
      }
      elseif ($lidkey == 'tid' && module_exists('taxonomy')) {
        $path = url('taxonomy/term/' . $lid);
      }
      elseif ($lidkey == 'cid' && module_exists('comment')) {
        $path = url('comment/' . $lid);
      }
      if ($path) {
        $output = $path;
      }
    }
  }
  return $output;

}
