package arez.downstream;

import gir.sys.SystemProperty;
import java.util.Properties;
import javax.annotation.Nonnull;
import org.realityforge.gwt.symbolmap.SoycSizeMapsDiff;
import org.realityforge.gwt.symbolmap.SymbolEntryIndexDiff;
import org.testng.annotations.Test;
import static org.testng.Assert.*;

public class BuildStatsTest
{
  @Test
  public void arez()
    throws Exception
  {
    compareSizesForBranch( "arez", true );
  }

  @Test
  public void dagger()
    throws Exception
  {
    compareSizesForBranch( "dagger", true );
  }

  @Test
  public void spritz()
    throws Exception
  {
    compareSizesForBranch( "spritz", true );
  }

  @Test
  public void arez_j2cl()
    throws Exception
  {
    if ( WorkspaceUtil.buildJ2clBuilds() )
    {
      compareSizesForBranch( "arez_maven_j2cl", true );
    }
  }

  @Test
  public void dagger_j2cl()
    throws Exception
  {
    if ( WorkspaceUtil.buildJ2clBuilds() )
    {
      compareSizesForBranch( "dagger_maven_j2cl", true );
    }
  }

  @Test
  public void sithtracker()
    throws Exception
  {
    compareSizesForBranch( "sithtracker", false );
  }

  @Test
  public void drumloop()
    throws Exception
  {
    compareSizesForBranch( "drumloop", false );
  }

  private void compareSizesForBranch( @Nonnull final String branch, final boolean includeBranchInFixtureKey )
    throws Exception
  {
    final String nextVersion = SystemProperty.get( "arez.next.version" );
    final String previousVersion = SystemProperty.get( "arez.prev.version" );

    final Properties buildStatistics = WorkspaceTestUtil.loadBuildStatistics();
    final Properties fixtureStatistics = WorkspaceTestUtil.loadFixtureStatistics();

    final long nextVersionFixtureSize =
      extractSize( fixtureStatistics, nextVersion + ( includeBranchInFixtureKey ? "." + branch : "" ) );
    final long currentVersionFixtureSize =
      extractSize( fixtureStatistics, previousVersion + ( includeBranchInFixtureKey ? "." + branch : "" ) );
    final String beforeBuild = branch + "." + "before";
    final String afterBuild = branch + "." + "after";
    final long beforeSize = extractSize( buildStatistics, beforeBuild );
    final long afterSize = extractSize( buildStatistics, afterBuild );

    if ( 0 != nextVersionFixtureSize )
    {
      if ( nextVersionFixtureSize != afterSize )
      {
        reportSymbolDifferences( beforeBuild, afterBuild );
        fail( "Build size after upgrading arez in branch '" + branch + "' does not match the build size " +
              "configured for the next version '" + nextVersion + "' which was " + nextVersionFixtureSize +
              ". Actual build size is " + afterSize + ". The statistics can be updated by " +
              "running 'buildr update_downstream_build_stats' and committing the changes if the new size " +
              "is acceptable." );
      }
    }
    else if ( 0 != currentVersionFixtureSize )
    {
      if ( currentVersionFixtureSize != afterSize )
      {
        reportSymbolDifferences( beforeBuild, afterBuild );
        fail( "Build size after upgrading arez in branch '" + branch + "' does not match the build size " +
              "configured for the current version '" + previousVersion + "' which was " +
              currentVersionFixtureSize + ". No build size was specified for the next version. The actual build " +
              "size is " + afterSize + ". The statistics for the next version can be generated by running " +
              "'buildr update_downstream_build_stats' and committing the changes if the new size is acceptable." );
      }
    }
    else
    {
      if ( beforeSize != afterSize )
      {
        reportSymbolDifferences( beforeBuild, afterBuild );
        fail( "Build size changed after upgrading arez in branch '" + branch + "' from " + beforeSize + " to " +
              afterSize + ". The statistics for the next version can be generated by running " +
              "'buildr update_downstream_build_stats' and committing the changes if the new size is acceptable." );
      }
    }
  }

  private void reportSymbolDifferences( @Nonnull final String beforeBuild, @Nonnull final String afterBuild )
    throws Exception
  {
    final SymbolEntryIndexDiff diff =
      SymbolEntryIndexDiff.diff( WorkspaceTestUtil.getSymbolMapIndex( "todomvc", beforeBuild ),
                                 WorkspaceTestUtil.getSymbolMapIndex( "todomvc", afterBuild ) );
    if ( diff.hasDifferences() )
    {
      System.out.println( "Differences detected in symbols compiled between the " +
                          "two variants " + beforeBuild + " and " + afterBuild );
      System.out.println( diff.printToString() );
    }
    final SoycSizeMapsDiff soycDiff =
      SoycSizeMapsDiff.diff( WorkspaceTestUtil.getSoycSizeMaps( "todomvc", beforeBuild ),
                             WorkspaceTestUtil.getSoycSizeMaps( "todomvc", afterBuild ) );
    if ( soycDiff.hasDifferences() )
    {
      System.out.println( "Differences detected in sizes compiled between the " +
                          "two variants " + beforeBuild + " and " + afterBuild );
      System.out.println( soycDiff.printToString() );
    }
  }

  private long extractSize( @Nonnull final Properties properties,
                            @Nonnull final String prefix )
  {
    return Long.parseLong( properties.getProperty( prefix + ".todomvc.size", "0" ) );
  }
}

@@ -330,16 +330,116 @@
 sTest%0A%7B%0A
+  @Test%0A  public void raw()%0A    throws Exception%0A  %7B%0A    compareSizesForBranch( %22raw%22, true );%0A  %7D%0A%0A
   @Test%0A

Test raw size as it now uses arez