#!/usr/bin/perl

=pod

=head1 NAME

test_cgi.pl

=head1 DESCRIPTION

This is an incredibly simple (and awful) script to show new programmers
the OAuth steps required to connect to LOVEFiLM. Please use it as a guide
only as programming style has moved on since the 90's, however it does keep
the dependancies down.

Also, it will only work for one user.

=head1 RUNNING

Having a checkout/download version of the code, I setup apache to have a
virtual server with its cgi-bin set like this

    ScriptAlias /cgi-bin/ /the/full/path/WWW-Lovefilm-API/examples

The lib dir is at /the/full/path/WWW-Lovefilm-API/lib, and the required
package WWW::Lovefilm::API can be found in there. Hence you don't have
to install the package to run it since it is relative and it will be found.

Make sure "vars_tokenless.inc" in the examples directory has your consumer_key
and consumer_secret set for your app.

=head1 INTERNAL FUNCTIONS

=cut


use strict;
use warnings;
use CGI;
use Data::Dumper;
use Storable qw( freeze thaw );
use URI::Escape;
use XML::Simple;
use FindBin;
use lib "$FindBin::Bin/../lib";
use WWW::Lovefilm::API;

my $q = CGI->new;


# Prepare various HTTP responses
print
    $q->header() .
    $q->start_html('My LOVEFiLM App Demo');

my %auth = (
    do('vars_tokenless.inc'),
);

my %store = _read();

my $lovefilm = WWW::Lovefilm::API->new({
    %auth,
    %store,
    content_filter => sub { XMLin(@_) },
});


if ( defined($store{access_token}) ) {
    _welcome();
}
# Been redirect back to this script by LOVEFiLM?
#
elsif ( $q->param('myuser') ) {
    print
        $q->p("You must have been redirected back from LOVEFiLM after authorising this app for your account ".
              "as I picked up my parameter I set.");

    my %data = $lovefilm->RequestAccessToken(
        oauth_token  => $store{token},
        token_secret => $store{token_secret},
    );

    unless (defined($data{access_token}) && $data{access_token} ) {
        print $q->p("Error: Please look at the error.log file to see what went wrong");
    }
    else {
        _store( %store, %data );

        %store = _read();

        print $q->p("The details we have are: " . $q->pre(Dumper(\%store)));
        _welcome();
    }
}
# Fresh request to talk to LOVEFiLM, get a token
#
else {
    my %data = $lovefilm->RequestToken(  );

    if ($data{token} && $data{login_url}) {
        _store( %data );
    
        my $encoded  = uri_escape('?myuser=123'); # params will be sent back to us
        my $this_url = $q->url();
        my $url      = $data{login_url} . '?oauth_token=' . $data{token}. ";oauth_callback=$this_url" . $encoded;

        print 
            $q->h1('Ask LOVEFiLM for permission...');

        print $q->p("You need to click this link and tell LOVEFiLM to give access to MyAppName : " .
                    $q->a({-href => $url}, "GOTO LOVEFiLM")
                    );
    }
    else {
        print 
            $q->h1('Error') .
            $q->p("Could not access LOVEFiLM !!!");
    }
}

print $q->end_html;


=head2 _store

This is a cheap way of storing state when the user gets redirected.

=cut

sub _store {
    my %data = @_;
    my $filename = '/tmp/store';

    my $dd = Data::Dumper->new([\%data], [ qw(data) ]);

    open my $handle, ">$filename" or die "ERROR: could not write to file $filename: $!";
    print $handle $dd->Dump();
    close $handle;
}

=head2 _append

This appends any new key values onto the existing state.

=cut


sub _append {
    my %append   = @_;
    my $filename = '/tmp/store';

    my %data = (_read(), %append);
    my $dd   = Data::Dumper->new([\%data], [ qw(data) ]);

    open my $handle, ">$filename" or die "ERROR: could not write to file $filename: $!";
    print $handle $dd->Dump();
    close $handle;
}

=head2 _read

return a hash of representing the stored state

=cut

sub _read {
    unless (-f '/tmp/store') {
        return;
    }

    my $data = do {
        if( open my $fh, '<', '/tmp/store' ) { local $/; <$fh> }
        else { undef }
    };

    my $isbn;

    eval $data;

    return %{$data};
}

=head2 _welcome

This function will only work if the user has given permission to your
app to access your account at LOVEFiLM.

=cut

sub _welcome {
    # Who has authorised this app?
    #
    $lovefilm->REST->Users(); # user_id automatically added in i.e. /users/1234567
    $lovefilm->Get();

    my $content = $lovefilm->content;

    my $first_name = $content->{first_name};
    my $last_name  = $content->{last_name};

    print $q->p("Welcome $first_name $last_name, at_home you have:");

    # What discs do they have at home?
    #
    $lovefilm->REST->Users->at_home();
    $lovefilm->Get();
    $content = $lovefilm->content;

    print
        $q->start_table() .
        $q->Tr($q->th(), $q->th("Name"), $q->th("Rating"));

    foreach my $item (@{$content->{'at_home_item'}}) {
        my $catalog_title   = $item->{catalog_title};
        my $art_href =_get_artwork_href($catalog_title);
        print
            $q->Tr(
                $q->td($q->img({src => $art_href, alt => $catalog_title->{title}->{clean}, rowspan => 2})),
                $q->td($catalog_title->{title}->{clean}).
                $q->td($catalog_title->{rating} . "/5")
            );
    }

    print $q->end_table;;
}

=head2 _get_artwork_href

The images for a given film (title) are split into different directories so we can't construct
a URL by just knowing the ID of the title.

This function performs an API call to get the href of the correct image size.

=cut

sub _get_artwork_href {
    my $catalog_title = shift;
    my $size          = shift || 'small';
    my $type          = shift || 'title';
    my $href_id       = $catalog_title->{id};
    my ($id)          = ($href_id =~ /(\d+)$/ );

    $lovefilm->REST->catalog->title($id)->artworks; # user_id automatically added in i.e. /users/1234567
    $lovefilm->Get();
    my $content = $lovefilm->content;

    foreach my $arttype ( @{$content->{artwork}} ) {
        if ($arttype->{type} eq $type) { # title or hero

            foreach my $image_data ( @{$arttype->{image}} ) {

                if ($image_data->{size} eq $size) {
                    return $image_data->{href};
                }
            }
        }
    }

    return "";
}
