#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
# $Id$
#------------------------------------------------------------
package BookPub::Catalog::Command::ShowChart;
use strict;
use warnings;
use Data::Dumper;

use Date::Calc;

use lib '/app/tools/bookpub/lib';
use BookPub::Catalog::Chart::Base;
use BookPub::Catalog::Chart::Price;
use BookPub::Catalog::Chart::BookPrice;
use BookPub::Catalog::Chart::Sales;
use BookPub::Catalog::Chart::Rank;
use BookPub::RDAS::Service;
use BookPub::DB::Item::Service;
use BookPub::DB::Item::BookProduct;
use BookPub::Tracker::Service;
use BookPub::Catalog::Product::Book::WithFormat;
use BookPub::Catalog::BookProductList;
use BookPub::Price::PriceTypeList;

use lib '/app/tools/common/lib';
use RSApache::Response::XSLT;
use RSApache::Response::JSON;
use RSApache::Command::XMLCommand;
use Common::Preference;
use Common::Log;

use base 'RSApache::Command::XMLCommand';

sub cmd  { return 'show_chart'; }
sub area { return 'catalog'; }

use constant kTemplate => "/app/tools/bookpub/templates/catalog/show_chart.xsl";

use constant kDefaultDays      => 30;
use constant kDefaultServiceID => 8;

sub execute {
    my ($self) = @_;

    my $response = $self->SUPER::execute();
    return $response if $response;

    my $productID = $self->getParam("ProductID");
    my $bookID    = $self->getParam("BookID");
    my $serviceID = $self->getParam("ServiceID");
    my $chartType = $self->getParam("ChartType");
    my $days      = $self->getParam("Days");
    my $offset    = $self->getParam("Offset");
    my $dateStart = $self->getParam("DateStart");
    my $dateEnd   = $self->getParam("DateEnd");

    if ( $dateStart && $dateEnd ) {
        my ( $startMonth, $startDay, $startYear ) = split( /\//, $dateStart );
        my ( $endMonth,   $endDay,   $endYear )   = split( /\//, $dateEnd );

        my $delta = Date::Calc::Delta_Days( $startYear, $startMonth, $startDay, $endYear, $endMonth, $endDay );

        if ( $delta > 0 ) {
            $days = $delta;
            $days++;
            $dateStart = $startYear . "-" . $startMonth . "-" . $startDay;
            $dateEnd   = $endYear . "-" . $endMonth . "-" . $endDay;
        } else {

            #Blow up?
        }

    } elsif ( $days && $days eq 'ytd' ) {

        # If we are going to display YTD, we need to translate that into a number of days now.
        # !! Need to do something to the offset, just not sure what yet...
        my ( $y, $m, $d ) = Date::Calc::Today();
        $days = Date::Calc::Delta_Days( $y, 1, 1, $y, $m, $d );
        $days++;
    } elsif ( !$days || $days eq '' ) {

        # If they have a cookie set, we'll use that.
        # Otherwise we'll use a default value.
        #
        Common::Log::Print("Getting the Days param from the cookie");
        $days = Common::Preference::GetValue('BookPubCatalogChartDays');
        Common::Log::Print(" cookie value: $days");
        $days = kDefaultDays unless $days;
        $self->setParam( 'Days', $days );
    }

    # Save the 'Days' parameter as a preference.
    #
    Common::Preference::SetPersistentCookie( 'BookPubCatalogChartDays', $days );

    if ( !$offset ) {
        $offset = 0;
    }

    # We'll need the service list for books and products.
    if ( $bookID || BookPub::DB::Item::BookProduct->IsEBook( productID => $productID ) ) {
        $self->{xml}{ServiceList}{Service} = $self->_getServiceList();
    } else {
        $self->{xml}{ServiceList}{Service} = $self->_getPhysicalServiceList();
    }

    if ($bookID) {

        # Checking to see if the service id has been set.
        if ( !$serviceID ) {

            # If they have a cookie set, we'll use that.
            # Otherwise we'll use a default value.
            #
            Common::Log::Print("Getting the ServiceID param from the cookie");
            $serviceID = Common::Preference::GetValue('BookPubCatalogChartBookService');
            Common::Log::Print(" cookie value: $serviceID");
            $serviceID = kDefaultServiceID unless $serviceID;
        }
        Common::Preference::SetPersistentCookie( 'BookPubCatalogChartBookService', $serviceID );

        my $priceChart = BookPub::Catalog::Chart::BookPrice->new(
            bookID    => $bookID,
            days      => $days,
            offset    => $offset,
            serviceID => $serviceID,
            dateStart => $dateStart,
            dateEnd   => $dateEnd
        );

        $self->{xml}{PriceChart}      = $priceChart;
        $self->{xml}{BookProductList} = BookPub::Catalog::BookProductList->new( bookID => $bookID );
        $self->{xml}{PriceTypes}      = BookPub::Price::PriceTypeList->new();
        $self->{xml}{ServiceID}       = $serviceID;
    } else {

        # Checking to see if the service id has been set.
        if ( !$serviceID ) {

            # If they have a cookie set, we'll use that.
            # Otherwise we'll use a default value.
            #
            Common::Log::Print("Getting the ServiceID param from the cookie");
            $serviceID = Common::Preference::GetValue('BookPubCatalogChartProductService');
            Common::Log::Print(" cookie value: $serviceID");
            $serviceID = kDefaultServiceID unless $serviceID;

            # If we got back a comma separated list, let's turn it into an array ref now to be consistent.
            #
            if ( $serviceID =~ /,/ ) {
                my @serviceArray = split( ',', $serviceID );
                $serviceID = \@serviceArray;
            }
        }

        # Let's turn the array ref into a comma separated list before storing it in the prefs.
        #
        my $serviceIDtoStore = $serviceID;
        if ( 'ARRAY' eq ref($serviceID) ) {
            my @serviceArray = @$serviceID;
            $serviceIDtoStore = join( ',', @serviceArray );
        }

        Common::Preference::SetPersistentCookie( 'BookPubCatalogChartProductService', $serviceIDtoStore );

        my $priceChart = BookPub::Catalog::Chart::Price->new(
            productID => $productID,
            days      => $days,
            offset    => $offset,
            serviceID => $serviceID,
            dateStart => $dateStart,
            dateEnd   => $dateEnd
        );

        $self->{xml}{PriceChart} = $priceChart;

        if ($chartType) {

            # Save the 'ChartType' parameter as a preference.
            # !!! Note that we are only saving this as a pref if the user specifies it.
            Common::Preference::SetPersistentCookie( 'BookPubCatalogChartType', $chartType );
        } else {

            # If they have a cookie set, we'll use that.
            # Otherwise we'll set a default value later.
            #
            Common::Log::Print("Getting the ChartType param from the cookie");
            $chartType = Common::Preference::GetValue('BookPubCatalogChartType');
            Common::Log::Print(" cookie value: $chartType");
        }

        # We need to tell the template which options should be displayed for the bottom chart,
        # based on the services that have been selected.
        # We'll also set the default here.
        # We need to tell the template which options it should display
        #
        my $showRank;
        my $showPOS;

        my @serviceIDArray;
        if ( 'ARRAY' eq ref($serviceID) ) {
            @serviceIDArray = @$serviceID;
        } else {
            push( @serviceIDArray, $serviceID );
        }

        foreach (@serviceIDArray) {
            if ( BookPub::Catalog::Chart::Base->HasRankings($_) ) {
                $showRank = 1;
            }
            if ( BookPub::Catalog::Chart::Base->HasPOS($_) ) {
                $showPOS = 1;
            }
        }

        $self->{xml}{ShowRank} = $showRank;
        $self->{xml}{ShowPOS}  = $showPOS;

        # Setting default chart type to Rank for the view product page.
        #
        if ( !$chartType && $showRank == 1 ) {
            $chartType = 'Rank';
        } elsif ( !$chartType && $showPOS == 1 ) {
            $chartType = 'UnitPOS';
        }

        if ( $chartType && ( $showRank || $showPOS ) ) {
            my $salesChart;

            if ( $chartType eq 'Rank' ) {

                # This is the ranking chart.
                $salesChart = BookPub::Catalog::Chart::Rank->new(
                    productID => $productID,
                    days      => $days,
                    offset    => $offset,
                    serviceID => $serviceID,
                    dateStart => $dateStart,
                    dateEnd   => $dateEnd
                );
            } else {

                # This is used for the rest of the bottom panel charts.
                $salesChart = BookPub::Catalog::Chart::Sales->new(
                    productID => $productID,
                    days      => $days,
                    offset    => $offset,
                    serviceID => $serviceID,
                    dateStart => $dateStart,
                    dateEnd   => $dateEnd,
                    chartType => $chartType
                );
            }

            $self->{xml}{SalesChart} = $salesChart;
        }

        $self->{xml}{Product} = BookPub::Catalog::Product::Book::WithFormat->new( productID => $productID );

        $self->{xml}{SelectedServiceList}{SelectedService} = $self->_makeSelectedServiceList($serviceID);

    }

    # Need to access these in the template.
    $self->{xml}{ChartType} = $chartType;
    $self->{xml}{Days}      = $days;
    $self->{xml}{Offset}    = $offset;

    $response = RSApache::Response::XSLT->new( $self->{xml}, kTemplate );

    # Store the cookies
    Common::Preference::StoreCookies();

    return $response;
}

sub _makeSelectedServiceList {
    my ( $self, $serviceID ) = @_;
    my @result;
    my $item;

    if ( 'ARRAY' eq ref($serviceID) ) {
        my @serviceIDArray = @$serviceID;
        foreach (@serviceIDArray) {
            my $item = {};
            $item->{ServiceID} = $_;
            push( @result, $item );
        }
    } else {
        my $item = {};
        $item->{ServiceID} = $serviceID;
        push( @result, $item );
    }
    return \@result;
}

sub _getServiceList {
    my $self = shift;
    my @result;

    my @serviceIDs = BookPub::RDAS::Service->GetAllServiceIDs();

    foreach my $serviceID (@serviceIDs) {

        if ( $serviceID != 49 ) {
            my $item = {};

            $item->{ServiceName} = $self->_getServiceName($serviceID);
            $item->{ServiceID}   = $serviceID;

            push( @result, $item );
        }
    }

    return \@result;
}

sub _getPhysicalServiceList {
    my $self = shift;
    my @result;

    my @serviceIDs = BookPub::RDAS::Service->GetAllServiceIDs();

    foreach my $serviceID (@serviceIDs) {

        if ( $serviceID != 49 ) {

            if ( $self->_isValidPhysicalServiceID($serviceID) ) {
                my $item = {};

                $item->{ServiceName} = $self->_getServiceName($serviceID);
                $item->{ServiceID}   = $serviceID;

                push( @result, $item );
            }

        }
    }

    return \@result;
}

sub _getServiceName {
    my $self = shift;
    my $serviceID = shift || die;

    my $service = BookPub::DB::Item::Service->Lookup( service_id => $serviceID );

    unless ($service) {
        BookPub::Tracker::Service::AddService( service_id => $serviceID );
        $service = BookPub::DB::Item::Service->Lookup( service_id => $serviceID );
    }

    die "Unknown Service ID: $serviceID" unless ($service);

    return $service->service_name();
}

sub _isValidPhysicalServiceID {
    my $self = shift;
    my $serviceID = shift || return;

    for my $id ( BookPub::RDAS::Service->validPhysicalServices ) {
        return 1 if ( $id == $serviceID );
    }

    return;
}

1;
