#!/usr/bin/perl

=head1 NAME

Comment Map Movable Type plugin

=head1 DESCRIPTION

    Show your comments on a Google Map

=head1 COPYRIGHT

  Copyright (c) 2006 Antoine Imbert <antoine.imbert@gmail.com> All rights reserved.

  This program is free software; you can redistribute it and/or modify it under
  the same terms as Perl itself.

=cut

package MT::Plugin::CommentMap;

use strict;
use warnings;
use Data::Dumper;
use MT;
use vars qw( $VERSION $plugin);
$VERSION = 0.01;

eval {
    require MT::Plugin;
    $plugin = MT::Plugin->new({
        name => 'Comment Map',
        description => "Show your comments on a Google Map",
        doc_link => 'http://blog.ant0ine.com/2006/11/mt_comment_map_plugin.html',
        author_name => 'Antoine Imbert',
        author_link => 'http://blog.ant0ine.com',
        version => $VERSION,
        config_template => \&template,
        settings => new MT::PluginSettings([
            ['google_api_key', { Default => '' }],
        ]),
    });
    MT->add_plugin($plugin);
    MT::Template::Context->add_tag( CommentMapHead => \&comment_map_head);
    MT::Template::Context->add_tag( CommentMapDiv => \&comment_map_div);
    MT::Template::Context->add_tag( CommentMapScript => \&comment_map_script);
};

sub make_map {
    my ($args) = @_;

    require Geo::IP::PurePerl;
    require HTML::GoogleMaps;
    require MT::Comment;
    require HTML::Template;

    my $gi = Geo::IP::PurePerl->new(Geo::IP::PurePerl::GEOIP_STANDARD());

    my $map_key = $plugin->get_config_value('google_api_key')
        or die 'You must provide a Google Maps API key';
    my $map = HTML::GoogleMaps->new(
        key => $map_key, 
        height => $args->{height}, 
        width => $args->{width}
        );
    $map->v2_zoom($args->{zoom});
    $map->dragging(0);
    $map->controls('small_map_control');
    $map->map_type($args->{type});

    my $markers = {};
    my $iter = MT::Comment->load_iter(
            { junk_status => 1, blog_id => $args->{blog_id} }, 
            { 'sort' => 'created_on', direction => 'descend', limit => $args->{lastn} }
            );
    while (my $comment = $iter->()) {
        my $h = $gi->get_city_record_as_hash($comment->ip) or next;
        next unless $h->{longitude} && $h->{latitude} && $h->{city};
        my $key = $h->{country_code}.$h->{city};
        $markers->{$key} = $h unless $markers->{$key};
        next if $markers->{$key}->{comments} && 
                @{$markers->{$key}->{comments}} > $args->{max_comments_per_bubble};
        push @{$markers->{$key}->{comments}}, {
            comment_author => $comment->author,
            comment_permalink => $comment->entry->permalink.'#comment-'.$comment->id,
            entry_title => $comment->entry->title,
            entry_permalink => $comment->entry->permalink,
            };
    }

    for my $key (keys %{$markers}) {
        my $tmpl = &bubble;
        my $tmpl_obj = HTML::Template->new(scalarref => \$tmpl);
        $tmpl_obj->param( city => $markers->{$key}->{city}, comments => $markers->{$key}->{comments} );
        my $html = $tmpl_obj->output;
        $html =~ s/"/\\"/g;
        $html =~ s/\n//g;
        $map->add_marker(   point => [$markers->{$key}->{longitude}, $markers->{$key}->{latitude}],
                            html => $html, noformat => 1);
    }
    return $map->render or die 'failed to render the map';
}

sub comment_map_head { 
    my ($ctx, $args, $cond) = @_;
    $args->{blog_id} ||= $ctx->stash('blog')->id;
    $args->{height} ||= 400;
    $args->{width} ||= 600;
    $args->{zoom} ||= 1;
    $args->{type} ||= 'normal';
    $args->{lastn} ||= 10;
    $args->{max_comments_per_bubble} ||= 8;
    my $data = {};
    eval {
        ($data->{head}, $data->{div}, $data->{script}) = &make_map($args); 
    };
    return $ctx->error($@) if $@;
    $ctx->stash('comment_map', $data);
    return $data->{head};
}

sub comment_map_div { return $_[0]->stash('comment_map')->{div}; }

sub comment_map_script { return $_[0]->stash('comment_map')->{script}; }

sub template {
    my $tmpl = <<'EOT';
    <div class="setting">
    <p>You can get a key at <a href="http://maps.google.com/apis/maps/signup.html">http://maps.google.com/apis/maps/signup.html</a> </p> 
    <div class="label"><label for="google_api_key">GMaps API Key:</label></div>
    <div class="field">
    <input type="text" name="google_api_key" id="google_api_key" value="<TMPL_VAR NAME=GOOGLE_API_KEY>" size="60" />
    </div> 
    </div>
EOT
}

sub bubble {
    my $tmpl = <<'EOT';
    <p><b><TMPL_VAR NAME=CITY></b></p>
    <TMPL_LOOP NAME=COMMENTS>
    <a href="<TMPL_VAR NAME=COMMENT_PERMALINK>"><TMPL_VAR NAME=COMMENT_AUTHOR></a> on <a href="<TMPL_VAR NAME=ENTRY_PERMALINK>"><TMPL_VAR NAME=ENTRY_TITLE></a><br/>
    </TMPL_LOOP>
EOT
}

1;
