package votorola::b::GWT; # Copyright 2010, 2012-2013, Michael Allan.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE.

use strict; use warnings;

=pod

=head1 EXPORTS

=over 4

=cut

BEGIN
{
    use Exporter ();
    our @ISA; @ISA = qw( Exporter );
    our @EXPORT_OK; @EXPORT_OK = qw( codeserver compile compile_time_library_jar_list devmode SDK_dir
      runtime_library_jar_list version );
}
our @EXPORT_OK;

{
    use votorola::b::Config qw( do_fail config_basepath_from_package );
    my $config_path = config_basepath_from_package(__PACKAGE__) . '.pl';
    do $config_path or do_fail $config_path;

    my $version = version();
  # my $expected_version = '2.8.0';
  # $expected_version gt $version and die "Expecting at least version '$expected_version', found '$version'.";
    my $expected_version = '2.8.0+mca.1'; # get it from http://reluk.ca/project/_/gwt/release/
    if( $expected_version ne $version )
    {
        die "Expecting GWT version '$expected_version', found '$version'.  "
          . "You may need an upgrade from http://reluk.ca/project/_/gwt/release/.  Died";
    }
}



=pod

=item B<codeserver>()

Call the CodeServer for "super" development mode, per script gwt-codeserver.

=cut

sub codeserver()
{
    use votorola::b::Build qw( %option );
    use votorola::b::Console qw( print_score $verbosity );
    use votorola::b::Function qw( system_exit_decode );

    my $sdk_dir = SDK_dir();
    my $command;
    $command = join_clean( ' ',
      votorola::b::Java::home_dir() . '/bin/java',
      _common_Java_options(),
      '-classpath ' . _classpath() . ":$sdk_dir/gwt-codeserver.jar",
      'com.google.gwt.dev.codeserver.CodeServer' );
    if( defined $option{'help'} )
    {
        $command = join_clean( ' ', $command, '-help' );
    }
    else
    {
        $command = join_clean( ' ', $command, custom_codeserver_options(), @ARGV );
    }
    # else call it without any options or arguments in order to show options

    if( $verbosity ) { print "$command\n"; print_score( undef, '^' ); }
    system $command; $? != 0 and exit system_exit_decode( $? );
}



=pod

=item B<compile>()

Compiles all GWT modules for production-mode deployment.

=cut

sub compile()
{
    use votorola::b::Build qw( %option out_dir );
    use votorola::b::Console qw( print_score $verbosity );
    use votorola::b::Function qw( join_clean system_exit_decode );

    my $modules = $option{'module'};
    if( !defined $modules )
    {
      $modules = join_clean( ' ',
        'votorola.s.gwt.stage.StageIn',
        'votorola.s.gwt.mediawiki.MediaWikiIn',
        'votorola.s.gwt.pollwiki.PollwikiIn',
        'votorola.s.gwt.scene.SceneIn',
        'votorola.s.gwt.wic.CountIn',
        'votorola.s.gwt.wic.DIn' );
        # Changing these?  Change also in a/web/context/, and maybe also change the "In" pattern
        # in votorola::b::Build::build__target_doc.
    }
    my $command = join_clean( ' ',
      votorola::b::Java::home_dir() . '/bin/java',
      _common_Java_options(),
      custom_compiler_java_options(),
      '-classpath ' . _classpath(),
      'com.google.gwt.dev.Compiler', # for all options > java -classpath GWT_SDK_DIR/gwt-dev.jar com.google.gwt.dev.Compiler
      _common_GWT_options(),
      '-strict',
      '-war ' . out_dir() . '/votorola/a/web/context',
      custom_compiler_options(),
      $modules );

    print votorola::b::Build::call_stack_indentation() . "(compile\n";
    if( $verbosity ) { print "\n$command\n"; print_score( undef, '^' ); }
    system $command; $? != 0 and exit system_exit_decode( $? );
}



=pod

=item B<compile_time_library_jar_list>()

The list of all GWT library jars that are needed at compile time and are external to
Votorola, meaning outside of its code repository.  The list is cached.  It should be
appended to the Java::compile_time_library_jar_list().

=cut

sub compile_time_library_jar_list()
{
    our @_compile_time_library_jar_list; # cached
    if( !@_compile_time_library_jar_list ) # then lazily create it
    {
        my @list = ();
        push( @list, SDK_dir() . '/gwt-user.jar'); # for client-side GWT source
        push( @list, SDK_dir() . '/validation-api-1.0.0.GA.jar'); # dependency of gwt-user.jar as of GWT 2.3 http://groups.google.com/group/google-web-toolkit/t/0819c7c83eb224d8
        push( @list, SDK_dir() . '/validation-api-1.0.0.GA-sources.jar');
        @_compile_time_library_jar_list = @list;
    }
    return @_compile_time_library_jar_list;
}



=pod

=item B<devmode>()

Serves one or more GWT modules in development mode, per script gwt-devmode.

=cut

sub devmode()
{
    use votorola::b::Build qw( %option );
    use votorola::b::Console qw( print_score $verbosity );
    use votorola::b::Function qw( system_exit_decode );

    my $modules = $option{'module'};
    defined $modules or $modules = 'votorola.s.gwt.pollwiki.PollwikiIn';
      # not sure why, but that alone appears to suffice for running almost any stage module
    my $command =  join_clean( ' ',
      votorola::b::Java::home_dir() . '/bin/java',
      _common_Java_options(),
      custom_devmode_java_options(),
      '-classpath ' . _classpath(),
      'com.google.gwt.dev.DevMode', # for all options > java -classpath GWT_SDK_DIR/gwt-dev.jar com.google.gwt.dev.DevMode
      _common_GWT_options(),
      '-noserver', # no Jetty needed for HTTP files, will run our own Tomcat
      '-port 8080',
      custom_devmode_options(),
      $modules );

    if( $verbosity ) { print "$command\n"; print_score( undef, '^' ); }
    system $command; $? != 0 and exit system_exit_decode( $? );
}



=pod

=item B<runtime_library_jar_list>()

The list of all GWT library jars that are needed at runtime and are external to Votorola,
meaning outside of its code repository.

=cut

sub runtime_library_jar_list()
{
    our @_runtime_library_jar_list; # cached
    if( !@_runtime_library_jar_list ) # then lazily create it
    {
        my @list = ();
        push( @list, SDK_dir() . '/gwt-servlet.jar'); # for GWT RPC
          # we serve JSONP instead of RPC, but we need this for sake of RegExp class (in
          # use of GWTX.DEV_MODE_LOCATION_PATTERN) and such like on the server
        @_runtime_library_jar_list = @list;
    }
    return @_runtime_library_jar_list;
}



=pod

=back

=head1 PRIVATE

=over 4

=cut

##### P r i v a t e ######################################################################


=pod

=item B<_classpath>()

Returns the common portion of the classpath for both compile() and devmode().

=cut

sub _classpath()
{
    use votorola::b::Build qw( build_cache_root );
    use votorola::b::Java qw( compile_class_outdir );

    my $sdk_dir = SDK_dir();
    my $classpath = '.';
  # $classpath .= ':/home/mike/code/gwt/x-release/repo/user/src'; # TEST
    $classpath .= ':' . compile_class_outdir();
    for my $path( votorola::b::Java::compile_time_library_jar_list() )
    {
        next if $path eq 'votorola/g/web/google-gson.jar';
          # codeserver depends on (and pulls in) a newer version; don't clobber it
        next if $path eq 'votorola/g/web/servlet-api.jar';
          # codeserver + embedded servlet container depend on (and pull in) a newer version; don't clobber it

        $classpath .= ':';
        $classpath .= $path;
    }
    $classpath .= ":$sdk_dir/gwt-user.jar:$sdk_dir/gwt-dev.jar";
      # Last in order to "make sure lib-gwt-svg.jar appears before the GWT SDK."
      # See http://www.vectomatic.org/lib-gwt-svg/getting-started
    return $classpath;
}



=pod

=item B<_common_GWT_options>() ret @options

Returns GWT options common to both compile() and devmode().

=cut

sub _common_GWT_options()
{
    return
    (
      '-extra ' . _extra_outdir(),
      '-logLevel WARN', # ERROR, WARN, INFO, TRACE, DEBUG, SPAM, ALL
      '-war ' . out_dir() . '/votorola/a/web/context'
    )
}



=pod

=item B<_common_Java_options>() ret @options

Returns Java options common to both compile() and devmode().

=cut

sub _common_Java_options()
{
    return
    (
    # '-Xmx512M',
    ## MCA moved to custom_*_java_options in config file GWT_config.pl
      '-Dgwt.persistentunitcachedir=' . _extra_outdir()
        # per http://code.google.com/p/google-web-toolkit/issues/detail?id=6802
        # else dir gwt-unitCache is output
    );
}



=pod

=item B<_extra_outdir>()

The directory to which extra files are output, per GWT compiler -extra.

=cut

sub _extra_outdir()
{
    use votorola::b::Build qw( build_cache_root );
    return build_cache_root() . '/votorola/GWT-extra-out';
}



=pod

=back

=cut



1;