<?php
/*
Plugin Name: JayBo Mapping Entries
Plugin URI: http://www.jaybowalkin.com/plugins
Description: Adds a (DBX) box to your Posts Advanced Editing view, allowing you to give a GPS location via the google maps interface.
Author: Bryan Clark
Version: 0.2
Author URI: http://www.jaybowalkin.com/
*/ 

// If you hard code a key here, it should work as expected
// http://0.0.0.0/wordpress/wp-admin
// like ABQIAAAAqVZbLKBCznFQ46dDHPptjRRiOXgXOM8br8zb7qn-pRBSAb_VyhQgFVaXOIjMXy3qDeh5mM8WZnE8lA
$google_maps_admin_api_key = '';

function jaybo_mapping_entry_scripts() {
	global $google_maps_admin_api_key;

	if ( ! $google_maps_admin_api_key ) {
		$google_maps_admin_api_key = get_option('google_maps_admin_api_key');
	}

	if ( $google_maps_admin_api_key ) {

?>

	    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=<?php echo $google_maps_admin_api_key; ?>"
	            type="text/javascript"></script>
	    <script src="http://maps.google.com/maps?file=api&v=2&key=<?php echo $google_maps_admin_api_key; ?>" type="text/javascript"></script>
	    <script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=<?php echo $google_maps_admin_api_key; ?>" type="text/javascript"></script>
	    <script src="http://www.google.com/uds/solutions/localsearch/gmlocalsearch.js" type="text/javascript"></script>
    
	    <style type="text/css">
	      @import url("http://www.google.com/uds/css/gsearch.css");
	      @import url("http://www.google.com/uds/solutions/localsearch/gmlocalsearch.css");

	      #jaybo_mapping_entry_map {
	        border : 1px solid #979797;
	        width : 100%;
	        height : 600px;
	      }
	    </style>

	<script type="text/javascript">
	    //<![CDATA[

		function jaybo_mapping_entry_ajax_gps ( post_id, gps )
		{
			var ajaxSave = new WPAjax( false , 'jaybo_mapping_entry_ajax_response' );
			if ( ajaxSave.notInitialized() )
				return true;

			ajaxSave.addOnComplete( function(transport) {
				var msg = transport.responseXML.getElementsByTagName("response_data")[0];
				Element.update(ajaxSave.myResponseElement, '<div class="updated fade"><p>' + msg.textContent + '</p></div>');
				setTimeout(function() {Element.update(ajaxSave.myResponseElement, '');}, 10 * 1000);
			} );

			ajaxSave.addArg( "action", "jaybo_mapping_entry_save_gps" );
		  	ajaxSave.addArg( "gps", gps.lat() + "," + gps.lng() );
		  	ajaxSave.addArg( "post_id", post_id );

			ajaxSave.request(ajaxSave.url);

			return true;
		}

	    //]]>
	</script>

<?
	}
}

function jaybo_mapping_entry() {
	global $post;
	global $google_maps_admin_api_key;

	if ( ! $google_maps_admin_api_key ) {
		$google_maps_admin_api_key = get_option('google_maps_admin_api_key');
	}

?>
<div class="dbx-b-ox-wrapper">
	<fieldset id="posturl" class="dbx-box">
		<div class="dbx-h-andle-wrapper">
			<h3 class="dbx-handle"><?php _e('Map This Entry'); ?></h3>
		</div>
		<div class="dbx-c-ontent-wrapper">
			<div class="dbx-content">
		
<?php
	if ( $google_maps_admin_api_key && $post->ID > 0) {
		jaybo_mapping_entry_scripts();
?>
	<script type="text/javascript">
	    //<![CDATA[
		
    var CURRENT_MARKER = null;
    var CURRENT_POST = null;

    var Post = function(id, title, link, date, latlng) {
      this.id = id;
      this.title = title;
      this.link = link;
      this.date = date || "Current Post";
      this.latlng = latlng;
      this.icon = (date)? G_DEFAULT_ICON : G_PAUSE_ICON;
    };

    function jaybo_create_info_html(post) {
			return '<div><a target="_blank" href="' + post.link + '">' + post.title + '</a></div><div>' + post.date + '</div>';
    }

    function jaybo_set_marker(jaybo_map, marker, post) {
      post.latlng = marker.getPoint();

			marker.setPoint( post.latlng );
			jaybo_map.panTo ( post.latlng );

			marker.openInfoWindowHtml(jaybo_create_info_html(post));

			jaybo_mapping_entry_ajax_gps  ( post.id, marker.getPoint() );

    }

		function jaybo_create_marker(jaybo_map, post) {
   		var marker = new GMarker( post.latlng, {icon: post.icon, draggable: true, bouncy: true});

			jaybo_map.addOverlay(marker);

			GEvent.addListener(marker, "click", function() {
				marker.openInfoWindowHtml(jaybo_create_info_html(post));
			});

			GEvent.addListener(marker, "dragstart", function() {
				jaybo_map.closeInfoWindow();
			});

			GEvent.addListener(marker, "dragend", function() {
        jaybo_set_marker(jaybo_map, marker, post);
			});

      return marker;
		}

    function JayBoload() {
      if (GBrowserIsCompatible()) {
        var jaybo_map = new GMap2(document.getElementById("jaybo_mapping_entry_map"));
    		jaybo_map.addControl(new GLargeMapControl());
    		jaybo_map.addControl(new GMapTypeControl());
    		jaybo_map.addControl(new GOverviewMapControl());

		GEvent.addListener(jaybo_map, "dblclick", function(overlay, latlng) {
      if (CURRENT_MARKER) {
  			CURRENT_MARKER.setPoint( latlng );
      } else {
        CURRENT_POST = new Post("<?php echo $post->ID;?>", "<?php echo htmlspecialchars($post->post_title); ?>", "<?php echo get_permalink($post->ID);?>",null,latlng);
	  		CURRENT_MARKER = jaybo_create_marker(jaybo_map, CURRENT_POST);
      }
      jaybo_set_marker(jaybo_map, CURRENT_MARKER, CURRENT_POST);
		});

		// request that tabular search results should be suppressed
		var options = {
		    resultList : google.maps.LocalSearch.RESULT_LIST_SUPPRESS
		};
		jaybo_map.addControl(new google.maps.LocalSearch(options));

<?php		
    $gps = false;
		date_default_timezone_set("GMT");
		if ( $gps = get_post_meta($post->ID, 'gps', true) ) { 			?>
		jaybo_map.setCenter(new GLatLng(<?php echo $gps; ?>), 12);
    CURRENT_POST = new Post("<?php echo $post->ID;?>", "<?php echo htmlspecialchars($post->post_title); ?>", "<?php echo get_permalink($post->ID);?>",null, new GLatLng(<?php echo $gps; ?>));
		CURRENT_MARKER = jaybo_create_marker(jaybo_map, CURRENT_POST);
		CURRENT_MARKER.openInfoWindowHtml(jaybo_create_info_html(CURRENT_POST));
<?php		}

		global $wpdb;
		if ($ps = $wpdb->get_results("SELECT * FROM $wpdb->posts JOIN $wpdb->postmeta on $wpdb->posts.id = $wpdb->postmeta.post_id WHERE $wpdb->posts.id != $post->ID AND $wpdb->postmeta.meta_key = 'gps' AND $wpdb->posts.post_date <= DATE_ADD('$post->post_date', INTERVAL 1 DAY) ORDER BY $wpdb->posts.post_date DESC LIMIT 15")) {

			foreach ($ps as $index => $p) {
				if ( $p_gps = get_post_meta( $p->ID, 'gps', true) ) {
					if ( abs(strtotime($p->post_date)) > abs(strtotime($post->post_date)) ) {
						$time_diff = jaybo_mapping_entry_time_since(abs(strtotime($post->post_date) . " GMT"), abs(strtotime($p->post_date) . " GMT")) . " after";
					} else {
						$time_diff = jaybo_mapping_entry_time_since(abs(strtotime($p->post_date) . " GMT"), abs(strtotime($post->post_date) . " GMT")) . " before";
					}
?>
				<?php if(!$gps && $index == 0) { ?> 
					jaybo_map.setCenter(new GLatLng(<?php echo $p_gps; ?>), 11);
				<?php } ?>
					jaybo_create_marker(jaybo_map, new Post("<?php echo $p->ID;?>", "<?php echo htmlspecialchars($p->post_title); ?>", "<?php echo get_permalink($p->ID);?>","<?php echo $time_diff; ?>", new GLatLng(<?php echo $p_gps; ?>)) );
<?php
				}
			}

		}

?>

	      }
	    }
	    GSearch.setOnLoadCallback(JayBoload);
	    window.unload=GUnload;

	    //]]>
	</script>
	<strong>Double click to add a marker to the map</strong>
	<div id="jaybo_mapping_entry_map"></div>
	<div id="jaybo_mapping_entry_ajax_response"></div>
<?php
	} else if ( $post->ID <= 0 ) {
?>
	<p>Save your post and continue editing in order to see a map (if you're a hacker you could fix this problem!)</p>
<?php
	} else {
?>
		<p>You need a Google Maps API Key, <a target="_blank" href="http://www.google.com/apis/maps/signup.html">sign up</a> with this URL: <tt style="font-weight:bold"><?php bloginfo('home'); ?>/wp-admin</tt></p>
<?php
	}
?>

			</div>
		</div>
	</fieldset>
</div>
<?php
}

add_action('dbx_post_advanced', 'jaybo_mapping_entry');

function jaybo_mapping_entry_add_page() {
	add_options_page("JayBo Mapping Entries", "Mapping Entries", 10, 
			 "jaybo_mapping_entries", jaybo_mapping_entries_admin);
}

add_action('admin_menu', 'jaybo_mapping_entry_add_page');


function jaybo_mapping_entries_admin() {
	global $google_maps_admin_api_key;

	if ( ! $google_maps_admin_api_key ) {
		$google_maps_admin_api_key = get_option('google_maps_admin_api_key');
	}

        if ( isset($_POST['jaybo_maps_submit']) ) {
                if ( function_exists('current_user_can') && !current_user_can('manage_options') )
                        die(__('Cheatin&#8217; uh?'));

		$google_maps_admin_api_key = $_POST['google_maps_admin_api_key'];
		update_option('google_maps_admin_api_key', $google_maps_admin_api_key);
	}


?>
<?php if ( !empty($_POST ) ) : ?>
	<div id="message" class="updated fade"><p><strong><?php _e('Options saved.') ?></strong></p></div>
<?php endif; ?>

<div class="wrap">
	<h2>Edit your Google Maps Admin API Key</h2>
	<p>You need a Google Maps API Key for your wp-admin pages, <a target="_blank" href="http://www.google.com/apis/maps/signup.html">sign up</a> with this URL: <tt style="font-weight:bold"><?php bloginfo('home'); ?>/wp-admin</tt></p>

	<form action="" method="post" id="jaybo-mapping-entries-conf" >
	<div>Then enter your key here: <input type="text" name="google_maps_admin_api_key" id="google_maps_admin_api_key" value="<?php echo $google_maps_admin_api_key; ?>" size="100"/><input type="submit" name="jaybo_maps_submit" value="Save"/></div>
	</form>
</div>
<?php

}

function jaybo_mapping_entry_save_gps() {
	$post_id = $_POST['post_id'];
	$key = 'gps';
	$value = urldecode($_POST[$key]);

	if ( get_post_meta( $post_id, $key, true ) == '') {
		add_post_meta( $post_id, $key, $value);
	} 

	if ( update_post_meta( $post_id, $key, $value ) ) {
		$x = new WP_Ajax_Response( array(
			'what' => 'jaybo-map',
			'id' => $post_id,
			'data' => 'Got it!  The Entry Location was saved.',
			'supplemental' => array('postid' => $post_id, 'gps' => $value)
		) );
		$x->send();
	}
}
add_action('wp_ajax_jaybo_mapping_entry_save_gps', 'jaybo_mapping_entry_save_gps' );

function jaybo_mapping_entry_init() {
	global $google_maps_admin_api_key;

	if( ! $google_maps_admin_api_key ) {
		add_option('google_maps_admin_api_key', $google_maps_admin_api_key, 'Google Maps API Key for wp-admin');
	}

	if ( ! $google_maps_admin_api_key ) {
		$google_maps_admin_api_key = get_option('google_maps_admin_api_key');
	}

}

add_action('init', 'jaybo_mapping_entry_init');

/* ==================== HELPER FUNCTIONS =============================== */

/* 
Function Name: Time Since 
Function URI: http://binarybonsai.com/wordpress/timesince
Description: Tells the time between the entry being posted and the comment being made.
Author: Michael Heilemann & Dunstan Orchard
Author URI: http://binarybonsai.com
*/

function jaybo_mapping_entry_time_since($older_date, $newer_date = false)
{
	// array of time period chunks
	$chunks = array(
	array(60 * 60 * 24 * 365 , 'year'),
	array(60 * 60 * 24 * 30 , 'month'),
	array(60 * 60 * 24 * 7, 'week'),
	array(60 * 60 * 24 , 'day'),
	array(60 * 60 , 'hour'),
	array(60 , 'minute'),
	);
	
	// $newer_date will equal false if we want to know the time elapsed between a date and the current time
	// $newer_date will have a value if we want to work out time elapsed between two known dates
	$newer_date = ($newer_date == false) ? (time()+(60*60*get_settings("gmt_offset"))) : $newer_date;
	
	// difference in seconds
	$since = $newer_date - $older_date;
	
	// we only want to output two chunks of time here, eg:
	// x years, xx months
	// x days, xx hours
	// so there's only two bits of calculation below:

	// step one: the first chunk
	for ($i = 0, $j = count($chunks); $i < $j; $i++)
		{
		$seconds = $chunks[$i][0];
		$name = $chunks[$i][1];

		// finding the biggest chunk (if the chunk fits, break)
		if (($count = floor($since / $seconds)) != 0)
			{
			break;
			}
		}

	// set output var
	$output = ($count == 1) ? '1 '.$name : "$count {$name}s";

	// step two: the second chunk
	if ($i + 1 < $j)
		{
		$seconds2 = $chunks[$i + 1][0];
		$name2 = $chunks[$i + 1][1];
		
		if (($count2 = floor(($since - ($seconds * $count)) / $seconds2)) != 0)
			{
			// add to output var
			$output .= ($count2 == 1) ? ', 1 '.$name2 : ", $count2 {$name2}s";
			}
		}
	
	return $output;
}

