#!/usr/bin/perl
package tracker;
use strict;

use Carp; 
$Carp::Verbose = 1; 

$ENV{PATH} = "/bin:/usr/bin";
delete @ENV{ 'IFS', 'CDPATH', 'ENV', 'BASH_ENV' };

use FindBin;
use lib "$FindBin::Bin/../";
use lib "$FindBin::Bin/../DADA/perllib";

BEGIN {
    my $b__dir = ( getpwuid($>) )[7] . '/perl';
    push @INC, $b__dir . '5/lib/perl5', $b__dir . '5/lib/perl5/x86_64-linux-thread-multi', $b__dir . 'lib',
      map { $b__dir . $_ } @INC;
}

use DADA::Config 8.0.0 qw(!:DEFAULT);
use DADA::Template::HTML;
use DADA::App::Guts;
use DADA::MailingList::Settings;
use DADA::Logging::Clickthrough;
use DADA::MailingList::Archives;
use Try::Tiny;

my $Plugin_Config = {};
$Plugin_Config->{Plugin_Name}    = 'Tracker';
$Plugin_Config->{Plugin_URL}     = $DADA::Config::S_PROGRAM_URL . '/plugins/tracker/';
$Plugin_Config->{GeoIP_Db}       = 'data/GeoIP.dat';
$Plugin_Config->{GeoLiteCity_Db} = 'data/GeoLiteCity.dat';

&init_vars;

run()
  unless caller();

sub init_vars {

    # DEV: This NEEDS to be in its own module - perhaps DADA::App::PluginHelper or something?

    while ( my $key = each %$Plugin_Config ) {
        if ( exists( $DADA::Config::PLUGIN_CONFIGS->{Tracker}->{$key} ) ) {
            if ( defined( $DADA::Config::PLUGIN_CONFIGS->{Tracker}->{$key} ) ) {
                $Plugin_Config->{$key} =
                  $DADA::Config::PLUGIN_CONFIGS->{Tracker}->{$key};
            }
        }
    }
}

my $list;
my $ls;
my $rd;
my $mja;
my $root_login;

sub reset_globals {
    $list       = undef;
    $ls         = undef;
    $rd         = undef;
    $mja        = undef;
    $root_login = 0;
}

sub run {

    my $q = shift;

    my $admin_list;
    my $checksout;
    my $error_msg;

    ( $admin_list, $root_login, $checksout, $error_msg ) = check_list_security(
        -cgi_obj  => $q,
        -Function => 'tracker'
    );
    if ( !$checksout ) {
        return ( {}, $error_msg );
    }

    $list = $admin_list;
    $ls   = DADA::MailingList::Settings->new( { -list => $list } );
    $rd   = DADA::Logging::Clickthrough->new( { -list => $list } );
    $mja  = DADA::MailingList::Archives->new( { -list => $list } );

    my $prm = $q->param('prm') || undef;
    my %Mode = (
        'default'                               => \&default,
        'm'                                     => \&message_report,
        'edit_prefs'                            => \&edit_prefs,
        'save_view_count_prefs'                 => \&save_view_count_prefs,
        'download_logs'                         => \&download_logs,
		'export_page'                           => \&export_page, 
        'ajax_delete_log'                       => \&ajax_delete_log,
        'message_history_html'                  => \&message_history_html,
        'message_history_json'                  => \&message_history_json,
        'delete_msg_id_data'                    => \&delete_msg_id_data,
        'download_clickthrough_logs'            => \&download_clickthrough_logs,
        'download_activity_logs'                => \&download_activity_logs,
        'country_geoip_table'                   => \&country_geoip_table,
        'country_geoip_json'                    => \&country_geoip_json,
        'individual_country_geoip_json'         => \&individual_country_geoip_json,
        'individual_country_geoip_report_table' => \&individual_country_geoip_report_table,
        'data_over_time_json'                   => \&data_over_time_json,
        'message_email_report_table'            => \&message_email_report_table,
        'message_email_report_export_csv'       => \&message_email_report_export_csv,
        'email_stats_json'                      => \&email_stats_json,
        'user_agent_json'                       => \&user_agent_json, 
        'clear_data_cache'                      => \&clear_data_cache,
        'clear_message_data_cache'              => \&clear_message_data_cache,
        'export_subscribers'                    => \&export_subscribers,

        'message_email_activity_listing_table'           => \&message_email_activity_listing_table,
        'message_individual_email_activity_report_table' => \&message_individual_email_activity_report_table,
        'message_individual_email_activity_csv'          => \&message_individual_email_activity_csv,
        'the_basics_piechart_json'                       => \&the_basics_piechart_json,
    );
    if ( exists( $Mode{$prm} ) ) {
        return $Mode{$prm}->($q);    #call the correct subroutine
    }
    else {
        return default($q);
    }

}

sub default {

    my $q = shift;

    require DADA::MailingList::Subscribers;
    my $lh = DADA::MailingList::Subscribers->new( { -list => $list } );

	require HTML::Menu::Select; 
    my $tracker_record_view_count_widget = HTML::Menu::Select::popup_menu(
        {
			id      => 'tracker_record_view_count',
	        name    => 'tracker_record_view_count',
	        values  => [qw(5 10 15 20 25 50 75 100)],
	        default => $ls->param('tracker_record_view_count'),
		}
    );
    eval {
        require URI::Find;
        require HTML::LinkExtor;
    };
    my $can_use_auto_redirect_tag = 1;
    if ($@) {
        $can_use_auto_redirect_tag = 0;
    }

    require DADA::ProfileFieldsManager;
    my $dpfm          = DADA::ProfileFieldsManager->new;
    my $field_attr    = $dpfm->get_all_field_attributes;
    my $geo_ip_fields = [];

# thawed_geo_ip_profile_field_settings
#    warn '$ls->param(\'tracker_update_profile_fields_ip_dada_meta\') ' . $ls->param('tracker_update_profile_fields_ip_dada_meta');

    my $thawed_gip = {};

    my $meta = $ls->param('tracker_update_profile_fields_ip_dada_meta');

    if ( length($meta) > 4 ) {
        $thawed_gip = $ls->_dd_thaw($meta);
    }
    require Geo::IP::PurePerl;
    my $gi = Geo::IP::PurePerl->new( $Plugin_Config->{GeoLiteCity_Db} );
    my (
        $country_code, $country_code3, $country_name, $region,     $city,
        $postal_code,  $latitude,      $longitude,    $metro_code, $area_code
    ) = $gi->get_city_record( $rd->remote_addr );

    my $geo_ip_data_order = [
        qw(
          ip_address
          country_code
          country_code3
          country_name
          region
          city
          postal_code
          latitude
          longitude
          metro_code
          area_code
		  unix_time_stamp
          )
    ];

    my $geo_ip_data_types = {
        'ip_address'      => 'IP Address     (' . $rd->remote_addr . ')',
        'country_code'    => 'Country Code 2 (' . $country_code . ')',
        'country_code3'   => 'Country Code 3 (' . $country_code3 . ')',
        'country_name'    => 'Country Name   (' . $country_name . ')',
        'region'          => 'Region         (' . $region . ')',
        'city'            => 'City           (' . $city . ')',
        'postal_code'     => 'Postal Code    (' . $postal_code . ')',
        'latitude'        => 'Latitude       (' . $latitude . ')',
        'longitude'       => 'Longitude      (' . $longitude . ')',
        'metro_code'      => 'Metro Code     (' . $metro_code . ')',
        'area_code'       => 'Area Code      (' . $area_code . ')',
		'unix_time_stamp' => 'Unix Timestamp (' . time .')',
    };
    my $field_names = [];
	require HTML::Menu::Select; 
    for ( @{ $dpfm->fields( { -show_hidden_fields => 1, } ) } ) {
        push(
            @$field_names,
            {
                name       => $_,
                label      => $field_attr->{$_}->{label},
                enabled    => $thawed_gip->{$_}->{enabled},
                popup_menu => HTML::Menu::Select::popup_menu(
                    { 
						default => $thawed_gip->{$_}->{geoip_data_type},
	                    name    => $_ . '.geoip_data_type',
	                    id      => $_ . '.geoip_data_type',
	                    values  => $geo_ip_data_order,
	                    labels  => $geo_ip_data_types,
					}
                )
            }
        );
    }
	
	my $tracker_tracking_mode = ''; 
	if(
		$ls->param('tracker_track_email') == 1
		&& $DADA::Config::PII_OPTIONS->{allow_logging_emails_in_analytics} == 1
	){ 
		$tracker_tracking_mode = 'email_address'; 
	}
	elsif ($ls->param('tracker_track_anonymously') == 1){ 
		$tracker_tracking_mode = 'anonymously'; 
	}
	else { 
		$tracker_tracking_mode = 'anonymously'; 
	}

	# warn '$tracker_tracking_mode: ' . $tracker_tracking_mode; 
	
	
	my $remove_after_timespan_vals = [
	'1m',
	'2m',
	'3m',
	'4m',
	'5m',
	'6m',
	'7m',
	'8m',
	'9m',
	'10m',
	'11m',
	'1y',
	'2y',
	'3y',
	'4y',
	'5y'];

	my $remove_after_timespan_ops = { 
		'1m'  => '1 month',
		'2m'  => '2 months',
		'3m'  => '3 months',
		'4m'  => '4 months',
		'5m'  => '5 months',
		'6m'  => '6 months',
		'7m'  => '7 months',
		'8m'  => '8 months',
		'9m'  => '9 months',
		'10m' => '10 months',
		'11m' => '11 months',
		'1y'  => '1 year',
		'2y'  => '2 years',
		'3y'  => '3 years',
		'4y'  => '4 years',
		'5y'  => '5 years',
	};
	my $tracker_data_auto_remove_after_timespan_menu = HTML::Menu::Select::popup_menu(
        {
            name  => 'tracker_data_auto_remove_after_timespan',
            id    => 'tracker_data_auto_remove_after_timespan',
            values => $remove_after_timespan_vals,
			labels => $remove_after_timespan_ops, 
			default => $ls->param('tracker_data_auto_remove_after_timespan'), 
		}
    );
	
	
	my $can_use_DateTime = can_use_DateTime(); 
	
    require DADA::Template::Widgets;
    my $scrn = DADA::Template::Widgets::wrap_screen(
        {
            -screen         => 'plugins/tracker/default.tmpl',
            -with           => 'admin',
            -wrapper_params => {
                -Root_Login => $root_login,
                -List       => $ls->param('list'),
            },
            -vars => {
                screen                           => 'using_tracker',
				root_login                       => $root_login,
                done                             => scalar $q->param('done') || 0,
                Plugin_URL                       => $Plugin_Config->{Plugin_URL},
                tracker_record_view_count_widget => $tracker_record_view_count_widget,
                can_use_auto_redirect_tag        => $can_use_auto_redirect_tag,
				can_use_DateTime                 => $can_use_DateTime, 
                num_subscribers                  => commify( $lh->num_subscribers ),
                field_names                      => $field_names,
				
				tracker_tracking_mode            => $tracker_tracking_mode, 
				
				tracker_data_auto_remove_after_timespan_menu => $tracker_data_auto_remove_after_timespan_menu, 
				
				PII_OPTIONS_allow_logging_emails_in_analytics 
					=> $DADA::Config::PII_OPTIONS->{allow_logging_emails_in_analytics},
            },
            -list_settings_vars_param => {
                -list   => $list,
                -dot_it => 1,
            },
        }
    );
    return ( {}, $scrn );

}




sub percent {
    my ( $num, $total ) = @_;

    my $percent = ( $total ? $num / $total : undef );
    $percent = $percent * 100;
    $percent = sprintf( "%.2f", $percent );
    return $percent;
}

sub message_history_json {
    my $q = shift;

    my $page = $q->param('page') || 1;
    my $type = $q->param('type') || 'number';

    return $rd->message_history_json(
        {
            -page     => $page,
            -type     => $type,
            -printout => 0
        }
    );
}

sub delete_msg_id_data {

    my $q = shift;

    my $mid = $q->param('mid');
    $rd->delete_msg_id_data(
        {
            -mid => $mid,
        }
    );
    return ( {}, undef );
}

# This seems pretty ...universal
sub every_nth {
    my $array_ref = shift;
    my $nth = shift || 10;

    if ( $nth < 0 ) {
        return $array_ref;
    }
    if ( scalar(@$array_ref) < $nth ) {
        return $array_ref;
    }

    my $index = int( scalar(@$array_ref) / $nth );
    my $count = 0;
    my @group = ();
    for (@$array_ref) {

        unless ( $count % $index ) {
            push( @group, $_ );
        }
        $count++;
    }

    return [@group];
}

sub data_over_time_json {
    my $q     = shift;
    my $mid   = $q->param('mid');
    my $type  = $q->param('type');
    my $label = $q->param('label');

    return $rd->data_over_time_json(
        {
            -mid      => $mid,
            -type     => $type,
            -label    => $label,
            -printout => 0
        }
    );

}

sub message_email_report_table {
    my $q    = shift;
    my $mid  = $q->param('mid');
    my $type = $q->param('type') || 'soft_bounce';
    return $rd->message_email_report_table(
        {
            -mid      => $mid,
            -type     => $type,
            -printout => 0,
            -vars     => {
                Plugin_URL => $Plugin_Config->{Plugin_URL},
                mid        => $mid,
                type       => $type,
            }
        }
    );
}

sub message_email_report_export_csv {
    my $q    = shift;
    my $mid  = $q->param('mid');
    my $type = $q->param('type') || 'soft_bounce';
    return $rd->message_email_report_export_csv(
        {
            -mid  => $mid,
            -type => $type,
        }
    );
}

sub email_stats_json {
    my $q    = shift;
    my $mid  = $q->param('mid');
    my $type = $q->param('type') || 'soft_bounce';
    return $rd->email_stats_json(
        {
            -mid      => $mid,
            -type     => $type,
            -printout => 0,
        }
    );

}


sub user_agent_json { 
    my $q    = shift;
    my $mid  = $q->param('mid');
    my $type = $q->param('type');
    return $rd->user_agent_json(
        {
            -mid      => $mid,
            -type     => $type,
            -printout => 0,
        }
    );
}

sub clear_data_cache {
    require DADA::App::DataCache;
    my $dc = DADA::App::DataCache->new;
    $dc->flush(
        {
            -list => $list
        }
    );
    return ( { -redirect_uri => $Plugin_Config->{Plugin_URL} . '?done=1' }, undef );
}

sub clear_message_data_cache {
    my $q = shift;
    require DADA::App::DataCache;
    my $dc = DADA::App::DataCache->new;
    $dc->flush(
        {
            -list   => $list,
            -msg_id => xss_filter( strip( scalar $q->param('msg_id') ) ),
        }
    );
    return (
        {
                -redirect_uri => $Plugin_Config->{Plugin_URL}
              . '?prm=m&mid='
              . xss_filter( strip( scalar $q->param('msg_id') ) )
        },
        undef
    );
}

sub export_subscribers {

    my $q    = shift;
    my $mid  = xss_filter( scalar $q->param('mid') );
    my $type = xss_filter( scalar $q->param('type') );
    if (   $type ne 'clickthroughs'
        && $type ne 'opens'
        && $type ne 'abuse_reports' )
    {
        $type = 'clickthroughs';
    }

    return $rd->export_by_email(
        {
            -type => $type,
            -mid  => $mid,

            #-fh   => \*STDOUT
            #-printout => 0,
        }
    );

}

sub message_email_activity_listing_table {
    my $q   = shift;
    my $mid = xss_filter( scalar $q->param('mid') );
    return $rd->message_email_activity_listing_table(
        {
            -mid  => $mid,
            -vars => {
                mid  => $mid,
                type => 'email_activity',
            }
        }
    );
}

sub message_individual_email_activity_report_table {
    my $q     = shift;
    my $mid   = xss_filter( scalar $q->param('mid') );
    my $email = xss_filter( scalar $q->param('email') );
    return $rd->message_individual_email_activity_report_table(
        {
            -mid        => $mid,
            -email      => $email,
            -plugin_url => $Plugin_Config->{Plugin_URL},

        }
    );
}

sub message_individual_email_activity_csv {
    my $q        = shift;
    my $mid      = xss_filter( scalar $q->param('mid') );
    my $email    = xss_filter( scalar $q->param('email') );
    my $fn_email = $email;
    $fn_email =~ s/\@/_at_/;

    return $rd->message_individual_email_activity_csv(
        {
            -mid   => $mid,
            -email => $email,

            #-fh   => \*STDOUT,
        }
    );
}

sub the_basics_piechart_json {
    my $q     = shift;
    my $mid   = xss_filter( scalar $q->param('mid') );
    my $type  = xss_filter( scalar $q->param('type') );
    my $label = xss_filter( scalar $q->param('label') );

    return $rd->msg_basic_event_count_json(
        {
            -mid      => $mid,
            -type     => $type,
            -label    => $label,
            -printout => 0,
        }
    );
}

sub message_history_html {

    my $q = shift;
    my $page = $q->param('page') || 1;
	my $fake = $q->param('fake') || 0; 


    require DADA::Template::Widgets;
    my $html;


    require DADA::App::DataCache;
    my $dc = DADA::App::DataCache->new;

	if($fake != 1) {
	    $html = $dc->retrieve(
	        {
	            -list    => $list,
	            -name    => 'message_history_html',
	            -page    => $page,
	            -entries => $ls->param('tracker_record_view_count'),
	        }
	    );
	}
    if ( defined($html) ) {
        # warn 'message_history_html cached in file';
    }

    if ( !defined($html) ) {

        my ( $total, $msg_ids ) = $rd->get_all_mids(
            {
                -page    => $page,
                -entries => $ls->param('tracker_record_view_count'),
            }
        );

        require Data::Pageset;
        my $page_info = Data::Pageset->new(
            {
                'total_entries'    => $total,
                'entries_per_page' => $ls->param('tracker_record_view_count'),    # needs to be tweakable...
                'current_page'     => $page,
                'mode'             => 'slide',                                    # default fixed
            }
        );

        my $pages_in_set = [];
        foreach my $page_num ( @{ $page_info->pages_in_set() } ) {
            if ( $page_num == $page_info->current_page() ) {
                push( @$pages_in_set, { page => $page_num, on_current_page => 1 } );
            }
            else {
                push( @$pages_in_set, { page => $page_num, on_current_page => undef } );
            }
        }

        my $report_by_message_id = $rd->report_by_message_index(
            {
                -all_mids => $msg_ids,    #Strange speedup
                -page     => $page,
				-fake     => $fake, 
            }
        ) || [];


		# COMMIFY!
		for my $this_id(@{$report_by_message_id}){ 
			# And uh: THIS: 
			$this_id->{Plugin_URL} = $Plugin_Config->{Plugin_URL};
					}
		#use Data::Dumper; 
		#my $report_by_message_id_dump = Dumper($report_by_message_id);
		
		
        require DADA::Template::Widgets;
        $html = DADA::Template::Widgets::screen(
            {
                -screen => 'plugins/tracker/clickthrough_table.tmpl',
                -vars   => {
					page                    => $page,
                    report_by_message_index => $report_by_message_id,
                    first_page              => $page_info->first_page(),
                    last_page               => $page_info->last_page(),
                    next_page               => $page_info->next_page(),
                    previous_page           => $page_info->previous_page(),
                    pages_in_set            => $pages_in_set,
                    Plugin_URL              => $Plugin_Config->{Plugin_URL},
					#report_by_message_id_dump => $report_by_message_id_dump, 
                },
                -list_settings_vars_param => {
                    -list   => $list,
                    -dot_it => 1,
                },
            }
        );
		if($fake != 1) { 
	        $dc->cache(
	            {
	                -list    => $list,
	                -name    => 'message_history_html',
	                -page    => $page,
	                -entries => $ls->param('tracker_record_view_count'),
	                -data    => \$html,
	            }
	        );
		}
    }
    return ( {}, $html );

}

sub download_logs {

    my $q    = shift;
    my $type = xss_filter( scalar $q->param('log_type') );
    if ( $type ne 'clickthrough' && $type ne 'activity' ) {
        $type = 'clickthrough';
    }
    my $headers = {
        'Content-disposition' => 'attachment; filename=' . $list . '-' . $type . '.csv',
        -type                 => 'text/csv',
    };
    my $r = $rd->export_logs(
        {
            -type => $type,

            #-fh   => \*STDOUT
        }
    );
    return ( $headers, $r );
}


sub export_page { 
    my $q    = shift;
    my $page = xss_filter( scalar $q->param('page') ) || 1;

    my $headers = {
        'Content-disposition' => 'attachment; filename=' . $list . '-' . 'page' . '.csv',
        -type                 => 'text/csv',
    };

	
    my ( $total, $msg_ids ) = $rd->get_all_mids(
        {
            -page    => $page,
            -entries => $ls->param('tracker_record_view_count'),
        }
    );
	
    my $report_by_message_id = $rd->report_by_message_index(
        {
            -all_mids => $msg_ids,    #Strange speedup
            -page     => $page,
			#-fake     => $fake, 
        }
    ) || [];
	
	my $labels = [qw(

		date
		msg_id

		message_subject

		num_subscribers
		total_recipients
		delivered_to

		received
		received_percent
		
		open
		unique_open
		unique_opens_percent
		
		clickthroughs
		unique_clickthroughs
		unique_clickthroughs_percent
		
		view_archive
		forward_to_a_friend
		
		unsubscribe
		unique_unsubscribes_percent
		
		errors_sending_to
		errors_sending_to_percent
		
		abuse_report
		
		unique_bounces_percent
		
		soft_bounce
		unique_soft_bounces_percent
		
		hard_bounce
		unique_hard_bounces_percent
		
	)];
	
    require Text::CSV;
    my $csv = Text::CSV->new($DADA::Config::TEXT_CSV_PARAMS);
	my $header_status = $csv->combine(@$labels);
	my $r = $csv->string();
	$r .= "\n";
	
	for my $rbmi(@$report_by_message_id){
		my $fields = []; 
		for my $h(@$labels){ 
			if($h eq 'clickthroughs'){ 
				push(@$fields, $rbmi->{count}); # this is because, "count" is being translated to, "clickthroughs"
			}else { 
				push(@$fields, $rbmi->{$h});
			}
		}
	    my $status = $csv->combine(@$fields); # combine columns into a string
	    $r        .= $csv->string();   # get the combined string
		$r        .= "\n";
	}
 
    return ( $headers, $r );
}

sub download_clickthrough_logs {

    my $q       = shift;
    my $mid     = xss_filter( scalar $q->param('mid') );
    my $headers = {
        '-Content-disposition' => 'attachment; filename=' . $list . '-clickthrough-' . $mid . '.csv',
        -type                  => 'text/csv',
    };
    my $r = $rd->export_logs(
        {
            -type => 'clickthrough',
            -mid  => $mid,

            #-fh   => \*STDOUT
        }
    );
    return ( $headers, $r );
}

sub download_activity_logs {

    my $q       = shift;
    my $mid     = xss_filter( scalar $q->param('mid') );
    my $headers = {
        'Content-disposition' => 'attachment; filename=' . $list . '-activity-' . $mid . '.csv',
        -type                 => 'text/csv',
    };

    my $r = $rd->export_logs(
        {
            -type => 'activity',
            -mid  => $mid,
            -fh   => \*STDOUT
        }
    );
    return ( $headers, $r );

}

sub ajax_delete_log {
    $rd->purge_log;
    return ( {}, undef );
}

sub save_view_count_prefs {

    my $q = shift;
    $ls->save_w_params(
        {
            -associate => $q,
            -settings  => {
                tracker_record_view_count => 0,
            }
        }
    );
    require DADA::App::DataCache;
    my $dc = DADA::App::DataCache->new;
    $dc->flush(
        {
            -list => $list
        }
    );
    return ( {}, undef );
}

sub edit_prefs {

    my $q = shift;
	my $also_save_for_list = $ls->also_save_for_list($q);
	
	if($q->param('tracker_tracking_mode') eq 'email_address'
		&& $DADA::Config::PII_OPTIONS->{allow_logging_emails_in_analytics} == 1){
		$q->param('tracker_track_email', 1);
		$q->param('tracker_track_anonymously', 0);
		
	}
	if($q->param('tracker_tracking_mode') eq 'anonymously'){
		$q->param('tracker_track_email', 0);
		$q->param('tracker_track_anonymously', 1);
	}
	$q->delete('tracker_tracking_mode'); 
	
    $ls->save_w_params(
        {
            -associate => $q,
            -settings  => {
                tracker_auto_parse_links                        => 0,
                tracker_auto_parse_mailto_links                 => 0,
                tracker_track_opens_method                      => undef,
                tracker_track_email                             => 0,
				tracker_track_anonymously                       => 0, 
				tracker_show_location_data                      => 0,
				tracker_show_maps_in_reports                    => 0, 
                tracker_clean_up_reports                        => 0,
                tracker_show_message_reports_in_mailing_monitor => 0,
                tracker_update_profiles_w_geo_ip_data           => 0,
				tracker_send_analytics_email_notification       => 0, 
				tracker_data_auto_remove                        => 0, 
				tracker_data_auto_remove_after_timespan         => undef, 
				tracker_protect_tracked_links_from_prefetching  => 0, 
            },
			-also_save_for => $also_save_for_list,
        }
    );

    my $tracker_update_profiles_geo_ip_data = {};
    require DADA::ProfileFieldsManager;
    my $dpfm = DADA::ProfileFieldsManager->new;
    for ( @{ $dpfm->fields( { -show_hidden_fields => 1, } ) } ) {
        my $enabled         = $q->param( $_ . '.enabled' )         || 0;
        my $geoip_data_type = $q->param( $_ . '.geoip_data_type' ) || '';
        $tracker_update_profiles_geo_ip_data->{$_} = {
            enabled         => $enabled,
            geoip_data_type => $geoip_data_type,
        };
    }
#    warn '$ls->_dd_freeze($tracker_update_profiles_geo_ip_data)'
#      . $ls->_dd_freeze($tracker_update_profiles_geo_ip_data);

    $ls->save({ -settings =>
        {
            tracker_update_profile_fields_ip_dada_meta => $ls->_dd_freeze($tracker_update_profiles_geo_ip_data)
        }
    });

    require DADA::App::DataCache;
    my $dc = DADA::App::DataCache->new;
    $dc->flush( { -list => $list } );
    return ( { -redirect_uri => $Plugin_Config->{Plugin_URL} . '?done=1' }, undef );
}

sub message_report {

    my $q   = shift;
    my $mid = $q->param('mid');
    $mid =~ s/\.(.*?)$//;
    $q->param( 'mid', $mid );

    my $chrome = 1;
    if ( defined( $q->param('chrome') ) ) {
        $chrome = $q->param('chrome') || 0;
    }
    my $Plugin_Url = $Plugin_Config->{Plugin_URL};
    if ( defined( $q->param('tracker_url') ) ) {
        $Plugin_Url = $q->param('tracker_url');
    }
    
	my $m_report = $rd->report_by_message( $q->param('mid') );
	my %tmpl_vars = (); 

	#use Data::Dumper; 
	#warn '$m_report' . Dumper($m_report);
	
	# Hmm, a little fishy: 
	if(
		(! defined($m_report->{num_subscribers}) || $m_report->{num_subscribers} == 0) 
		&&
		(! defined($m_report->{total_recipients}) || $m_report->{total_recipients} == 0) 
		&&
		(! defined($m_report->{received}) || $m_report->{received} == 0) 
	){ 		
		$tmpl_vars{has_data} = 0; 
	}
	else  { 
	
	    # This is strange, as we have to first break it out of the data structure,
	    # and stick it back in:

	    my $u_url_report = {};
	    foreach ( @{ $m_report->{url_report} } ) {
	        $u_url_report->{ $_->{url} } = $_->{count};
	    }
	    my $s_url_report = [];
	    foreach my $v (
	        sort { $u_url_report->{$b} <=> $u_url_report->{$a} }
	        keys %$u_url_report
	      )
	    {
	        push( @$s_url_report, { url => $v, count => $u_url_report->{$v} } );
	    }

	    %tmpl_vars = (

	        screen => 'using_tracker',
			has_data             => 1,
	        mid                  => scalar $q->param('mid')                         || '',
			# This needs to be updated, to grab the subject from the activity table
	        subject              => $rd->fetch_message_subject( $q->param('mid') )  || '',
	        url_report           => $s_url_report                            || [],
	        Plugin_URL           => $Plugin_Url,
	        Plugin_Name          => $Plugin_Config->{Plugin_Name},
	        chrome               => $chrome,
			a_in_t               => 1, 
			%$m_report, 
		

	    );
	}
    my $scrn = '';
    require DADA::Template::Widgets;

    if ( $chrome == 0 ) {
        $scrn = DADA::Template::Widgets::screen(
            {
                -screen => 'plugins/tracker/message_report.tmpl',
                -vars   => { %tmpl_vars, },
            },
            -list_settings_vars_param => {
                -list   => $list,
                -dot_it => 1,
            },
           
        );
    }
    else {
        $scrn = DADA::Template::Widgets::wrap_screen(
            {
                -screen         => 'plugins/tracker/message_report.tmpl',
                -with           => 'admin',
                -wrapper_params => {
                    -Root_Login => $root_login,
                    -List       => $ls->param('list'),
                },
                -vars => { %tmpl_vars, },
	            -list_settings_vars_param => {
	                -list   => $list,
	                -dot_it => 1,
	            },
            },
           
        );
    }
    return ( {}, $scrn );

}

sub country_geoip_table {

    my $q     = shift;
    my $mid   = $q->param('mid') || undef;
    my $type  = $q->param('type') || undef;
    my $label = $q->param('label') || undef;

    my $html;

    require DADA::App::DataCache;
    my $dc = DADA::App::DataCache->new;

    $html = $dc->retrieve(
        {
            -list => $list,
            -name => 'country_geoip_table' . '.' . $mid . '.' . $type,
        }
    );
    if ( !defined($html) ) {

        my $report = $rd->country_geoip_data(
            {
                -mid   => $mid,
                -type  => $type,
                -label => $label,
                -db    => $Plugin_Config->{GeoIP_Db},
            }
        );
        for (@$report) {
            $_->{type} = $type;
        }
        require DADA::Template::Widgets;
        $html = DADA::Template::Widgets::screen(
            {
                -screen => 'plugins/tracker/country_geoip_table.tmpl',
                -vars   => {
                    c_geo_ip_report => $report,
                    type            => $type,
                    label           => $label,

                }
            }
        );
        $dc->cache(
            {
                -list => $list,
                -name => 'country_geoip_table' . '.' . $mid . '.' . $type,
                -data => \$html,
            }
        );
    }

    return ( {}, $html );

}

sub country_geoip_json {

    my $q    = shift;
    my $mid  = $q->param('mid') || undef;
    my $type = $q->param('type') || undef;

    my $labels = {
        clickthroughs       => 'Clickthroughs',
        opens               => 'Opens',
        forward_to_a_friend => 'Forwards',
        view_archive        => 'Archive Views',
    };
    return $rd->country_geoip_json(
        {
            -mid      => $mid,
            -type     => $type,
            -db       => $Plugin_Config->{GeoIP_Db},
            -label    => $labels->{$type},
            -printout => 0,
        }
    );
}

sub individual_country_geoip_json {

    my $q       = shift;
    my $mid     = $q->param('mid') || undef;
    my $type    = $q->param('type') || undef;
    my $country = $q->param('country') || undef;

    $rd->individual_country_geoip_json(
        {
            -mid      => $mid,
            -type     => $type,
            -db       => $Plugin_Config->{GeoLiteCity_Db},
            -country  => $country,
            -printout => 0,
        }
    );
}

sub individual_country_geoip_report {

    my $q       = shift;
    my $mid     = $q->param('mid') || undef;
    my $type    = $q->param('type') || undef;
    my $country = $q->param('country') || undef;

    return $rd->individual_country_geoip_report(
        {
            -mid      => $mid,
            -type     => $type,
            -db       => $Plugin_Config->{GeoLiteCity_Db},
            -country  => $country,
            -printout => 0,
        }
    );
}

sub individual_country_geoip_report_table {

    my $q       = shift;
    my $mid     = $q->param('mid') || undef;
    my $type    = $q->param('type') || undef;
    my $country = $q->param('country') || undef;
    my $chrome  = $q->param('chrome') || 0;

    return $rd->individual_country_geoip_report_table(
        {
            -mid       => $mid,
            -type      => $type,
            -db        => $Plugin_Config->{GeoLiteCity_Db},
            -country   => $country,
            -chrome    => $chrome,
            -printout  => 0,
            Plugin_URL => $Plugin_Config->{Plugin_URL},
        }
    );
}




sub commify {
    local $_ = shift;
    1 while s/^(-?\d+)(\d{3})/$1,$2/;
    return $_;
}

1;

=pod

=head1 Tracker

The Tracker plugin creates analytic reports of activity of your mass mailings. You can think of a mass mailing being a B<campaign> if you'd like and the Tracker plugin being what presents data on your campaign.  

The activities that are logged and reported include: 

=over

=item * # subscribers when a mass mailing was sent out

=item * # of recorded clickthroughs 

=item * # of recorded opens/views

=item * # of unsubscribes

=item * # bounces, both soft and hard

=back

=head1 User Guide

For a guide on using Tracker, see the B<Dada Mail Manual>: 

L<https://dadamailproject.com/pro_dada/using_tracker.html>

For more information on Pro Dada/Dada Mail Manual: 

L<https://dadamailproject.com/purchase/pro.html>

=head2 Birds-Eye View

These reports include the above information in tabular data, as well 
as in a line graph, for past mass mailings to help you spot general trends. 
This information can also be exported into .csv files, giving you more flexibility, specific to your needs. 


=head2 Individual Messages/Campaigns

Along with the birds-eye view of seeing data of many messages at once, each mass mailing/campaign can also be explored.

=over

=item * Clickthroughs are broken down per # of clicks per link

=item * Clickthroughs are also broken down by country of origin, displayed in both a  table and map. 

=item * Message opens are also broken down by country of origin and displayed both in  a table and map. 

=item * Bounces, both soft and hard bounces are listed by date and email address of the bouncee. 

Clicking on the email address will allow you to view the data about the bounced message itself in the bounce handler plugin. 

I<(No bounces will be recorded, unless you've separately set up and 
installed the Bounce Handler plugin that comes with Dada Mail)> 

If you suddenly get a ton of bounced messages for a mailing from addresses you know  look legitimate, there's a good chance that something seriously went wrong in the  delivery part of a mass mailing. The reports that the Tracker plugin links to may help in resolving this problem. 

=back

All this message-specific data can also be exported via .csv files that may be downloaded. 

What's below will go into installing the plugin and advanced configuration.

=head1 Installing tracker

This plugin can be installed during a Dada Mail install/upgrade, using the included installer that comes with Dada Mail. The below installation instructions go through how to install the plugin manually.

The tracker plugin comes with Dada Mail. You'll find it in the, I<dada/plugins> directory with the file name, I<tracker> 

Change its permission to, C<755>. 

=head2 List Control Panel Menu

Now, edit your C<.dada_config> file, so that it shows the Tracker in the left-hand menu, under the, B<Plugins> heading: 

First, see if the following lines are present in your C<.dada_config> file: 

 # start cut for list control panel menu
 =cut

 =cut
 # end cut for list control panel menu

If they are, remove them. 

Then, find these lines: 

 #					{
 #					-Title      => 'Tracker',
 #					-Title_URL  => $S_PROGRAM_URL."/tracker",
 #					-Function   => 'tracker',
 #					-Activated  => 1,
 #					},

Uncomment the lines, by taking off the, "#"'s: 

 					{
 					-Title      => 'Tracker',
 					-Title_URL  => $S_PROGRAM_URL."/tracker",
 					-Function   => 'tracker',
 					-Activated  => 1,
 					},

Save your C<.dada_config> file.


=head1 Specific Plugin Config Variables

These variables have defaults saved in this plugin itself, but encourage you to 
reset the defaults to the values you may want, instead in your C<.dada_config> file, 
in the, C<$PLUGIN_CONFIGS> variable, under the, C<Tracker> entry

=head2 Plugin_Name

The name of this plugin 

=head2 Plugin_URL

The URL of this plugin. This is usually found by default, but sometimes the default
doesn't work correctly. If this happens to you, fill it out in this variable

=head2 GeoIP_Db

This variable holds the file path to the location ofthe GeoIP database. The GeoIP 
database is a IP Address -> Location lookup table, to quickly and easily figure out 
the location based on the IP Address. 

This database is updated monthly and new copies can be obtained at: 

L<http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz> 

The database is licensed under the LGPL, so it's OK to ship Dada Mail with a copy of 
this database. 

If you find it necessary, you may keep a copy of this database outside of Dada Mail and 
update it regularly and tell this plugin where to find the database to use. 

For more information, see:  

http://search.cpan.org/~borisz/Geo-IP-PurePerl-1.25/lib/Geo/IP/PurePerl.pm

I<This product includes GeoLite data created by MaxMind, available L<from http://www.maxmind.com/>>

=head2 GeoLiteCity_Db

Like, C<GeoIP_Db>, this variables holds the absolute file path to the City Geo IP database. Copies are obtained from, 

L<http://www.maxmind.com/download/geoip/database/GeoLiteCity.dat.xz>

=head1 Compatibility with clickthrough_tracking.cgi

The previous iteration of this plugin (tracker.cgi) was called, B<clickthrough_tracker.cgi>. Do not 
use this old plugin with anything newer than v4.5.0 of Dada Mail. It will not work correctly. 

=head2 Backwards Compatibility with the [redirect=] tag

Past versions of Dada Mail (before v4.5.0) used a different syntax for redirect URLs. 
The syntax looked like this: 

 [redirect=http://example.com]

This tag format is still supported, but consider it deprecated. 

=head2 Limitations of Redirect tags

One thing that you cannot do with the redirect tags, is embedd other Dada Mail Template Tags within the redirect tag.

This will not work: 

 <?dada redirect url="http://example.com/index.html?email=<!-- tmpl_var subscriber.email -->" ?>


=head2 Upgrade Notes

The below is information for people who have used the B<clickthrough_tracking.cgi> script in past
versions of Dada Mail (before v4.5.0) and want to take advantage of the new Tracker plugin 
and also want to move over the old logged data.

=head4 Importing Old Clickthrough Logs 

Data saved within the older, PlainText clickthrough logs would have to 
be moved over, 

There is a script called, I<dada_clickthrough_plaintext_to_sql.pl> located in the, 
I<dada/extras/scripts> directory that will do this conversion. Move it into your, 
I<dada> directory, change its permissions to, C<755> and run it I<once> in your web browser. It may take a few minutes to run to completion. 


=head1 COPYRIGHT 

Copyright (c) 1999 - 2023 Justin Simoni All rights reserved. 

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, 
Boston, MA  02111-1307, USA.

=cut
