package SaleReport::Reports;

use strict;
use warnings;
use Carp;

use lib '/app/tools/raptor/lib';
use SaleReport::ReportLib;

use lib '/app/tools/data_classes/lib';
use Client::Service;
use Client::Label;
use Product::ProductAlbum;
use Product::ProductTrack;
use Period::QuarterPeriod;
use Period::MonthPeriod;
use Period::YearPeriod;
use Artist;

use lib ('/app/tools/common/lib');
use Common::Consts qw(%URLS %CODE_TO_COUNTRY);
use Common::Util qw(commify moneyize);
use RSApache::Session;

use lib '/app/tools/stats/lib';
use Stats::Sales;

# in leiu of a "new" subroutine.
use RSApache::RSApp;
use base 'RSApache::RSApp';

use constant MAX_RECORDS      => 200;
use constant RECORDS_PER_PAGE => 20;

$| = 1;

my $Session;
my $CurrentUser;
my $Period;

my %sub_command_for = (
    "m"  => "MainReport",
    "ss" => "ServicesSummary",
    "s"  => "ServiceDetail",
    "fs" => "FormatsSummary",
    "f"  => "FormatDetail",
    "as" => "AlbumsSummary",
    "a"  => "AlbumDetail",
    "ks" => "TracksSummary",
    "k"  => "TrackDetail",
    "sf" => "ServiceFormatDetail",
    "ls" => "LabelsSummary",
    "rs" => "ArtistsSummary",
    "r"  => "ArtistDetail",
    "gs" => "GeoSummary",
);

sub execute {
    my $self = shift;
    my $current_period;
    $self->Stylesheet("reports.xsl");

    # ---------------------------------------
    # check login
    # ---------------------------------------
    $Session = new RSApache::Session();
    if ( !$Session->IsValid() ) {

        # redirect them
        $self->Redirect( $URLS{login} . "?redirect=" . $self->GetRequestString() );
        return 1;
    }

    # ---------------------------------------
    # check general access
    # ---------------------------------------
    $CurrentUser = $Session->ActiveUser;
    $self->SetNavigationAccess($CurrentUser);
    if ( $CurrentUser->CanAccess( $self->{xml}->{App} ) ) {

        # let's set all the access levels here
        $self->{xml}->{CurrentUser} = $CurrentUser->GetObjectXML();
    } else {

        # $self->Redirect($URLS{access_denied});
        $self->{xml}->{CurrentUser}  = $CurrentUser->GetObjectXML();
        $self->{xml}->{AccessDenied} = 1;
        return 1;
    }

    # load period
    #
    # we're allowing for three types of periods specified by period_type:
    # quarters, months, and years - (quarter is default)
    # The MonthPeriod, QuarterPeriod, and YearPeriod
    # classes share the same basic functions.
    # The specific period to view will be passed as "period".
    # ---------------------------------------
    my $period_type_param = $self->GetParam("period_type") || "q";
    if ( lc $period_type_param eq 'm' ) {
        $Period = new Period::MonthPeriod();
    } elsif ( lc $period_type_param eq 'q' ) {
        $Period = new Period::QuarterPeriod();
    } elsif ( lc $period_type_param eq 'y' ) {
        $Period = new Period::YearPeriod();
    } else {
        return 1;
    }

    my $period_param = $self->GetParam("period");
    if ( !length $period_param ) {

        # just get the current period
        $Period->LoadCurrent();
    } else {

        # lookup by id
        $Period->Load( period_id => $period_param );
    }

    # if no valid period then we don't have sales reports
    # to show, just return now.
    if ( !$Period->PeriodID ) {
        return 1;
    }

    $self->{xml}->{Period} = $Period->GetObjectXML();

    # ---------------------------------------
    # dispatch
    # ---------------------------------------
    my $view_param = $self->GetParam("view") || "m";
    if ($view_param) {
        my $sub_command = $sub_command_for{$view_param} || $sub_command_for{"m"};
        my $success = $self->$sub_command();
        if ( !$success ) {
            $self->AddMessageXML( type => "error", code => "fatal_error" );
        }
    }

    # setup period nav xml
    my $stats_obj = Stats::Sales->new(
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
    );
    my $periods  = $stats_obj->GetPeriodNavParams();
    my $monthMap = _getMonthMap();

    my $mEnd = $periods->{start_month};
    my $mid = $periods->{max_m} - ( $mEnd - 1 );

    my $qEnd = int( $mEnd / 3 );
    $qEnd++ if ( $mEnd % 3 );
    my $qid = $periods->{max_q} - ( $qEnd - 1 );

    for ( my $y = $periods->{max_y} ; $y >= $periods->{min_y} ; $y-- ) {
        my @item = ();
        for ( my $q = 1 ; $q <= $qEnd ; $q++ ) {
            if ( $qid < $periods->{min_q} ) {
                $qid++;
                next;
            }
            push( @item, { Name => "Q$q", ID => 'q' . $qid++ } );
        }
        for ( my $m = 1 ; $m <= $mEnd ; $m++ ) {
            if ( $mid < $periods->{min_m} ) {
                $mid++;
                next;
            }
            push( @item, { Name => $monthMap->{$m}, ID => 'm' . $mid++ } );
        }
        push(
            @{ $self->{xml}{PeriodNav}{Year} },
            {
                ID   => "y$y",
                Year => $y,
                Item => \@item,
            }
        );

        $mid -= $mEnd + 12;
        $mEnd = 12;

        $qid -= $qEnd + 4;
        $qEnd = 4;
    }

    # we always need sub label xml, unless this user is
    # limited to their own label
    my $labels = Client::Label->GetAllLabels();
    if ( !$CurrentUser->LabelID ) {
        foreach my $label_id ( sort { $labels->{$a}->{label_name} cmp $labels->{$b}->{label_name} } keys %$labels ) {
            my $pretty_name = $labels->{$label_id}->{label_name};
            if ( length $labels->{$label_id}->{label_name} > 40 ) {
                $pretty_name = substr $pretty_name, 0, 37;
                $pretty_name .= "...";
            }
            push @{ $self->{xml}->{Labels}->{Label} },
              { LabelID => $label_id, LabelName => $labels->{$label_id}->{label_name}, LabelNamePretty => $pretty_name };
        }
    }

    # label specific name
    my $label_param = $CurrentUser->LabelID || $self->GetParam("label");
    if ($label_param) {
        $self->{xml}->{Label} = { LabelID => $label_param, LabelName => $labels->{$label_param}->{label_name} };
    }

    # country info
    my $geo_map = _mapCountries( $stats_obj->GetCountryList( all => 1 ) );
    foreach my $ccode ( sort { $geo_map->{$a} cmp $geo_map->{$b} } keys %$geo_map ) {
        push @{ $self->{xml}->{Countries}->{Country} }, { Code => $ccode, Name => $geo_map->{$ccode} };
    }
    my $current_country = uc $self->GetParam('country');
    $self->{xml}->{Country} = $CODE_TO_COUNTRY{$current_country} || $current_country;

    return 1;
}

# ------------------------------------------------
# Sub Commands Within This App
# ------------------------------------------------
sub MainReport {
    my $self = shift;

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
    );
    my $stats_obj = new Stats::Sales(%params);

    my $pie_count      = 0;
    my $base_image_url = "";
    my $data           = {};
    my @pies           = ();
    my @tables         = ();

    # --------------------------
    # grand total data
    # --------------------------
    my $total_metric = {};
    $total_metric                     = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    # --------------------------
    # pie chart - top services
    # --------------------------
    my $top_services = $stats_obj->GetTopRanking( category => 'service' );
    my $service_names = Client::Service->GetAllServiceNames();

    foreach my $service_ref (@$top_services) {
        next if ( $service_ref->Revenue <= 0 );

        push @{ $data->{labels} }, $service_names->{ $service_ref->ID };
        push @{ $data->{ids} },    $service_ref->ID;
        push @{ $data->{data} },   $service_ref->Revenue;
    }

    if ( $data && defined $data->{data} ) {
        my $image_link = "view=s&" . $self->GetPartialQueryString( view => 1 ) . "&service=";
        my $pie_href = GetPieChart(
            labels         => $data->{labels},
            data           => $data->{data},
            image_map_link => $image_link,
            label_ids      => $data->{ids},
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_services";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of the image we created
        # and how many we've created
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    # --------------------------
    # pie chart - top formats
    # --------------------------
    my $top_formats = $stats_obj->GetTopRanking( category => 'format' );
    my $format_names = $stats_obj->FormatMap();
    $data = {};

    foreach my $format_ref (@$top_formats) {
        next if ( $format_ref->Revenue <= 0 );

        push @{ $data->{labels} }, $format_names->{ $format_ref->ID };
        push @{ $data->{ids} },    $format_ref->ID;
        push @{ $data->{data} },   $format_ref->Revenue;
    }

    if ( $data && defined $data->{data} ) {
        my $image_link = "view=f&" . $self->GetPartialQueryString( view => 1 ) . "&format=";
        my $pie_href = GetPieChart(
            labels         => $data->{labels},
            data           => $data->{data},
            image_map_link => $image_link,
            label_ids      => $data->{ids},
            image_src      => $base_image_url,
            chart_num      => $pie_count,
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_formats";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of dynamic images
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    # -------------------------
    # table data - top albums
    # -------------------------
    $self->_getTopProducts(
        tables    => \@tables,
        stats_obj => $stats_obj,
        prod_type => 'A',
        limit     => 10
    );

    # -------------------------
    # table data - top tracks
    # -------------------------
    $self->_getTopProducts(
        tables    => \@tables,
        stats_obj => $stats_obj,
        prod_type => 'T',
        limit     => 10
    );

    # -------------------------
    # table data - top artists
    # -------------------------
    $self->_getTopArtists(
        tables    => \@tables,
        stats_obj => $stats_obj,
        limit     => 10
    );

    # -------------------------
    # file summary
    # -------------------------
    # my $file_summary = $stats_obj->GetServiceStatus(%params);
    # $months->{$month} = substr(Date::Calc::Month_to_Text($month), 0, 3)
    my ( undef, $start_month, undef ) = split( '-', $Period->StartDate );
    my ( undef, $end_month,   undef ) = split( '-', $Period->EndDate );

    # my $fs_labels = ['Apr 2005','May 2005','Jun 2005'];
    my $fs_labels = [];
    for ( my $mon = $start_month ; $mon <= $end_month ; $mon++ ) {
        my $abbr_mon = substr( Date::Calc::Month_to_Text($mon), 0, 3 );
        push @$fs_labels, sprintf( "%s %d", $abbr_mon, $Period->Year );
    }
    my $fs_order = [ 'Service', 'Data' ];

    # my $fs_data = [ {Service => 'iTunes', Data => [0,1,0]} ];
    my $table_data = [];

    foreach my $service_id ( sort { lc $service_names->{$a} cmp lc $service_names->{$b} } keys %$service_names ) {
        next if ( $service_id == 0 );

        my $href = {};
        $href->{Service} = $service_names->{$service_id};
        $href->{Data} = $stats_obj->GetServiceFileStatus( service_id => $service_id, %params );
        push @$table_data, $href;
    }

    my $table_href = CreateTableXML( data => $table_data, order => $fs_order, labels => $fs_labels );

    if ($table_href) {
        $table_href->{TableName} = "file_summary";
        push @tables, $table_href;
    }

    $self->{xml}->{Pies}->{Pie} = \@pies;
    $self->{xml}->{Tables}->{Table} = \@tables if ( @pies or $total_metric->Revenue < 0 );
}

# ----------------------------------
# all ServiceS page (view=ss)
# ----------------------------------
sub ServicesSummary {
    my $self = shift;

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
    );
    my $stats_obj = new Stats::Sales(%params);

    my $pie_count      = 0;
    my $base_image_url = "";
    my $pie_data       = {};
    my @pies           = ();
    my @tables         = ();

    # --------------------------
    # grand total data
    # --------------------------
    my $total_metric = {};
    $total_metric                     = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    # ---------------------------------
    # pie chart - revenue by service
    # ---------------------------------
    my $top_services = $stats_obj->GetTopRanking( category => 'service' );
    my $service_names = Client::Service->GetAllServiceNames();
    $pie_data = {};
    foreach my $service_ref (@$top_services) {
        next if ( $service_ref->Revenue <= 0 );
        push @{ $pie_data->{labels} }, $service_names->{ $service_ref->ID };
        push @{ $pie_data->{ids} },    $service_ref->ID;
        push @{ $pie_data->{data} },   $service_ref->Revenue;
    }

    if ( $pie_data && defined $pie_data->{data} ) {
        my $image_link = "view=s&" . $self->GetPartialQueryString( view => 1 ) . "&service=";
        my $pie_href = GetPieChart(
            labels         => $pie_data->{labels},
            data           => $pie_data->{data},
            image_map_link => $image_link,
            label_ids      => $pie_data->{ids},
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_services";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of the image we created
        # and how many we've created
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    splice( @$top_services, 5 );

    # ---------------------------
    # table data - top 10 albums
    # ---------------------------
    $self->_getTopProducts(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        prod_type   => 'A',
        limit       => 10,
        metric_name => 'service',
        metric_list => $top_services,
        metric_hash => $service_names,
    );

    # ---------------------------
    # table data - top 10 tracks
    # ---------------------------
    $self->_getTopProducts(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        prod_type   => 'T',
        limit       => 10,
        metric_name => 'service',
        metric_list => $top_services,
        metric_hash => $service_names,
    );

    # -------------------------
    # table data - top 10 artists
    # -------------------------
    $self->_getTopArtists(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        limit       => 10,
        metric_name => 'service',
        metric_list => $top_services,
        metric_hash => $service_names,
    );

    $self->{xml}->{Pies}->{Pie}     = \@pies;
    $self->{xml}->{Tables}->{Table} = \@tables;
}

#---------------------------------------
# service specific revenue (view=s)
#---------------------------------------
sub ServiceDetail {
    my $self = shift;
    my $service_id = $self->GetParam("service") || undef;

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        service_id  => $service_id,
        country_code => $self->GetParam('country') || undef,
    );
    my $stats_obj = new Stats::Sales(%params);

    my $service_names = Client::Service->GetAllServiceNames();
    $self->{xml}->{ProductInfo}->{ServiceName} = $service_names->{$service_id};
    $self->{xml}->{ProductInfo}->{ServiceID}   = $service_id;

    my $pie_count      = 0;
    my $base_image_url = "";
    my $data           = {};
    my @pies           = ();
    my @tables         = ();

    # --------------------------
    # grand total data
    # --------------------------
    my $total_metric = {};
    $total_metric                     = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    # ---------------------------------
    # pie chart - revenue by format
    # ---------------------------------
    my $top_formats = $stats_obj->GetTopRanking( category => 'format' );
    my $format_names = $stats_obj->FormatMap();
    $data = {};

    foreach my $format_ref (@$top_formats) {
        next if ( $format_ref->Revenue <= 0 );

        push @{ $data->{labels} }, $format_names->{ $format_ref->ID };
        push @{ $data->{ids} },    $format_ref->ID;
        push @{ $data->{data} },   $format_ref->Revenue;
    }

    if ( $data && defined $data->{data} ) {
        my $image_link = "view=sf&" . $self->GetPartialQueryString( view => 1 ) . "&format=";
        my $pie_href = GetPieChart(
            labels         => $data->{labels},
            data           => $data->{data},
            image_map_link => $image_link,
            label_ids      => $data->{ids},
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_formats";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of the image we created
        # and how many we've created
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    # ---------------------------
    # table data - top 10 albums
    # ---------------------------
    $self->_getTopProducts(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        prod_type   => 'A',
        limit       => 10,
        metric_name => 'format',
        metric_list => $top_formats,
        metric_hash => $format_names,
    );

    # ---------------------------
    # table data - top 10 tracks
    # ---------------------------
    $self->_getTopProducts(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        prod_type   => 'T',
        limit       => 10,
        metric_name => 'format',
        metric_list => $top_formats,
        metric_hash => $format_names,
    );

    # -------------------------
    # table data - top 10 artists
    # -------------------------
    $self->_getTopArtists(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        limit       => 10,
        metric_name => 'format',
        metric_list => $top_formats,
        metric_hash => $format_names,
    );

    $self->{xml}->{Pies}->{Pie}     = \@pies;
    $self->{xml}->{Tables}->{Table} = \@tables;
}

#---------------------------------------
# format summary (view=fs)
#---------------------------------------
sub FormatsSummary {
    my $self = shift;

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
    );
    my $stats_obj = new Stats::Sales(%params);

    my $pie_count      = 0;
    my $base_image_url = "";
    my $data           = {};
    my @pies           = ();
    my @tables         = ();

    # --------------------------
    # grand total data
    # --------------------------
    my $total_metric = {};
    $total_metric                     = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    # ---------------------------------
    # pie chart - revenue by format
    # ---------------------------------
    my $top_formats = $stats_obj->GetTopRanking( category => 'format' );
    my $format_names = $stats_obj->FormatMap();
    $data = {};

    foreach my $format_ref (@$top_formats) {
        next if ( $format_ref->Revenue <= 0 );

        push @{ $data->{labels} }, $format_names->{ $format_ref->ID };
        push @{ $data->{ids} },    $format_ref->ID;
        push @{ $data->{data} },   $format_ref->Revenue;
    }

    if ( $data && defined $data->{data} ) {
        my $image_link = "view=f&" . $self->GetPartialQueryString( view => 1 ) . "&format=";
        my $pie_href = GetPieChart(
            labels         => $data->{labels},
            data           => $data->{data},
            image_map_link => $image_link,
            label_ids      => $data->{ids},
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_formats";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of the image we created
        # and how many we've created
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    # ---------------------------
    # table data - top 10 albums
    # ---------------------------
    $self->_getTopProducts(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        prod_type   => 'A',
        limit       => 10,
        metric_name => 'format',
        metric_list => $top_formats,
        metric_hash => $format_names,
    );

    # ---------------------------
    # table data - top 10 tracks
    # ---------------------------
    $self->_getTopProducts(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        prod_type   => 'T',
        limit       => 10,
        metric_name => 'format',
        metric_list => $top_formats,
        metric_hash => $format_names,
    );

    # -------------------------
    # table data - top 10 artists
    # -------------------------
    $self->_getTopArtists(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        limit       => 10,
        metric_name => 'format',
        metric_list => $top_formats,
        metric_hash => $format_names,
    );

    $self->{xml}->{Pies}->{Pie}     = \@pies;
    $self->{xml}->{Tables}->{Table} = \@tables;
}

#---------------------------------------
# format specific revenue (view=f)
#---------------------------------------
sub FormatDetail {
    my $self = shift;
    my $format_type = $self->GetParam("format") || undef;

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        format_type => $format_type,
        country_code => $self->GetParam('country') || undef,
    );
    my $stats_obj = new Stats::Sales(%params);

    my $format_names = $stats_obj->FormatMap();
    $self->{xml}->{ProductInfo}->{FormatName} = $format_names->{$format_type};
    $self->{xml}->{ProductInfo}->{FormatType} = $format_type;

    my $pie_count      = 0;
    my $base_image_url = "";
    my $pie_data       = {};
    my @pies           = ();
    my @tables         = ();

    # --------------------------
    # grand total data
    # --------------------------
    my $total_metric = {};
    $total_metric                     = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    # ---------------------------------
    # pie chart - revenue by service
    # ---------------------------------
    my $top_services = $stats_obj->GetTopRanking( category => 'service' );
    my $service_names = Client::Service->GetAllServiceNames();

    foreach my $service_ref (@$top_services) {
        next if ( $service_ref->Revenue <= 0 );

        push @{ $pie_data->{labels} }, $service_names->{ $service_ref->ID };
        push @{ $pie_data->{ids} },    $service_ref->ID;
        push @{ $pie_data->{data} },   $service_ref->Revenue;
    }

    if ( $pie_data && defined $pie_data->{data} ) {
        my $image_link = "view=sf&" . $self->GetPartialQueryString( view => 1 ) . "&service=";
        my $pie_href = GetPieChart(
            labels         => $pie_data->{labels},
            data           => $pie_data->{data},
            image_map_link => $image_link,
            label_ids      => $pie_data->{ids},
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_services";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of the image we created
        # and how many we've created
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    # $top_services is really ALL services at this point so narrow it down to top 5
    splice( @$top_services, 5 );

    # ---------------------------
    # table data - top 10 albums
    # ---------------------------
    $self->_getTopProducts(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        prod_type   => 'A',
        limit       => 10,
        metric_name => 'service',
        metric_list => $top_services,
        metric_hash => $service_names,
    );

    # ---------------------------
    # table data - top 10 tracks
    # ---------------------------
    $self->_getTopProducts(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        prod_type   => 'T',
        limit       => 10,
        metric_name => 'service',
        metric_list => $top_services,
        metric_hash => $service_names,
    );

    # -------------------------
    # table data - top 10 artists
    # -------------------------
    $self->_getTopArtists(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        limit       => 10,
        metric_name => 'service',
        metric_list => $top_services,
        metric_hash => $service_names,
    );

    $self->{xml}->{Pies}->{Pie}     = \@pies;
    $self->{xml}->{Tables}->{Table} = \@tables;
}

#---------------------------------------
# service/format revenue (view=sf)
#---------------------------------------
sub ServiceFormatDetail {
    my $self        = shift;
    my $format_type = $self->GetParam("format") || undef;
    my $service_id  = $self->GetParam("service") || undef;

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        format_type => $format_type,
        service_id  => $service_id,
        country_code => $self->GetParam('country') || undef,
    );
    my $stats_obj = new Stats::Sales(%params);

    my $service_names = Client::Service->GetAllServiceNames();
    $self->{xml}->{ProductInfo}->{ServiceName} = $service_names->{$service_id};
    $self->{xml}->{ProductInfo}->{ServiceID}   = $service_id;

    my $format_names = $stats_obj->FormatMap();
    $self->{xml}->{ProductInfo}->{FormatName} = $format_names->{$format_type};
    $self->{xml}->{ProductInfo}->{FormatType} = $format_type;

    my $data   = {};
    my @tables = ();

    # --------------------------
    # grand total data
    # --------------------------
    my $total_metric = {};
    $total_metric                     = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    # ---------------------------
    # table data - top 10 albums
    # ---------------------------
    $self->_getTopProducts(
        tables    => \@tables,
        stats_obj => $stats_obj,
        prod_type => 'A',
        limit     => 25
    );

    # ---------------------------
    # table data - top 10 tracks
    # ---------------------------
    $self->_getTopProducts(
        tables    => \@tables,
        stats_obj => $stats_obj,
        prod_type => 'T',
        limit     => 25
    );

    # -------------------------
    # table data - top 10 artists
    # -------------------------
    $self->_getTopArtists(
        tables    => \@tables,
        stats_obj => $stats_obj,
        limit     => 25,
    );

    $self->{xml}->{Tables}->{Table} = \@tables;
}

#---------------------------------------
# album summary (view=as)
#---------------------------------------
sub AlbumsSummary {
    my $self = shift;

    my $offset = $self->_getPageOffset();

    my %params = (
        offset      => $offset,
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
        product_type => 'A',
    );
    my $stats_obj = new Stats::Sales(%params);

    my $pie_count      = 0;
    my $base_image_url = "";
    my $data           = {};
    my @pies           = ();
    my @tables         = ();

    # --------------------------
    # pie chart - top services
    # --------------------------
    my $top_services = $stats_obj->GetTopRanking( category => 'service', product_type => 'A' );
    my $service_names = Client::Service->GetAllServiceNames();

    foreach my $service_ref (@$top_services) {
        next if ( $service_ref->Revenue <= 0 );

        push @{ $data->{labels} }, $service_names->{ $service_ref->ID };
        push @{ $data->{ids} },    $service_ref->ID;
        push @{ $data->{data} },   $service_ref->Revenue;
    }

    if ( $data && defined $data->{data} ) {
        my $image_link = "view=s&" . $self->GetPartialQueryString( view => 1 ) . "&service=";
        my $pie_href = GetPieChart(
            labels         => $data->{labels},
            data           => $data->{data},
            image_map_link => $image_link,
            label_ids      => $data->{ids},
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_services";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of the image we created
        # and how many we've created
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    # --------------------------
    # pie chart - top formats
    # --------------------------
    my $top_formats = $stats_obj->GetTopRanking( category => 'format' );
    my $format_names = $stats_obj->FormatMap();
    $data = {};

    foreach my $format_ref (@$top_formats) {
        next if ( $format_ref->Revenue <= 0 );

        push @{ $data->{labels} }, $format_names->{ $format_ref->ID };
        push @{ $data->{ids} },    $format_ref->ID;
        push @{ $data->{data} },   $format_ref->Revenue;
    }

    if ( $data && defined $data->{data} ) {
        my $image_link = "view=f&" . $self->GetPartialQueryString( view => 1 ) . "&format=";
        my $pie_href = GetPieChart(
            labels         => $data->{labels},
            data           => $data->{data},
            image_map_link => $image_link,
            label_ids      => $data->{ids},
            image_src      => $base_image_url,
            chart_num      => $pie_count,
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_formats";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of dynamic images
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    # -------------------------
    # table data - top albums
    # -------------------------

    # $top_services is really ALL services at this point so narrow it down to top 5
    splice( @$top_services, 5 );

    my $top_count = $self->_getTopProducts(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        prod_type   => 'A',
        limit       => RECORDS_PER_PAGE,
        rank_start  => $offset,
        metric_name => 'service',
        metric_list => $top_services,
        metric_hash => $service_names,
    );

    my $page_count = _getPageCount( $top_count, $offset );

    $self->{xml}->{Records}{Limit}      = RECORDS_PER_PAGE;
    $self->{xml}->{Records}{MaxPageNum} = $page_count;
    $self->{xml}->{Pies}->{Pie}         = \@pies;
    $self->{xml}->{Tables}->{Table}     = \@tables;
}

#---------------------------------------
# album specific revenue (view=a)
#---------------------------------------
sub AlbumDetail {
    my $self = shift;

    my $product_id = $self->GetParam("product") || undef;
    my $album_info = new Product::ProductAlbum( product_id => $product_id );
    $self->{xml}->{ProductInfo}->{AlbumName}   = $album_info->AlbumName;
    $self->{xml}->{ProductInfo}->{ArtistName}  = $album_info->ArtistName;
    $self->{xml}->{ProductInfo}->{ProductType} = $album_info->ProductType;
    $self->{xml}->{ProductInfo}->{UPC}         = $album_info->UPC;
    $self->{xml}->{ProductInfo}->{CatalogID}   = $album_info->CatalogID;
    $self->{xml}->{ProductInfo}->{ProductID}   = $product_id;

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
        product_id   => $product_id,
        product_type => 'A',
    );
    my $stats_obj = new Stats::Sales(%params);

    my $total_metric = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    my $albums     = $stats_obj->GetTopRanking( category => 'product', rank_only => 1 );
    my $albumsPrev = $stats_obj->GetTopRanking( category => 'product', prev_rank => 1 );
    $self->{xml}{Totals}{Rank}     = $albums->{$product_id}     || 0;
    $self->{xml}{Totals}{PrevRank} = $albumsPrev->{$product_id} || 0;

    my $pie_count      = 0;
    my $base_image_url = "";
    my $pie_data       = {};
    my @pies           = ();
    my @tables         = ();
    my $table_data     = [];

    # --------------------------
    # pie chart - top services
    # --------------------------
    my $top_services = $stats_obj->GetTopRanking( category => 'service', product_type => 'A' );
    my $service_names = Client::Service->GetAllServiceNames();

    my $service_rank = $stats_obj->GetDetailRanking( category => 'service' );
    my $service_rank_prev = $stats_obj->GetDetailRanking( category => 'service', prev_rank => 1 );

    foreach my $service_ref (@$top_services) {
        next if ( $service_ref->Revenue <= 0 );

        push @{ $pie_data->{labels} }, $service_names->{ $service_ref->ID };
        push @{ $pie_data->{ids} },    $service_ref->ID;
        push @{ $pie_data->{data} },   $service_ref->Revenue;

        my $row_data = {
            Units    => $service_ref->Units,
            Revenue  => $service_ref->Revenue,
            Rank     => $service_rank->{ $service_ref->ID },
            PrevRank => $service_rank_prev->{ $service_ref->ID },
        };

        $row_data->{ProductInfo}->{ServiceName} = $service_names->{ $service_ref->ID };
        $row_data->{ProductInfo}->{ServiceID}   = $service_ref->ID;

        push @$table_data, $row_data;
    }

    if ( $pie_data && defined $pie_data->{data} ) {
        my $image_link = "view=s&" . $self->GetPartialQueryString( view => 1, service => 1 ) . "&service=";
        my $pie_href = GetPieChart(
            labels         => $pie_data->{labels},
            data           => $pie_data->{data},
            image_map_link => $image_link,
            label_ids      => $pie_data->{ids},
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_services";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of the image we created
        # and how many we've created
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    if ( $table_data && ( scalar @$table_data >= 1 ) ) {
        my $table_href = CreateTableXML( data => $table_data, order => [ 'ProductInfo', 'Rank', 'PrevRank', 'Units', 'Revenue' ] );

        if ($table_href) {
            $table_href->{TableName} = "album_revenue_by_service";
            push @tables, $table_href;
        }
    }

    # --------------------------
    # pie chart - top formats
    # --------------------------
    my $top_formats = $stats_obj->GetTopRanking( category => 'format' );
    my $format_names = $stats_obj->FormatMap();

    my $format_rank = $stats_obj->GetDetailRanking( category => 'format' );
    my $format_rank_prev = $stats_obj->GetDetailRanking( category => 'format', prev_rank => 1 );

    $pie_data   = {};
    $table_data = [];

    foreach my $format_ref (@$top_formats) {
        next if ( $format_ref->Revenue <= 0 );

        push @{ $pie_data->{labels} }, $format_names->{ $format_ref->ID };
        push @{ $pie_data->{ids} },    $format_ref->ID;
        push @{ $pie_data->{data} },   $format_ref->Revenue;

        my $row_data = {
            Units    => $format_ref->Units,
            Revenue  => $format_ref->Revenue,
            Rank     => $format_rank->{ $format_ref->ID },
            PrevRank => $format_rank_prev->{ $format_ref->ID },
        };

        $row_data->{ProductInfo}->{FormatName} = $format_names->{ $format_ref->ID };
        $row_data->{ProductInfo}->{FormatType} = $format_ref->ID;

        push @$table_data, $row_data;
    }

    if ( $pie_data && defined $pie_data->{data} ) {
        my $image_link = "view=f&" . $self->GetPartialQueryString( view => 1 ) . "&format=";
        my $pie_href = GetPieChart(
            labels         => $pie_data->{labels},
            data           => $pie_data->{data},
            image_map_link => $image_link,
            label_ids      => $pie_data->{ids},
            image_src      => $base_image_url,
            chart_num      => $pie_count,
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_formats";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of dynamic images
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    if ( $table_data && ( scalar @$table_data >= 1 ) ) {
        my $table_href = CreateTableXML( data => $table_data, order => [ 'ProductInfo', 'Rank', 'PrevRank', 'Units', 'Revenue' ] );

        if ($table_href) {
            $table_href->{TableName} = "album_revenue_by_format";
            push @tables, $table_href;
        }
    }

    $self->{xml}->{Pies}->{Pie}     = \@pies;
    $self->{xml}->{Tables}->{Table} = \@tables;
}

#---------------------------------------
# track summary (view=ks)
#---------------------------------------
sub TracksSummary {
    my $self = shift;

    my $offset = $self->_getPageOffset();

    my %params = (
        offset      => $offset,
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
        product_type => 'T',
    );
    my $stats_obj = new Stats::Sales(%params);

    my $pie_count      = 0;
    my $base_image_url = "";
    my $data           = {};
    my @pies           = ();
    my @tables         = ();

    # --------------------------
    # pie chart - top services
    # --------------------------
    my $top_services = $stats_obj->GetTopRanking( category => 'service' );
    my $service_names = Client::Service->GetAllServiceNames();

    foreach my $service_ref (@$top_services) {
        next if ( $service_ref->Revenue <= 0 );

        push @{ $data->{labels} }, $service_names->{ $service_ref->ID };
        push @{ $data->{ids} },    $service_ref->ID;
        push @{ $data->{data} },   $service_ref->Revenue;
    }

    if ( $data && defined $data->{data} ) {
        my $image_link = "view=s&" . $self->GetPartialQueryString( view => 1 ) . "&service=";
        my $pie_href = GetPieChart(
            labels         => $data->{labels},
            data           => $data->{data},
            image_map_link => $image_link,
            label_ids      => $data->{ids},
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_services";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of the image we created
        # and how many we've created
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    # --------------------------
    # pie chart - top formats
    # --------------------------
    my $top_formats = $stats_obj->GetTopRanking( category => 'format' );
    my $format_names = $stats_obj->FormatMap();
    $data = {};

    foreach my $format_ref (@$top_formats) {
        next if ( $format_ref->Revenue <= 0 );

        push @{ $data->{labels} }, $format_names->{ $format_ref->ID };
        push @{ $data->{ids} },    $format_ref->ID;
        push @{ $data->{data} },   $format_ref->Revenue;
    }

    if ( $data && defined $data->{data} ) {
        my $image_link = "view=f&" . $self->GetPartialQueryString( view => 1 ) . "&format=";
        my $pie_href = GetPieChart(
            labels         => $data->{labels},
            data           => $data->{data},
            image_map_link => $image_link,
            label_ids      => $data->{ids},
            image_src      => $base_image_url,
            chart_num      => $pie_count,
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_formats";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of dynamic images
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    # -------------------------
    # table data - top tracks
    # -------------------------

    # $top_services is really ALL services at this point so narrow it down to top 5
    splice( @$top_services, 5 );

    my $top_count = $self->_getTopProducts(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        prod_type   => 'T',
        limit       => RECORDS_PER_PAGE,
        rank_start  => $offset,
        metric_name => 'service',
        metric_list => $top_services,
        metric_hash => $service_names,
    );

    my $page_count = _getPageCount( $top_count, $offset );

    $self->{xml}->{Records}{Limit}      = RECORDS_PER_PAGE;
    $self->{xml}->{Records}{MaxPageNum} = $page_count;
    $self->{xml}->{Pies}->{Pie}         = \@pies;
    $self->{xml}->{Tables}->{Table}     = \@tables;
}

#---------------------------------------
# track specific revenue (view=k)
#---------------------------------------
sub TrackDetail {
    my $self = shift;

    my $product_id = $self->GetParam("product") || undef;
    my $track_info = new Product::ProductTrack( product_id => $product_id );
    $self->{xml}->{ProductInfo}->{TrackName}   = $track_info->TrackName;
    $self->{xml}->{ProductInfo}->{AlbumName}   = $track_info->AlbumName;
    $self->{xml}->{ProductInfo}->{ArtistName}  = $track_info->ArtistName;
    $self->{xml}->{ProductInfo}->{ProductType} = $track_info->ProductType;
    $self->{xml}->{ProductInfo}->{ISRC}        = $track_info->ISRC;
    $self->{xml}->{ProductInfo}->{UPC}         = $track_info->UPC;

    #$self->{xml}->{ProductInfo}->{CatalogID} = $track_info->CatalogID;
    $self->{xml}->{ProductInfo}->{ProductID} = $product_id;

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
        product_id   => $product_id,
        product_type => 'T',
        format_type  => $self->GetParam('format')  || undef,
    );
    my $stats_obj = new Stats::Sales(%params);

    my $total_metric = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    my $tracks     = $stats_obj->GetTopRanking( category => 'product', rank_only => 1 );
    my $tracksPrev = $stats_obj->GetTopRanking( category => 'product', prev_rank => 1 );
    $self->{xml}{Totals}{Rank}     = $tracks->{$product_id}     || 0;
    $self->{xml}{Totals}{PrevRank} = $tracksPrev->{$product_id} || 0;

    my $pie_count      = 0;
    my $base_image_url = "";
    my $pie_data       = {};
    my @pies           = ();
    my $table_data     = [];
    my @tables         = ();

    # --------------------------
    # top services - build the pie and table data at the same time
    # --------------------------
    my $top_services = $stats_obj->GetTopRanking( category => 'service' );
    my $service_names = Client::Service->GetAllServiceNames();

    my $service_rank = $stats_obj->GetDetailRanking( category => 'service' );
    my $service_rank_prev = $stats_obj->GetDetailRanking( category => 'service', prev_rank => 1 );

    foreach my $service_ref (@$top_services) {
        next if ( $service_ref->Revenue <= 0 );

        push @{ $pie_data->{labels} }, $service_names->{ $service_ref->ID };
        push @{ $pie_data->{ids} },    $service_ref->ID;
        push @{ $pie_data->{data} },   $service_ref->Revenue;

        my $row_data = {
            Units    => $service_ref->Units,
            Revenue  => $service_ref->Revenue,
            Rank     => $service_rank->{ $service_ref->ID },
            PrevRank => $service_rank_prev->{ $service_ref->ID },
        };

        $row_data->{ProductInfo}->{ServiceName} = $service_names->{ $service_ref->ID };
        $row_data->{ProductInfo}->{ServiceID}   = $service_ref->ID;

        push @$table_data, $row_data;
    }

    if ( $pie_data && defined $pie_data->{data} ) {
        my $image_link = "view=s&" . $self->GetPartialQueryString( view => 1 ) . "&service=";
        my $pie_href = GetPieChart(
            labels         => $pie_data->{labels},
            data           => $pie_data->{data},
            image_map_link => $image_link,
            label_ids      => $pie_data->{ids},
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_services";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of the image we created
        # and how many we've created
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    if ( $table_data && ( scalar @$table_data >= 1 ) ) {
        my $table_href = CreateTableXML( data => $table_data, order => [ 'ProductInfo', 'Rank', 'PrevRank', 'Units', 'Revenue' ] );

        if ($table_href) {
            $table_href->{TableName} = "track_revenue_by_service";
            push @tables, $table_href;
        }
    }

    # --------------------------
    # top formats - build the pie and table data at the same time
    # --------------------------
    my $top_formats = $stats_obj->GetTopRanking( category => 'format' );
    my $format_names = $stats_obj->FormatMap();

    my $format_rank = $stats_obj->GetDetailRanking( category => 'format' );
    my $format_rank_prev = $stats_obj->GetDetailRanking( category => 'format', prev_rank => 1 );

    $pie_data   = {};
    $table_data = [];

    foreach my $format_ref (@$top_formats) {
        next if ( $format_ref->Revenue <= 0 );

        push @{ $pie_data->{labels} }, $format_names->{ $format_ref->ID };
        push @{ $pie_data->{ids} },    $format_ref->ID;
        push @{ $pie_data->{data} },   $format_ref->Revenue;

        my $row_data = {
            Revenue  => $format_ref->Revenue,
            Units    => $format_ref->Units,
            Rank     => $format_rank->{ $format_ref->ID },
            PrevRank => $format_rank_prev->{ $format_ref->ID },
        };

        $row_data->{ProductInfo}->{FormatName} = $format_names->{ $format_ref->ID };
        $row_data->{ProductInfo}->{FormatType} = $format_ref->ID;

        push @$table_data, $row_data;
    }

    if ( $pie_data && defined $pie_data->{data} ) {
        my $image_link = "view=f&" . $self->GetPartialQueryString( view => 1 ) . "&format=";
        my $pie_href = GetPieChart(
            labels         => $pie_data->{labels},
            data           => $pie_data->{data},
            image_map_link => $image_link,
            label_ids      => $pie_data->{ids},
            image_src      => $base_image_url,
            chart_num      => $pie_count,
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_formats";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of dynamic images
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    if ( $table_data && ( scalar @$table_data >= 1 ) ) {
        my $table_href = CreateTableXML( data => $table_data, order => [ 'ProductInfo', 'Rank', 'PrevRank', 'Units', 'Revenue' ] );

        if ($table_href) {
            $table_href->{TableName} = "track_revenue_by_format";
            push @tables, $table_href;
        }
    }

    $self->{xml}->{Pies}->{Pie}     = \@pies;
    $self->{xml}->{Tables}->{Table} = \@tables;
}

#---------------------------------------
# artist summary (view=rs)
#---------------------------------------
sub ArtistsSummary {
    my $self = shift;

    my $offset = $self->_getPageOffset();

    my %params = (
        offset      => $offset,
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
    );
    my $stats_obj     = new Stats::Sales(%params);
    my @tables        = ();
    my $top_services  = $stats_obj->GetTopRanking( category => 'service' );
    my $service_names = Client::Service->GetAllServiceNames();

    # -------------------------
    # table data - top artists
    # -------------------------

    # $top_services is really ALL services at this point so narrow it down to top 5
    splice( @$top_services, 5 );

    my $top_count = $self->_getTopArtists(
        tables      => \@tables,
        stats_obj   => $stats_obj,
        limit       => RECORDS_PER_PAGE,
        rank_start  => $offset,
        metric_name => 'service',
        metric_list => $top_services,
        metric_hash => $service_names,
    );

    my $page_count = _getPageCount( $top_count, $offset );

    $self->{xml}->{Records}{Limit}      = RECORDS_PER_PAGE;
    $self->{xml}->{Records}{MaxPageNum} = $page_count;
    $self->{xml}->{Tables}->{Table}     = \@tables;
}

#---------------------------------------
# artist specific revenue (view=r)
#---------------------------------------
sub ArtistDetail {
    my $self = shift;

    my $artist_id = $self->GetParam('artist') || undef;
    my $track_info = new Artist( artist_id => $artist_id );
    $self->{xml}->{ArtistInfo}->{ArtistName} = $track_info->ArtistName;
    $self->{xml}->{ArtistInfo}->{ArtistID}   = $artist_id;

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
        artist_id => $artist_id,
    );
    my $stats_obj = new Stats::Sales(%params);

    my $total_metric = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    my $artists     = $stats_obj->GetTopRanking( category => 'artist', rank_only => 1 );
    my $artistsPrev = $stats_obj->GetTopRanking( category => 'artist', prev_rank => 1 );
    $self->{xml}{Totals}{Rank}     = $artists->{$artist_id}     || 0;
    $self->{xml}{Totals}{PrevRank} = $artistsPrev->{$artist_id} || 0;

    my $pie_count      = 0;
    my $base_image_url = "";
    my $pie_data       = {};
    my @pies           = ();
    my @tables         = ();
    my $table_data     = [];

    # --------------------------
    # top services - build the pie and table data at the same time
    # --------------------------
    my $top_services = $stats_obj->GetTopRanking( category => 'service' );
    my $service_names = Client::Service->GetAllServiceNames();

    my $service_rank = $stats_obj->GetDetailRanking( category => 'service' );
    my $service_rank_prev = $stats_obj->GetDetailRanking( category => 'service', prev_rank => 1 );

    foreach my $service_ref (@$top_services) {
        next if ( $service_ref->Revenue <= 0 );

        push @{ $pie_data->{labels} }, $service_names->{ $service_ref->ID };
        push @{ $pie_data->{ids} },    $service_ref->ID;
        push @{ $pie_data->{data} },   $service_ref->Revenue;

        my $row_data = {
            Revenue  => $service_ref->Revenue,
            Units    => $service_ref->Units,
            Rank     => $service_rank->{ $service_ref->ID },
            PrevRank => $service_rank_prev->{ $service_ref->ID },
        };

        $row_data->{ProductInfo}->{ServiceName} = $service_names->{ $service_ref->ID };
        $row_data->{ProductInfo}->{ServiceID}   = $service_ref->ID;

        push @$table_data, $row_data;
    }

    if ( $pie_data && defined $pie_data->{data} ) {
        my $image_link = "view=s&" . $self->GetPartialQueryString( view => 1 ) . "&service=";
        my $pie_href = GetPieChart(
            labels         => $pie_data->{labels},
            data           => $pie_data->{data},
            image_map_link => $image_link,
            label_ids      => $pie_data->{ids},
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_services";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of the image we created
        # and how many we've created
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    if ( $table_data && ( scalar @$table_data >= 1 ) ) {
        my $table_href = CreateTableXML( data => $table_data, order => [ 'ProductInfo', 'Rank', 'PrevRank', 'Units', 'Revenue' ] );

        if ($table_href) {
            $table_href->{TableName} = 'artist_revenue_by_service';
            push @tables, $table_href;
        }
    }

    # --------------------------
    # top formats - build the pie and table data at the same time
    # --------------------------
    my $top_formats = $stats_obj->GetTopRanking( category => 'format' );
    my $format_names = $stats_obj->FormatMap();

    my $format_rank = $stats_obj->GetDetailRanking( category => 'format' );
    my $format_rank_prev = $stats_obj->GetDetailRanking( category => 'format', prev_rank => 1 );

    $pie_data   = {};
    $table_data = [];

    foreach my $format_ref (@$top_formats) {
        next if ( $format_ref->Revenue <= 0 );

        push @{ $pie_data->{labels} }, $format_names->{ $format_ref->ID };
        push @{ $pie_data->{ids} },    $format_ref->ID;
        push @{ $pie_data->{data} },   $format_ref->Revenue;

        my $row_data = {
            Revenue  => $format_ref->Revenue,
            Units    => $format_ref->Units,
            Rank     => $format_rank->{ $format_ref->ID },
            PrevRank => $format_rank_prev->{ $format_ref->ID },
        };

        $row_data->{ProductInfo}->{FormatName} = $format_names->{ $format_ref->ID };
        $row_data->{ProductInfo}->{FormatType} = $format_ref->ID;

        push @$table_data, $row_data;
    }

    if ( $pie_data && defined $pie_data->{data} ) {
        my $image_link = "view=f&" . $self->GetPartialQueryString( view => 1 ) . "&format=";
        my $pie_href = GetPieChart(
            labels         => $pie_data->{labels},
            data           => $pie_data->{data},
            image_map_link => $image_link,
            label_ids      => $pie_data->{ids},
            image_src      => $base_image_url,
            chart_num      => $pie_count,
        );
        my $xml_href = {};
        $xml_href->{PieName}        = "top_formats";
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};

        push @pies, $xml_href;

        # we have to keep track of dynamic images
        $base_image_url = $pie_href->{image_src};
        $pie_count++;
    }

    if ( $table_data && ( scalar @$table_data >= 1 ) ) {
        my $table_href = CreateTableXML( data => $table_data, order => [ 'ProductInfo', 'Rank', 'PrevRank', 'Units', 'Revenue' ] );

        if ($table_href) {
            $table_href->{TableName} = 'artist_revenue_by_format';
            push @tables, $table_href;
        }
    }

    $self->{xml}->{Pies}->{Pie}     = \@pies;
    $self->{xml}->{Tables}->{Table} = \@tables;
}

#---------------------------------------
# label summary (view=ls)
#---------------------------------------
sub LabelsSummary {
    my $self = shift;

    if ( $CurrentUser->LabelID ) {
        ## label report user isn't supposed to be here
        $self->Redirect("/app/reports");
    }

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
    );

    my $stats_obj = new Stats::Sales(%params);

    # --------------------------
    # grand total data
    # --------------------------
    my $total_metric = {};
    $total_metric                     = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    # --------------------------
    # build the pie and table data at the same time
    # --------------------------
    my $pie_count      = 0;
    my $base_image_url = '';
    my $pie_data       = {};
    my $table_data     = [];
    my $data_labels    = [];

    my $label_info    = Client::Label::GetAllLabels();
    my $labels        = $stats_obj->GetTopRanking( category => 'label' );
    my $labels_prev   = $stats_obj->GetTopRanking( category => 'label', prev_rank => 1 );
    my $top_services  = $stats_obj->GetTopRanking( category => 'service', ignore => 'label', limit => 5 );
    my $service_names = Client::Service->GetAllServiceNames();
    my @metric_list   = map { $_->ID } @$top_services;
    my $total_revenue = $params{label_id} ? _sumRevenue($labels) : $total_metric->Revenue;

    my $c             = 1;
    my $other_revenue = 0;
    my %seen          = ();

    foreach my $label_ref (@$labels) {
        my $label_id = $label_ref->ID;

        if ( $c++ <= 10 and ( $total_revenue and $label_ref->Revenue / $total_revenue ) >= 0.01 ) {
            next if ( $label_ref->Revenue <= 0 );

            push @{ $pie_data->{labels} }, $label_info->{$label_id}{label_name};
            push @{ $pie_data->{ids} },    $label_id;
            push @{ $pie_data->{data} },   $label_ref->Revenue;
        } else {
            $other_revenue += $label_ref->Revenue;
        }

        my $row_data = {
            Rank     => $label_ref->Rank,
            Units    => $label_ref->Units,
            Revenue  => $label_ref->Revenue,
            PrevRank => $labels_prev->{$label_id},
        };

        $row_data->{ProductInfo}->{LabelName} = $label_info->{$label_id}{label_name};
        $row_data->{ProductInfo}->{LabelID}   = $label_id;
        $seen{$label_id}                      = 1;

        my @extra_data     = ();
        my $summary_metric = $stats_obj->GetSummaryMetric(
            category    => 'service',
            metric_list => \@metric_list,
            label_id    => $label_id,
        );

        foreach my $service_ref (@$top_services) {
            push @extra_data, $summary_metric->{ $service_ref->ID } || 0;
            push @$data_labels, $service_names->{ $service_ref->ID };
        }
        $row_data->{Data} = \@extra_data;

        push @$table_data, $row_data;
    }

    # add any labels not yet seen above
    foreach my $label_id ( sort { $label_info->{$a}->{label_name} cmp $label_info->{$b}->{label_name} } keys %$label_info ) {
        next if ( $seen{$label_id} );
        my @place_holders = ();
        map { push @place_holders, 0 } @$top_services;
        push @$table_data,
          {
            Units       => 0,
            Revenue     => 0,
            Rank        => '--',
            PrevRank    => '--',
            ProductInfo => {
                LabelName => $label_info->{$label_id}{label_name},
                LabelID   => $label_id
            },
            Data => \@place_holders,
          };
    }

    my $xml_href = {};

    if ( $pie_data && defined $pie_data->{data} ) {
        if ($other_revenue) {
            push @{ $pie_data->{labels} }, 'Other';
            push @{ $pie_data->{data} },   $other_revenue;
        }

        my $q = $self->GetPartialQueryString( view => 1, label => 1 );
        substr( $q, 0, 0 ) = '&' if $q;
        my $image_link = "view=m$q&label=";
        my $pie_href   = GetPieChart(
            labels         => $pie_data->{labels},
            data           => $pie_data->{data},
            image_map_link => $image_link,
            label_ids      => $pie_data->{ids},
        );
        $xml_href->{PieName}        = 'label_revenue';
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};
    }

    my @tables = ();

    if ( $table_data && ( scalar @$table_data >= 1 ) ) {
        my $table_href = CreateTableXML( data => $table_data, labels => $data_labels );

        if ($table_href) {
            $table_href->{TableName} = 'top_labels';
            push @tables, $table_href;
        }
    }

    $self->{xml}->{Pies}->{Pie} = [$xml_href] if ( keys %$xml_href );
    $self->{xml}->{Tables}->{Table} = \@tables;
}

#---------------------------------------
# geo summary (view=gs)
#---------------------------------------
sub GeoSummary {
    my $self = shift;

    my %params = (
        period_id   => $Period->PeriodID,
        period_type => $Period->PeriodType,
        client_id   => $self->ClientID,
        label_id    => $CurrentUser->LabelID || $self->GetParam("label") || undef,
        country_code => $self->GetParam('country') || undef,
    );

    my $stats_obj = new Stats::Sales(%params);

    # --------------------------
    # grand total data
    # --------------------------
    my $total_metric = {};
    $total_metric                     = $stats_obj->GetTotalMetric(%params);
    $self->{xml}->{Totals}->{Revenue} = moneyize( $total_metric->Revenue );
    $self->{xml}->{Totals}->{Units}   = commify( $total_metric->Units );

    # --------------------------
    # build the pie and table data at the same time
    # --------------------------
    my $pie_count      = 0;
    my $base_image_url = '';
    my $pie_data       = {};
    my $table_data     = [];
    my $data_labels    = [];

    my $geo_map = _mapCountries( $stats_obj->GetCountryList( all => 1 ) );
    my $geo          = $stats_obj->GetTopRanking( category => 'country' );
    my $geo_prev     = $stats_obj->GetTopRanking( category => 'country', prev_rank => 1 );
    my $top_services = $stats_obj->GetTopRanking( category => 'service', ignore => 'country', limit => 5 );
    my $service_names = Client::Service->GetAllServiceNames();
    my @metric_list   = map { $_->ID } @$top_services;
    my $total_revenue = $params{country_code} ? _sumRevenue($geo) : $total_metric->Revenue;

    my $c             = 1;
    my $other_revenue = 0;
    my %seen          = ();

    foreach my $geo_ref (@$geo) {
        my $c_code = $geo_ref->ID;

        if ( $c++ <= 10 and ( $total_revenue > 0 and $geo_ref->Revenue / $total_revenue ) >= 0.01 ) {
            push @{ $pie_data->{labels} }, $geo_map->{$c_code};
            push @{ $pie_data->{ids} },    $c_code;
            push @{ $pie_data->{data} },   $geo_ref->Revenue;
        } else {
            $other_revenue += $geo_ref->Revenue;
        }

        my $row_data = {
            Rank     => $geo_ref->Rank,
            Units    => $geo_ref->Units,
            Revenue  => $geo_ref->Revenue,
            PrevRank => $geo_prev->{$c_code},
        };

        $row_data->{ProductInfo}->{CountryName} = $geo_map->{$c_code};
        $row_data->{ProductInfo}->{CountryID}   = $c_code;
        $seen{$c_code}                          = 1;

        my @extra_data     = ();
        my $summary_metric = $stats_obj->GetSummaryMetric(
            category     => 'service',
            metric_list  => \@metric_list,
            country_code => $c_code,
        );

        foreach my $service_ref (@$top_services) {
            push @extra_data, $summary_metric->{ $service_ref->ID } || 0;
            push @$data_labels, $service_names->{ $service_ref->ID };
        }
        $row_data->{Data} = \@extra_data;

        push @$table_data, $row_data;
    }

    # add any countries not yet seen above
    foreach my $ccode ( sort { $geo_map->{$a} cmp $geo_map->{$b} } keys %$geo_map ) {
        next if ( $seen{$ccode} or $ccode eq '??' );
        my @place_holders = ();
        map { push @place_holders, 0 } @$top_services;
        push @$table_data,
          {
            Units       => 0,
            Revenue     => 0,
            Rank        => '--',
            PrevRank    => '--',
            ProductInfo => {
                CountryName => $geo_map->{$ccode},
                CountryID   => $ccode
            },
            Data => \@place_holders,
          };
    }

    my $xml_href = {};
    if ( $pie_data && defined $pie_data->{data} ) {
        if ($other_revenue) {
            push @{ $pie_data->{labels} }, 'Other';
            push @{ $pie_data->{data} },   $other_revenue;
        }

        my $q = $self->GetPartialQueryString( view => 1, country => 1 );
        substr( $q, 0, 0 ) = '&' if $q;
        my $image_link = "view=m$q&country=";
        my $pie_href   = GetPieChart(
            labels         => $pie_data->{labels},
            data           => $pie_data->{data},
            image_map_link => $image_link,
            label_ids      => $pie_data->{ids},
        );
        $xml_href->{PieName}        = 'geo_revenue';
        $xml_href->{ImageSrc}       = $pie_href->{image_src};
        $xml_href->{ImageMap}       = $pie_href->{image_map};
        $xml_href->{Legend}->{Item} = $pie_href->{legend_xml};
    }

    my @tables = ();

    if ( $table_data && ( scalar @$table_data >= 1 ) ) {
        my $table_href = CreateTableXML( data => $table_data, labels => $data_labels );

        if ($table_href) {
            $table_href->{TableName} = 'top_countries';
            push @tables, $table_href;
        }
    }

    $self->{xml}->{Pies}->{Pie} = [$xml_href] if ( keys %$xml_href );
    $self->{xml}->{Tables}->{Table} = \@tables;
}

#---------------------------------------
# helper functions
#---------------------------------------

sub _getPageOffset {
    my $self = shift;

    my $max_pages = MAX_RECORDS / RECORDS_PER_PAGE;
    my $page_num = $self->GetParam('p') || 1;

    $page_num = 1          if ( $page_num < 1 );
    $page_num = $max_pages if ( $page_num > $max_pages );

    return ( $page_num - 1 ) * RECORDS_PER_PAGE;
}

sub _getPageCount {
    my ( $record_count, $offset ) = @_;
    my $pages = MAX_RECORDS / RECORDS_PER_PAGE;

    if ( $record_count + $offset < MAX_RECORDS ) {
        $pages = int( ( $record_count + $offset ) / RECORDS_PER_PAGE );
        $pages++ if ( ( $record_count + $offset ) % RECORDS_PER_PAGE );
    }

    return $pages;
}

sub _getTopProducts {
    my $self        = shift;
    my %args        = @_;
    my $stats_obj   = $args{stats_obj};
    my $prod_type   = $args{prod_type};
    my @metric_list = map { $_->ID } @{ $args{metric_list} };

    my $table_data = [];
    my ( $products, $count ) = $stats_obj->GetTopRanking( category => 'product', product_type => $prod_type, limit => $args{limit} );
    my $productsPrev = $stats_obj->GetTopRanking( category => 'product', product_type => $prod_type, prev_rank => 1 );

    foreach my $prodRef (@$products) {
        my $prod_id  = $prodRef->ID;
        my $row_data = {};

        $row_data->{Rank}     = $prodRef->Rank;
        $row_data->{Revenue}  = $prodRef->Revenue;
        $row_data->{Units}    = $prodRef->Units;
        $row_data->{PrevRank} = $productsPrev->{$prod_id} || '';

        if ( $prod_type eq 'A' ) {
            my $album_info = new Product::ProductAlbum( product_id => $prod_id );
            $row_data->{ProductInfo}->{AlbumName}   = $album_info->AlbumName;
            $row_data->{ProductInfo}->{AlbumName}   = "(" . $album_info->CatalogID . ")" unless ( $album_info->AlbumName );
            $row_data->{ProductInfo}->{ArtistName}  = $album_info->ArtistName;
            $row_data->{ProductInfo}->{ProductID}   = $album_info->ProductID;
            $row_data->{ProductInfo}->{ProductType} = $album_info->ProductType;
            $row_data->{ProductInfo}->{CatalogID}   = $album_info->CatalogID;
            $row_data->{ProductInfo}->{ArtistID}    = $album_info->ArtistID;
        } elsif ( $prod_type eq 'T' ) {
            my $track_info = new Product::ProductTrack( product_id => $prod_id );
            $row_data->{ProductInfo}->{TrackName}   = $track_info->TrackName;
            $row_data->{ProductInfo}->{TrackName}   = "(Track " . $track_info->TrackNumber . ")" unless ( $track_info->TrackName );
            $row_data->{ProductInfo}->{ArtistName}  = $track_info->ArtistName;
            $row_data->{ProductInfo}->{ProductID}   = $track_info->ProductID;
            $row_data->{ProductInfo}->{ProductType} = $track_info->ProductType;
            $row_data->{ProductInfo}->{CatalogID}   = $track_info->CatalogID;
            $row_data->{ProductInfo}->{ArtistID}    = $track_info->ArtistID;
        }

        if (@metric_list) {
            $row_data->{Data} = [];

            my $summary_metric =
              $stats_obj->GetSummaryMetric( category => $args{metric_name}, metric_list => \@metric_list, product_id => $prod_id );
            foreach my $metric_id (@metric_list) {
                push @{ $row_data->{Data} }, $summary_metric->{$metric_id} || 0;
            }
        }

        push @$table_data, $row_data;
    }

    if ( $table_data && ( scalar @$table_data >= 1 ) ) {
        my @data_labels = @metric_list ? map { $args{metric_hash}->{$_} } @metric_list : undef;
        my $table_href = CreateTableXML( data => $table_data, labels => \@data_labels );

        if ($table_href) {
            if ( $prod_type eq 'A' ) {
                $table_href->{TableName} = 'top_albums';
            } elsif ( $prod_type eq 'T' ) {
                $table_href->{TableName} = 'top_tracks';
            }
            push @{ $args{tables} }, $table_href;
        }
    }

    return $count;
}

sub _getTopArtists {
    my $self        = shift;
    my %args        = @_;
    my $stats_obj   = $args{stats_obj};
    my @metric_list = map { $_->ID } @{ $args{metric_list} };

    my $table_data = [];
    my ( $artists, $count ) = $stats_obj->GetTopRanking( category => 'artist', limit => $args{limit} );
    my $artistsPrev = $stats_obj->GetTopRanking( category => 'artist', prev_rank => 1 );

    foreach my $artistRef (@$artists) {
        my $artist_id = $artistRef->ID;
        my $row_data  = {};

        $row_data->{Rank}     = $artistRef->Rank;
        $row_data->{Revenue}  = $artistRef->Revenue;
        $row_data->{Units}    = $artistRef->Units;
        $row_data->{PrevRank} = $artistsPrev->{$artist_id} || '';

        my $artist_info = new Artist( artist_id => $artist_id );
        $row_data->{ArtistInfo}->{ArtistName} = $artist_info->ArtistName;
        $row_data->{ArtistInfo}->{ArtistID}   = $artist_id;

        if (@metric_list) {
            $row_data->{Data} = [];

            my $summary_metric =
              $stats_obj->GetSummaryMetric( category => $args{metric_name}, metric_list => \@metric_list, artist_id => $artist_id );
            foreach my $metric_id (@metric_list) {
                push @{ $row_data->{Data} }, $summary_metric->{$metric_id} || 0;
            }
        }

        push @$table_data, $row_data;
    }

    if ( $table_data && ( scalar @$table_data >= 1 ) ) {
        my @data_labels = @metric_list ? map { $args{metric_hash}->{$_} } @metric_list : undef;
        my $table_href = CreateTableXML( data => $table_data, labels => \@data_labels );

        if ($table_href) {
            $table_href->{TableName} = 'top_artists';
            push @{ $args{tables} }, $table_href;
        }
    }

    return $count;
}

sub _sumRevenue {
    my $metric = shift;
    my $sum    = 0;
    map { $sum += $_->Revenue } @$metric;

    return $sum;
}

sub _mapCountries {
    my $country_list = shift;
    my %country_map  = ();

    map { $country_map{$_} = $CODE_TO_COUNTRY{$_} || $_; } @$country_list;

    return \%country_map;
}

sub _getMonthMap {
    return {
        1  => 'Jan',
        2  => 'Feb',
        3  => 'Mar',
        4  => 'Apr',
        5  => 'May',
        6  => 'Jun',
        7  => 'Jul',
        8  => 'Aug',
        9  => 'Sep',
        10 => 'Oct',
        11 => 'Nov',
        12 => 'Dec',
    };
}

1;
