package Product::ProductTrack;

use strict;
use warnings;
use Carp;

use lib '/app/tools/sale_import/lib';
use Sale::Match;

use lib '/app/tools/common/lib';
use Common::RSDB;
use Common::Consts;
use Common::Client;
use Common::RSApp;

use constant PRODUCT_TYPE => "T";

# private attributes
my @attributes = qw(product_id
  parent_product_id
  product_title
  track_id
  client_track_id
  client_album_id
  title
  title_clean
  album_title
  release_date
  name
  artist_id
  album_id
  track_order
  isrc
  artist_id
  label_id
  label_name
  catalog_number
  company_id
  vendor_id
  location_id
  duration
  media_type
  album_custom_1
  album_custom_2
  album_custom_3
  custom_1
  custom_2
  custom_3
  upc
  upc_alt
  release_date
);

# what should show up in xml by default
my @xml_attributes = qw(ProductID
  ParentProductID
  ProductType
  ProductTitle
  AlbumID
  ClientAlbumID
  ClientTrackID
  AlbumName
  AlbumNameClean
  ArtistName
  AlbumArtistName
  TrackName
  ISRC
  ArtistID
  LabelID
  LabelName
  TrackNumber
  CatalogID
  AlbumCustom1
  AlbumCustom2
  AlbumCustom3
  TrackCustom1
  TrackCustom2
  TrackCustom3
  MediaType
  UPC
  UPCAlt
  ReleaseDate
  ReleaseDatePretty
);

# album related xml attributes that may get added
my @xml_attributes_prod_track = qw(DiscNumber DiscTrack BonusTrack);

use lib '/app/tools/data_classes/lib';
use Item;
use base 'Item';

# --------------------------------
# Constructor
# --------------------------------
sub new {
    my $class = shift;
    my %args  = @_;

    my $self = $class->SUPER::new(@_);

    $self->_init(%args);

    return $self;
}

sub _init {
    my $self = shift;
    my %args = @_;

    # initialize user properties
    foreach (@attributes) {
        $self->{$_} = undef;
    }

    # are we loading an existing?
    if ( $args{product_id} ) {
        $self->Load( product_id => $args{product_id} );
    }
}

# --------------------------------
# Properties
# --------------------------------

sub ProductID {
    my $self = shift;
    return $self->{product_id};
}

sub ParentProductID {
    my $self = shift;
    return $self->{parent_product_id};
}

sub ProductType {
    return PRODUCT_TYPE();
}

sub ProductTitle {
    my $self = shift;
    return $self->{product_title};
}

sub AlbumID {
    my $self = shift;
    return $self->{album_id};
}

sub ClientTrackID {
    my $self = shift;
    return $self->{client_track_id};
}

sub ClientAlbumID {
    my $self = shift;
    return $self->{client_album_id};
}

sub TrackName {
    my $self = shift;
    return $self->{title};
}

sub ArtistName {
    my $self = shift;
    return $self->{name};
}

sub AlbumName {
    my $self = shift;
    return $self->{album_title};
}

sub AlbumNameClean {
    my $self = shift;
    return $self->{album_name_clean};
}

sub AlbumArtistName {
    my $self = shift;

    if ( !defined $self->{album_artist_name} && $self->AlbumID ) {
        my $sql  = "SELECT name FROM artist art JOIN album alb ON art.artist_id=alb.artist_id WHERE alb.album_id=" . $self->AlbumID;
        my $sth  = $self->{dbo}->DoCmd($sql);
        my $href = $sth->fetchrow_hashref() if ($sth);
        if ($href) {
            $self->{album_artist_name} = $href->{name};
        }
    }

    return $self->{album_artist_name};
}

sub ISRC {
    my $self = shift;
    return $self->{isrc};
}

sub ArtistID {
    my $self = shift;
    return $self->{artist_id};
}

sub LabelID {
    my $self = shift;
    return $self->{label_id};
}

sub LabelName {
    my $self = shift;
    return $self->{label_name};
}

sub TrackNumber {
    my $self = shift;
    return $self->{track_order};
}

sub CatalogID {
    my $self = shift;
    return $self->{catalog_number};
}

sub AlbumCustom1 {
    my $self = shift;
    return $self->{album_custom_1};
}

sub AlbumCustom2 {
    my $self = shift;
    return $self->{album_custom_2};
}

sub AlbumCustom3 {
    my $self = shift;
    return $self->{album_custom_3};
}

sub NumberOfDiscs {
    my $self = shift;
    Carp::cluck('"ProductTrack->NumberOfDiscs" no longer supported');
    return undef;
}

sub Duration {
    my $self = shift;
    return $self->{duration};
}

sub TrackCustom1 {
    my $self = shift;
    return $self->{custom_1};
}

sub TrackCustom2 {
    my $self = shift;
    return $self->{custom_2};
}

sub TrackCustom3 {
    my $self = shift;
    return $self->{custom_3};
}

sub MediaType {
    my $self = shift;
    return $self->{media_type};
}

# the following 3 album fields need to come from the (parent) album product's record

sub DiscNumber {
    my $self = shift;

    $self->_load_product_track_info() if ( !defined $self->{disc_number} && $self->AlbumID );

    return $self->{disc_number};
}

sub DiscTrack {
    my $self = shift;

    $self->_load_product_track_info() if ( !defined $self->{disc_track} && $self->AlbumID );

    return $self->{disc_track};
}

sub BonusTrack {
    my $self = shift;

    $self->_load_product_track_info() if ( !defined $self->{is_bonus_track} && $self->AlbumID );

    return $self->{is_bonus_track};
}

sub Error {
    my $self = shift;
    $self->{errstr};
}

sub GetObjectXML {
    my $self = shift;

    my @object_attributes = @xml_attributes;
    push( @object_attributes, @xml_attributes_prod_track ) if ( $self->{_prod_track_looked_up} );

    my $xml = $self->SUPER::GetObjectXML(@object_attributes);

    return $xml;
}

# album info accessors
sub UPC {
    my $self = shift;
    return $self->{upc};
}

sub UPCAlt {
    my $self = shift;
    return $self->{upc_alt};
}

sub ReleaseDate {
    my $self = shift;
    return $self->{release_date};
}

sub ReleaseDatePretty {
    my $self = shift;
    return '' unless $self->{release_date};
    return Common::Client::Current()->Locale()->formatDate( $self->{release_date} );
}

# -------------------------------
# Public Methods
# -------------------------------
sub Load {
    my $self = shift;
    my %args = @_;

    # !!! Problem - we have some ambiguities.  both album and track use 'title' in the rps schema.
    my $sql;
    if ( defined $args{product_id} && $args{product_id} =~ /^\d+$/ ) {
        $sql =
            "SELECT"
          . " p.product_id,"
          . " p.parent_product_id,"
          . " trk.*,"
          . " art.name,"
          . " alb.title as album_title,"
          . " alb.album_id,"
          . " alb.catalog_number,"
          . " alb.client_album_id,"
          . " p.release_date,"
          . " alb.custom_1 as album_custom_1,"
          . " alb.custom_2 as album_custom_2,"
          . " alb.custom_3 as album_custom_3,"
          . " l.label_name,"
          . " m.isrc"

          . " FROM" . " product p," . " track trk," . " album alb," . " artist art," . " master m," . " label l"

          . " WHERE"
          . " p.product_id="
          . $self->{dbo}->DBQuote( $args{product_id} )
          . " AND p.asset_id = trk.track_id"
          . " AND trk.artist_id = art.artist_id"
          . " AND alb.label_id = l.label_id "
          . " AND alb.album_id = trk.album_id "
          . " AND trk.master_id = m.master_id ";
    } else {
        $self->{errstr} = "product_id ($args{product_id}) not specified or not valid";
        print STDERR $self->{errstr} . "\n";
        return undef;
    }

    my $sth = $self->{dbo}->DoCmd($sql);
    unless ( defined $sth ) {
        $self->{errstr} = "database error: " . $DBI::errstr;
        print STDERR $self->{errstr} . "\n";
        return undef;
    }

    my $href = $sth->fetchrow_hashref();
    if ( !defined $href || $sth->rows == 0 ) {
        $self->{errstr} = "no product track record for product_id=$args{product_id}";
        return undef;
    }

    # try to load album info, non-fatal if missing
    if ( $href->{'album_id'} && $href->{'parent_product_id'} ) {
        my $sql2 =
            "SELECT upc_ean as upc, upc_alt, release_date"
          . " FROM album JOIN product ON album.album_id=product.asset_id"
          . " WHERE product.product_type_id=3 AND album.album_id="
          . $href->{'album_id'}
          . " AND product.product_id="
          . $href->{'parent_product_id'};

        my $sth2 = $self->{dbo}->DoCmd($sql2);
        if ( $sth2->rows() ) {
            %$href = ( %$href, %{ $sth2->fetchrow_hashref } );
        }

    }

    # grab the product title from the parent product
    if ( $href->{'parent_product_id'} ) {
        my $sql3 = "SELECT product.title as product_title" . " FROM product" . " WHERE product.product_id=" . $href->{'parent_product_id'};

        my $sth3 = $self->{dbo}->DoCmd($sql3);
        if ( $sth3->rows() ) {
            %$href = ( %$href, %{ $sth3->fetchrow_hashref } );
        }

    }

    $self->_load($href);

    return 1;

}

# -------------------------------
# Private Methods
# -------------------------------
sub _load {
    my $self = shift;
    my $href = shift;

    map { $self->{$_} = $href->{$_} } @attributes;
}

sub _load_product_track_info {
    my $self = shift;
    return if $self->{_prod_track_looked_up};

    $self->{_prod_track_looked_up} = 1;    # prevent multiple fetches if 1 of the values is null
                                           # and do it now, so we don't keep doing it again, lookup notwithstanding

    my $sql =
        "SELECT disc_number, disc_track, is_bonus_track"
      . " FROM product_track JOIN product USING(product_id)"
      . " WHERE product_type_id=3 AND track_id=$self->{track_id} AND asset_id="
      . $self->AlbumID;

    my $sth = $self->{dbo}->DoCmd($sql);
    return unless ( $sth and $sth->rows );

    my $href = $sth->fetchrow_hashref();

    $self->{disc_number}    = $href->{disc_number};
    $self->{disc_track}     = $href->{disc_track};
    $self->{is_bonus_track} = $href->{is_bonus_track};
}
###
1;    # Play nicely.
###
