#!perl -T

=head2 USAGE

To run manually in the local directory assuming gapi.json present in source root and in xt/author/calendar directory
  C<prove -I../lib 01-client-discovery.t -w -o -v>

NB: is also run as part of dzil test

=cut

use 5.006;
use strict;
use warnings;
use Test::More;
use Data::Dumper;    ## remove this when finish tweaking
use Cwd;
my $dir   = getcwd;
my $DEBUG = 0;        ## to see noise of class debugging


use_ok( 'WebService::Google::Client' );    #  || print "Bail out!\n";
use_ok( 'WebService::Google::Client::Discovery' );


my $default_file = $ENV{ 'GOOGLE_TOKENSFILE' } || "$dir/../../gapi.json";    ## assumes running in a sub of the build dir by dzil
$default_file = "$dir/../gapi.json" unless -e $default_file;                 ## if file doesn't exist try one level up ( allows to run directly from t/ if gapi.json in parent dir )
my $user = $ENV{ 'GMAIL_FOR_TESTING' } || '';                                ## will be populated by first available if set to '' and default_file exists


subtest 'WebService::Google::Client::Discovery class properties' => sub {
  ok(
    ref WebService::Google::Client::Discovery->new->ua eq 'WebService::Google::Client::UserAgent',
    'ua property (WebService::Google::Client::Discovery->new->ua) is of type WebService::Google::Client::UserAgent'
  );
  ok( ref( WebService::Google::Client::Discovery->new->chi ) =~ /^CHI::Driver/xm, 'chi property (WebService::Google::Client::Discovery->new->chi) is of sub-type CHI::Driver::' );
  note( "CHI Root Directory = " . WebService::Google::Client::Discovery->new->chi->root_dir );
  ok( WebService::Google::Client::Discovery->new->debug eq '0', 'debug property defaults to 0' );
  ok( WebService::Google::Client::Discovery->new( debug => 1 )->debug eq '1', 'debug property when set to 1 on new returns 1' );
};


## NB - should probably skip tests that will fail when a dependent test fails
subtest 'Naked instance method tests (without Client parent container)' => sub {

=pod
## not currently caching when running a sudo test so removing - restore for production



  ok( ref  WebService::Google::Client->new( debug => $DEBUG ) eq 'WebService::Google::Client' , 'WebService::Google::Client new is correct type');
  ok( my $ret = WebService::Google::Client::Discovery->new->discover_all, 'WebService::Google::Client::Discovery->new->discover_all returns something');
  ## TODO - WebService::Google::Client::Discovery->new->discover_all structure as expected
  ## TODO - do some more testing of discovery_all as is foundation for much of the workings
  ok( ref WebService::Google::Client::Discovery->new->available_APIs eq 'ARRAY', "WebService::Google::Client::Discovery->new->available_APIs returns array ref");
  ok( scalar WebService::Google::Client::Discovery->new->available_APIs > 50 , "available_APIs() returns more than 50 elements in arra ref");
  ok ( WebService::Google::Client::Discovery->new->service_exists() == 0, 'WebService::Google::Client::Discovery->new->service_exists() == 0');
  ok ( WebService::Google::Client::Discovery->new->service_exists('gmail') == 1, 'WebService::Google::Client::Discovery->new->service_exists("gmail") == 1');
  ok ( WebService::Google::Client::Discovery->new->service_exists('calendar') == 1, 'WebService::Google::Client::Discovery->new->service_exists("calendar") == 1');
  ## TODO: refactor case of service handling across all code to make consistent - smells bad at the moment
  ok ( WebService::Google::Client::Discovery->new->service_exists('Gmail') == 0, 'test case-insensitive failure service_exists("Gmail") == 0');

  ok ( length(WebService::Google::Client::Discovery->new->supported_as_text()) > 100 , 'print_supported() returns string longer than 100 characters');
  ok ( ref( WebService::Google::Client::Discovery->new->available_versions() ) eq 'ARRAY' && 
       scalar( @{ WebService::Google::Client::Discovery->new->available_versions() } ) == 0
       ,'available_versions() no params returns empty array ref');
  ok ( ref( WebService::Google::Client::Discovery->new->available_versions('calendar') ) eq 'ARRAY' && 
       scalar( @{ WebService::Google::Client::Discovery->new->available_versions('calendar') } ) > 0
       ,'available_versions("calendar") returns at least 1 version');

  ok ( ref( WebService::Google::Client::Discovery->new->available_versions('sdfds') ) eq 'ARRAY' && 
       scalar( @{ WebService::Google::Client::Discovery->new->available_versions('sdfds') } ) == 0
       ,'available_versions("sdfds") returns empty array ref');

  ok ( ref( WebService::Google::Client::Discovery->new->latest_stable_version() ) eq '' && 
        WebService::Google::Client::Discovery->new->latest_stable_version() eq ''
       ,'latest_stable_version() no params returns empty string');
  ok ( WebService::Google::Client::Discovery->new->latest_stable_version('calendar')  && 
       WebService::Google::Client::Discovery->new->latest_stable_version('calendar') =~ /^v\d+/xm 
       ,'latest_stable_version("calendar") returns a string in v\d format');
  ok ( ref( WebService::Google::Client::Discovery->new->latest_stable_version('dsfjh') ) eq '' && 
        WebService::Google::Client::Discovery->new->latest_stable_version('dsfjh') eq ''
       ,'latest_stable_version("dsfjh")  returns empty string');

  ok ( ref(WebService::Google::Client::Discovery->new( debug => 1 )->get_resource_meta('WebService::Google::Client::Calendar::Events')) 
       eq 'HASH', 'get_resource_meta(\'WebService::Google::Client::Calendar::Events\') returns hashref' );

  ## this is getting pretty ugly - need to parse around abstract class name strings etc .. and that's with simple Calendar Structure
  ok ( ref(WebService::Google::Client::Discovery->new( debug => 0 )->get_resource_meta('WebService::Google::Client::Calendar::Events')) eq 'HASH' 
        && 
        (keys %{WebService::Google::Client::Discovery->new( debug => 0 )->get_resource_meta('WebService::Google::Client::Calendar::Events')} == 1
        && 
        defined WebService::Google::Client::Discovery->new( debug => 0 )->get_resource_meta('WebService::Google::Client::Calendar::Events')->{methods}
        )
       , 'get_resource_meta(\'WebService::Google::Client::Calendar::Events\') returns hashref with single key defined - methods' );


  ok ( ref(WebService::Google::Client::Discovery->new( debug => 0 )->get_resource_meta('WebService::Google::Client::Gmail::Users')) eq 'HASH' 
        && 
        (keys %{WebService::Google::Client::Discovery->new( debug => 1 )->get_resource_meta('WebService::Google::Client::Gmail::Users')} == 1
        && 
        defined WebService::Google::Client::Discovery->new( debug => 0 )->get_resource_meta('WebService::Google::Client::Gmail::Users')->{methods}
        )
       , 'get_resource_meta(\'WebService::Google::Client::Gmail::Users\') returns hashref with single key defined - methods with keys getProfile,stop,watch' );
=cut


#exit;
#my $ret = WebService::Google::Client::Discovery->new( debug => 1 )->get_resource_meta('WebService::Google::Client::Calendar::Events'); ## ::CalendarList::delete
## keys $ret->{methods} = update,quickAdd,insert,move,instances,watch,patch,delete,list,import,get

=pod
my $ret = WebService::Google::Client::Discovery->new( debug => 1 )->get_resource_meta('WebService::Google::Client::Gmail::User'); ## ::CalendarList::delete
print "ret = " . $ret ."\n";
print "ref = " . ref( $ret ) . "\n";

print Dumper $ret;

print join(',',  keys %{$ret->{methods}} ) . "\n";
exit;
=cut

#  my $ret = WebService::Google::Client::Discovery->new->available_versions('calendar');

#   my $ret = WebService::Google::Client::Discovery->new->available_versions();

  #print ref $ret;
  # my $ret = WebService::Google::Client::Discovery->new->
  #print ref $ret;
#   print Dumper $ret; exit;

TODO:
  {
    local $TODO = "tests for each WebService::Google::Client::Discovery method";
    ok( undef, 'get_rest' );

    # ok(undef,'discover_all');
    #ok(undef,'available_APIs');
    #ok(undef,'service_exists');
    #ok(undef,'print_supported');
    #ok(undef,'available_versions');
    #ok(undef,'latest_stable_version');
    ok( undef, 'find_APIs_with_diff_vers' );
    ok( undef, 'search_in_services' );
    ok( undef, 'get_method_meta' );
    ok( undef, 'get_resource_meta' );
    ok( undef, 'list_of_methods' );
    ok( undef, 'meta_for_API' );
  }

  #todo('get_rest');
};

subtest 'Discovery methods with User Configuration' => sub {
  plan( skip_all => 'No service configuration - set $ENV{GOOGLE_TOKENSFILE} or create gapi.json in dzil source root directory' ) unless -e $default_file;


  ## Create a local instance to extract default user
  ok( my $gapi = WebService::Google::Client->new( debug => $DEBUG ), 'Creating test session instance of WebService::Google::Client' );

  #ok( $gapi->auth_storage->setup( { type => 'jsonfile', path => $default_file } ) || croak( $! ), "Load '$default_file'");
  ok( ref $gapi->auth_storage->setup( { type => 'jsonfile', path => $default_file } ) eq 'WebService::Google::Client::AuthStorage',
    'auth_storage returns WebService::Google::Client::AuthStorage' );
  ok( my $aref_token_emails = $gapi->auth_storage->storage->get_token_emails_from_storage, 'Load token emails from config' );
  if ( !$user )    ## default to the first user in config file if none defined yet
  {
    ok( $user = $aref_token_emails->[0], "setting test user to first configured entry in config - '$user'" );
  }

  #note("ENV CONFIG SETS $ENV{'GMAIL_FOR_TESTING'} WITHIN $ENV{'GOOGLE_TOKENSFILE'} ");

  if ( -e $default_file && $user )
  {
    note( "Running tests with user '$user' using '$default_file' credentials" );


    ok( $gapi->user( $user ) eq $user, "\$gapi->user('$user') eq '$user'" );

    ## The reasoning behind not running doscovery tests without valid auth'd credentials is to
    ##  ensure that tests don't fail when Google blocks discovery requests for unauthenticated users
    ##  due to exceeding access limits.

    ok( my $ret = WebService::Google::Client::Discovery->new->discover_all, 'WebService::Google::Client::Discovery->new->discover_all returns something' );
  TODO:
    {
      local $TODO = "tests for each WebService::Google::Client::Discovery method with a valid user configuration";
      ok( undef, 'get_rest' );

      #ok(undef,'discover_all');
      ok( undef, 'available_APIs' );
      ok( undef, 'service_exists' );
      ok( undef, 'print_supported' );
      ok( undef, 'available_versions' );
      ok( undef, 'latest_stable_version' );
      ok( undef, 'find_APIs_with_diff_vers' );
      ok( undef, 'search_in_services' );
      ok( undef, 'get_method_meta' );
      ok( undef, 'get_resource_meta' );
      ok( undef, 'list_of_methods' );
      ok( undef, 'meta_for_API' );
    }

  }
};    ## END 'Test with User Configuration' SUBTEST


#note("Testing WebService::Google::Client $WebService::Google::Client::VERSION, Perl $], $^X");

done_testing();
