package arez.downstream;

import gir.Gir;
import gir.GirException;
import gir.git.Git;
import gir.io.FileUtil;
import gir.ruby.Buildr;
import gir.ruby.Ruby;
import gir.sys.SystemProperty;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import javax.annotation.Nonnull;

public final class CollectBuildStats
{
  public static void main( final String[] args )
    throws Exception
  {
    Gir.go( () -> {
      final String version = SystemProperty.get( "arez.version" );
      final HashMap<String, OrderedProperties> statistics = new HashMap<>();
      final Path workingDirectory =
        Paths.get( SystemProperty.get( "arez.deploy_test.work_dir" ) ).toAbsolutePath().normalize();
      final String localRepositoryUrl = SystemProperty.get( "arez.deploy_test.local_repository_url" );

      if ( !workingDirectory.toFile().exists() )
      {
        Gir.messenger().info( "Working directory does not exist." );
        Gir.messenger().info( "Creating directory: " + workingDirectory );
        if ( !workingDirectory.toFile().mkdirs() )
        {
          Gir.messenger().error( "Failed to create working directory: " + workingDirectory );
        }
      }

      FileUtil.inDirectory( workingDirectory, () -> {
        Gir.messenger().info( "Cloning react4j-todomvc into " + workingDirectory );
        Git.clone( "https://github.com/react4j/react4j-todomvc.git", "react4j-todomvc" );
        final Path appDirectory = workingDirectory.resolve( "react4j-todomvc" );
        FileUtil.inDirectory( appDirectory, () -> {
          Git.fetch();
          Git.resetBranch();
          Git.checkout();
          Git.pull();
          Git.deleteLocalBranches();
          Stream.of( "raw", "arez", "dagger" ).forEach( branch -> {
            Gir.messenger().info( "Processing branch " + branch + "." );

            Git.checkout( branch );
            Git.pull();
            Git.clean();
            final String newBranch = branch + "-ArezUpgrade-" + version;
            System.out.println( "Checking out " + newBranch );
            Git.checkout( newBranch, true );
            if ( Git.remoteTrackingBranches().contains( "origin/" + newBranch ) )
            {
              Git.pull();
            }
            Git.clean();

            Gir.messenger().info( "Building branch " + branch + " prior to modifications." );
            boolean initialBuildSuccess = false;
            try
            {
              final OrderedProperties buildProperties = buildAndRecordStatistics();
              statistics.put( branch + ".before", buildProperties );
              initialBuildSuccess = true;
            }
            catch ( final GirException ge )
            {
              Gir.messenger().info( "Failed to build branch '" + branch + "' before modifications.", ge );
            }

            Git.clean();

            if ( Buildr.patchBuildYmlDependency( appDirectory, "org.realityforge.arez", version ) )
            {
              Gir.messenger().info( "Building branch " + branch + " after modifications." );
              try
              {
                final String content = "repositories.remote << '" + localRepositoryUrl + "'\n";
                Files.write( appDirectory.resolve( "_buildr.rb" ), content.getBytes() );
              }
              catch ( final IOException ioe )
              {
                Gir.messenger().error( "Failed to emit _buildr.rb configuration file.", ioe );
              }

              try
              {
                final OrderedProperties buildProperties = buildAndRecordStatistics();
                statistics.put( branch + ".after", buildProperties );
              }
              catch ( final GirException ge )
              {
                if ( !initialBuildSuccess )
                {
                  Gir.messenger().error( "Failed to build branch '" + branch + "' before modifications " +
                                         "but branch also failed prior to modifications.", ge );
                }
                else
                {
                  Gir.messenger().error( "Failed to build branch '" + branch + "' after modifications.", ge );
                }
              }
            }
            else
            {
              Gir.messenger().info( "Branch " + branch + " not rebuilt as no modifications made." );
            }
          } );
        } );
      } );
      for ( final Map.Entry<String, OrderedProperties> branchStatistics : statistics.entrySet() )
      {
        final String branch = branchStatistics.getKey();
        System.out.println( branch + ": " + branchStatistics.getValue() );
      }
    } );
  }

  @Nonnull
  private static OrderedProperties buildAndRecordStatistics()
  {
    Ruby.buildr( "clean", "package", "EXCLUDE_GWT_DEV_MODULE=true", "GWT=react4j-todomvc" );
    return recordStatistics();
  }

  @Nonnull
  private static OrderedProperties recordStatistics()
  {
    final OrderedProperties branchStatistics = new OrderedProperties();
    final Path currentDirectory = FileUtil.getCurrentDirectory();
    final Path outputJsFile =
      currentDirectory.resolve( "target/generated/gwt/react4j.todomvc.TodomvcProd/todomvc/todomvc.nocache.js" );
    final File jsFile = outputJsFile.toFile();
    assert jsFile.exists();
    final long length = jsFile.length();
    branchStatistics.put( "todomvc.size", length );
    return branchStatistics;
  }
}

@@ -317,56 +317,8 @@
 hs;%0A
-import java.util.HashMap;%0Aimport java.util.Map;%0A
 impo
@@ -345,16 +345,16 @@
 Stream;%0A
+
 import j
@@ -594,24 +594,8 @@
 inal
- HashMap%3CString,
  Ord
@@ -608,17 +608,16 @@
 operties
-%3E
  statist
@@ -630,17 +630,25 @@
 new 
-HashMap%3C%3E
+OrderedProperties
 ();%0A
@@ -2528,137 +2528,150 @@
 nal 
-OrderedProperties buildProperties = buildAndRecordStatistics();%0A              statistics.put( branch + %22.before%22, buildProperties
+String prefix = branch + %22.before.%22;%0A              buildAndRecordStatistics().forEach( ( key, value ) -%3E statistics.put( prefix + key, value )
  );%0A
@@ -3608,138 +3608,151 @@
 nal 
-OrderedProperties buildProperties = buildAndRecordStatistics();%0A                statistics.put( branch + %22.after%22, buildProperties
+String prefix = branch + %22.after.%22;%0A                buildAndRecordStatistics().forEach( ( key, value ) -%3E statistics.put( prefix + key, value )
  );%0A
@@ -4500,178 +4500,46 @@
  );%0A
- 
+%0A
      
-for ( final Map.Entry%3CString, OrderedProperties%3E branchStatistics : statistics.entrySet() )%0A      %7B%0A        final String branch = branchStatistics.getKey();%0A       
+ statistics.forEach( ( k, v ) -%3E
  Sys
@@ -4555,22 +4555,17 @@
 rintln( 
-branch
+k
  + %22: %22 
@@ -4570,46 +4570,14 @@
 %22 + 
-branchStatistics.getValue() );%0A      %7D
+v ) );
 %0A   

Create a single statistics properties object