#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# Copyright (C) 2009 RoyaltyShare, Inc.   All Rights Reserved
# $Id$
#---------------------------------------------------------------
package BookPub::DB::Item::BookFormat;

use strict;
use warnings;
use Data::Dumper;

use lib '/app/tools/common/lib';
use lib '/app/tools/bookpub/lib';
use base 'Common::DB::Item';
use BookPub::DB::Item::OnixCode;
use BookPub::DB::Item::BookFormatType;
use BookPub::DB::Item::BookFormatSubtype;

use Common::Assert;

use constant kTable => 'book_format';
use constant kDB    => Common::DB::Item::kClientDB;

# Define some of the commonly used types here.
#
use constant kHardback  => 15;
use constant kPaperback => 16;
use constant kEBook     => 42;

sub FindByOnixCodeID {
    my ( $class, %args ) = @_;

    assert( $args{type_onix_code_id} );

    return $class->FindByOnixCode(%args);
}

sub FindByOnixCode {
    my ( $class, %args ) = @_;
    my @where;
    my @select;

    # !!! These need to be onix_code_ids...
    #
    my $formatTypeOnixCodeID    = $args{type_onix_code_id};
    my $formatSubtypeOnixCodeID = $args{subtype_onix_code_id};

    my $formatTypeOnixCode        = $args{type_onix_code};
    my $formatSubtypeOnixCode     = $args{subtype_onix_code};
    my $formatTypeOnixCodeList    = $args{type_onix_code_list};
    my $formatSubtypeOnixCodeList = $args{subtype_onix_code_list};

    if ($formatTypeOnixCodeID) {
        push( @where, "book_format_type.onix_code_id = " . $class->quote($formatTypeOnixCodeID) );
        if ($formatSubtypeOnixCodeID) {
            push( @where, "book_format_subtype.onix_code_id = " . $class->quote($formatSubtypeOnixCodeID) );
        } else {
            push( @where, "book_format_subtype.onix_code_id IS NULL" );
        }
    }

    elsif ($formatTypeOnixCode) {
        assert( $formatTypeOnixCodeList, "Code list required" );
        assert( $formatSubtypeOnixCodeList, "Code list required" ) if ($formatSubtypeOnixCodeList);

        push( @where, "type_onix_code.code_value = " . $class->quote($formatTypeOnixCode) );
        push( @where, "type_onix_code.code_list  = " . $class->quote($formatTypeOnixCodeList) );
        if ($formatSubtypeOnixCode) {
            push( @where, "subtype_onix_code.code_value = " . $class->quote($formatSubtypeOnixCode) );
            push( @where, "subtype_onix_code.code_list  = " . $class->quote($formatSubtypeOnixCodeList) );
        } else {
            push( @where, "book_format_subtype.onix_code_id IS NULL" );
        }

    }

    else {
        assert( 0, "Onix Code and list or Onix Code ID required" );
    }

    push( @select, kTable . ".*" );
    push( @select, "book_format_type.onix_code_id AS book_format_type_onix_code_id" );
    push( @select, "book_format_subtype.onix_code_id AS book_format_subtype_onix_code_id" );

    # Some known things:   product_form uses onix code list 7.
    # If product_form_detail is specified, that's code list 78.
    # If epubType is specified, AND product_form = 'DG', that's code list 10.
    #
    my $sql =
        "SELECT "
      . join( ',', @select )
      . " FROM book_format"
      . " INNER JOIN book_format_type ON book_format_type.book_format_type_id=book_format.book_format_type_id"
      . " INNER JOIN onix_code as type_onix_code ON book_format_type.onix_code_id = type_onix_code.onix_code_id"
      . " LEFT  JOIN book_format_subtype ON book_format_subtype.book_format_subtype_id=book_format.book_format_subtype_id"
      . " LEFT  JOIN onix_code as subtype_onix_code ON book_format_subtype.onix_code_id = subtype_onix_code.onix_code_id"
      . " WHERE "
      . join( ' AND ', @where );

    my $collection = $class->GetAll($sql);
    return undef unless ( $collection && $collection->size() > 0 );
    return $collection->next();
}

sub CreateByOnixCodeID {
    my ( $class, %args ) = @_;

    assert( $args{type_onix_code_id} );

    return $class->FindByOnixCode(%args);
}

sub CreateByOnixCode {
    my ( $class, %args ) = @_;

    # !!! These need to be onix_code_ids...
    #
    my $formatTypeOnixCodeID    = $args{type_onix_code_id};
    my $formatSubtypeOnixCodeID = $args{subtype_onix_code_id};

    my $formatTypeOnixCode        = $args{type_onix_code};
    my $formatSubtypeOnixCode     = $args{subtype_onix_code};
    my $formatTypeOnixCodeList    = $args{type_onix_code_list};
    my $formatSubtypeOnixCodeList = $args{subtype_onix_code_list};

    unless ($formatTypeOnixCodeID) {
        assert($formatTypeOnixCode);
        assert($formatTypeOnixCodeList);
        assert($formatSubtypeOnixCodeList) if ($formatSubtypeOnixCodeList);

        my $type = BookPub::DB::Item::OnixCode->Lookup(
            code_value => $formatTypeOnixCode,
            code_list  => $formatTypeOnixCodeList
        );

        my $subtype = BookPub::DB::Item::OnixCode->Lookup(
            code_value => $formatSubtypeOnixCode,
            code_list  => $formatSubtypeOnixCodeList
        ) if ($formatSubtypeOnixCode);

        assert($type);
        assert($subtype) if ($formatSubtypeOnixCode);

        $formatTypeOnixCodeID = $type->onix_code_id;
        $formatSubtypeOnixCodeID = $subtype->onix_code_id if ($subtype);
    }

    my $formatTypeID;
    my $formatSubtypeID;
    my $formatType = BookPub::DB::Item::BookFormatType->Lookup( onix_code_id => $formatTypeOnixCodeID );
    if ( !$formatType ) {
        $formatType = BookPub::DB::Item::BookFormatType->Create( onix_code_id => $formatTypeOnixCodeID );
        $formatType->save();
    }
    $formatTypeID = $formatType->book_format_type_id();

    if ($formatSubtypeOnixCodeID) {
        my $subtype = BookPub::DB::Item::BookFormatSubtype->Lookup( onix_code_id => $formatSubtypeOnixCodeID );
        if ( !$subtype ) {
            $subtype = BookPub::DB::Item::BookFormatSubtype->Create( onix_code_id => $formatSubtypeOnixCodeID );
            $subtype->save();
        }
        $formatSubtypeID = $subtype->book_format_subtype_id();
    }

    my $format = BookPub::DB::Item::BookFormat->FindByOnixCodeID(
        type_onix_code_id    => $formatTypeOnixCodeID,
        subtype_onix_code_id => $formatSubtypeOnixCodeID
    );

    unless ($format) {
        $format = $class->Create();
        $format->book_format_type_id($formatTypeID);
        $format->book_format_subtype_id($formatSubtypeID);
        $format->save();
    }

    return $format;
}

sub LookupOrCreate {
    my ( $class, %args ) = @_;

    my $code = $class->FindByOnixCode(%args);

    return $code ? $code : $class->CreateByOnixCode(%args);
}

1;
