// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.regress.b77496850;

import static org.junit.Assert.assertEquals;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.code.InvokeStatic;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import org.junit.Test;

public class B77496850 extends TestBase {

  static final String LOGTAG = "";

  // Mock class for the code in PathParser below.
  public static class Path {
    void rLineTo(int x, int y) {
    }
    void cubicTo(float a, float b, float c, float d, float e, float f) {
    }
  }

  // Mock class for the code in PathParser below.
  public static class Log {
    static void w(String x, String y) {
    }
  }

  // Code copied from Android support library:
  // https://android.googlesource.com/platform/frameworks/support/+/9791ac540f94c318f6602123d7000bfc55909b81/compat/src/main/java/android/support/v4/graphics/PathParser.java
  public static class PathParser {

    private static void drawArc(Path p,
        float x0,
        float y0,
        float x1,
        float y1,
        float a,
        float b,
        float theta,
        boolean isMoreThanHalf,
        boolean isPositiveArc) {
      /* Convert rotation angle from degrees to radians */
      double thetaD = Math.toRadians(theta);
      /* Pre-compute rotation matrix entries */
      double cosTheta = Math.cos(thetaD);
      double sinTheta = Math.sin(thetaD);
      /* Transform (x0, y0) and (x1, y1) into unit space */
      /* using (inverse) rotation, followed by (inverse) scale */
      double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
      double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
      double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
      double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
      /* Compute differences and averages */
      double dx = x0p - x1p;
      double dy = y0p - y1p;
      double xm = (x0p + x1p) / 2;
      double ym = (y0p + y1p) / 2;
      /* Solve for intersecting unit circles */
      double dsq = dx * dx + dy * dy;
      if (dsq == 0.0) {
        Log.w(LOGTAG, " Points are coincident");
        return; /* Points are coincident */
      }
      double disc = 1.0 / dsq - 1.0 / 4.0;
      if (disc < 0.0) {
        Log.w(LOGTAG, "Points are too far apart " + dsq);
        float adjust = (float) (Math.sqrt(dsq) / 1.99999);
        drawArc(p, x0, y0, x1, y1, a * adjust,
            b * adjust, theta, isMoreThanHalf, isPositiveArc);
        return; /* Points are too far apart */
      }
      double s = Math.sqrt(disc);
      double sdx = s * dx;
      double sdy = s * dy;
      double cx;
      double cy;
      if (isMoreThanHalf == isPositiveArc) {
        cx = xm - sdy;
        cy = ym + sdx;
      } else {
        cx = xm + sdy;
        cy = ym - sdx;
      }
      double eta0 = Math.atan2((y0p - cy), (x0p - cx));
      double eta1 = Math.atan2((y1p - cy), (x1p - cx));
      double sweep = (eta1 - eta0);
      if (isPositiveArc != (sweep >= 0)) {
        if (sweep > 0) {
          sweep -= 2 * Math.PI;
        } else {
          sweep += 2 * Math.PI;
        }
      }
      cx *= a;
      cy *= b;
      double tcx = cx;
      cx = cx * cosTheta - cy * sinTheta;
      cy = tcx * sinTheta + cy * cosTheta;
      arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
    }

    /**
     * Converts an arc to cubic Bezier segments and records them in p.
     *
     * @param p     The target for the cubic Bezier segments
     * @param cx    The x coordinate center of the ellipse
     * @param cy    The y coordinate center of the ellipse
     * @param a     The radius of the ellipse in the horizontal direction
     * @param b     The radius of the ellipse in the vertical direction
     * @param e1x   E(eta1) x coordinate of the starting point of the arc
     * @param e1y   E(eta2) y coordinate of the starting point of the arc
     * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane
     * @param start The start angle of the arc on the ellipse
     * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
     */
    private static void arcToBezier(Path p,
        double cx,
        double cy,
        double a,
        double b,
        double e1x,
        double e1y,
        double theta,
        double start,
        double sweep) {
      // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html
      // and http://www.spaceroots.org/documents/ellipse/node22.html
      // Maximum of 45 degrees per cubic Bezier segment
      int numSegments = (int) Math.ceil(Math.abs(sweep * 4 / Math.PI));
      double eta1 = start;
      double cosTheta = Math.cos(theta);
      double sinTheta = Math.sin(theta);
      double cosEta1 = Math.cos(eta1);
      double sinEta1 = Math.sin(eta1);
      double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
      double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
      double anglePerSegment = sweep / numSegments;
      for (int i = 0; i < numSegments; i++) {
        double eta2 = eta1 + anglePerSegment;
        double sinEta2 = Math.sin(eta2);
        double cosEta2 = Math.cos(eta2);
        double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2);
        double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2);
        double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
        double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
        double tanDiff2 = Math.tan((eta2 - eta1) / 2);
        double alpha =
            Math.sin(eta2 - eta1) * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
        double q1x = e1x + alpha * ep1x;
        double q1y = e1y + alpha * ep1y;
        double q2x = e2x - alpha * ep2x;
        double q2y = e2y - alpha * ep2y;
        // Adding this no-op call to workaround a proguard related issue.
        p.rLineTo(0, 0);
        p.cubicTo((float) q1x,
            (float) q1y,
            (float) q2x,
            (float) q2y,
            (float) e2x,
            (float) e2y);
        eta1 = eta2;
        e1x = e2x;
        e1y = e2y;
        ep1x = ep2x;
        ep1y = ep2y;
      }
    }
  }

  // Same code as PathParser above, but with exception handlers in the two methods.
  public static class PathParserWithExceptionHandler {

    private static void drawArc(Path p,
        float x0,
        float y0,
        float x1,
        float y1,
        float a,
        float b,
        float theta,
        boolean isMoreThanHalf,
        boolean isPositiveArc) {
      try {
        /* Convert rotation angle from degrees to radians */
        double thetaD = Math.toRadians(theta);
        /* Pre-compute rotation matrix entries */
        double cosTheta = Math.cos(thetaD);
        double sinTheta = Math.sin(thetaD);
        /* Transform (x0, y0) and (x1, y1) into unit space */
        /* using (inverse) rotation, followed by (inverse) scale */
        double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
        double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
        double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
        double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
        /* Compute differences and averages */
        double dx = x0p - x1p;
        double dy = y0p - y1p;
        double xm = (x0p + x1p) / 2;
        double ym = (y0p + y1p) / 2;
        /* Solve for intersecting unit circles */
        double dsq = dx * dx + dy * dy;
        if (dsq == 0.0) {
          Log.w(LOGTAG, " Points are coincident");
          return; /* Points are coincident */
        }
        double disc = 1.0 / dsq - 1.0 / 4.0;
        if (disc < 0.0) {
          Log.w(LOGTAG, "Points are too far apart " + dsq);
          float adjust = (float) (Math.sqrt(dsq) / 1.99999);
          drawArc(p, x0, y0, x1, y1, a * adjust,
              b * adjust, theta, isMoreThanHalf, isPositiveArc);
          return; /* Points are too far apart */
        }
        double s = Math.sqrt(disc);
        double sdx = s * dx;
        double sdy = s * dy;
        double cx;
        double cy;
        if (isMoreThanHalf == isPositiveArc) {
          cx = xm - sdy;
          cy = ym + sdx;
        } else {
          cx = xm + sdy;
          cy = ym - sdx;
        }
        double eta0 = Math.atan2((y0p - cy), (x0p - cx));
        double eta1 = Math.atan2((y1p - cy), (x1p - cx));
        double sweep = (eta1 - eta0);
        if (isPositiveArc != (sweep >= 0)) {
          if (sweep > 0) {
            sweep -= 2 * Math.PI;
          } else {
            sweep += 2 * Math.PI;
          }
        }
        cx *= a;
        cy *= b;
        double tcx = cx;
        cx = cx * cosTheta - cy * sinTheta;
        cy = tcx * sinTheta + cy * cosTheta;
        arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
      } catch (Throwable t) {
        // Ignore.
      }
    }

    /**
     * Converts an arc to cubic Bezier segments and records them in p.
     *
     * @param p     The target for the cubic Bezier segments
     * @param cx    The x coordinate center of the ellipse
     * @param cy    The y coordinate center of the ellipse
     * @param a     The radius of the ellipse in the horizontal direction
     * @param b     The radius of the ellipse in the vertical direction
     * @param e1x   E(eta1) x coordinate of the starting point of the arc
     * @param e1y   E(eta2) y coordinate of the starting point of the arc
     * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane
     * @param start The start angle of the arc on the ellipse
     * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
     */
    private static void arcToBezier(Path p,
        double cx,
        double cy,
        double a,
        double b,
        double e1x,
        double e1y,
        double theta,
        double start,
        double sweep) {
      try {
        // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html
        // and http://www.spaceroots.org/documents/ellipse/node22.html
        // Maximum of 45 degrees per cubic Bezier segment
        int numSegments = (int) Math.ceil(Math.abs(sweep * 4 / Math.PI));
        double eta1 = start;
        double cosTheta = Math.cos(theta);
        double sinTheta = Math.sin(theta);
        double cosEta1 = Math.cos(eta1);
        double sinEta1 = Math.sin(eta1);
        double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
        double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
        double anglePerSegment = sweep / numSegments;
        for (int i = 0; i < numSegments; i++) {
          double eta2 = eta1 + anglePerSegment;
          double sinEta2 = Math.sin(eta2);
          double cosEta2 = Math.cos(eta2);
          double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2);
          double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2);
          double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
          double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
          double tanDiff2 = Math.tan((eta2 - eta1) / 2);
          double alpha =
              Math.sin(eta2 - eta1) * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
          double q1x = e1x + alpha * ep1x;
          double q1y = e1y + alpha * ep1y;
          double q2x = e2x - alpha * ep2x;
          double q2y = e2y - alpha * ep2y;
          // Adding this no-op call to workaround a proguard related issue.
          p.rLineTo(0, 0);
          p.cubicTo((float) q1x,
              (float) q1y,
              (float) q2x,
              (float) q2y,
              (float) e2x,
              (float) e2y);
          eta1 = eta2;
          e1x = e2x;
          e1y = e2y;
          ep1x = ep2x;
          ep1y = ep2y;
        }
      } catch (Throwable t) {
        // Ignore.
      }
    }

  }

  // Reproduction from b/77496850.
  public static class Reproduction {
    public int test() {
      int count = 0;
      for (int i = 0; i < 1000; i++){
        count += arcToBezier(1.0, 1.0, 2.0);
      }
      return count;
    }

    private static int arcToBezier(double a, double b, double sweep) {
      int count = 0;

      int numSegments = (int) sweep;

      double cosTheta = 0.5;
      double sinTheta = 0.5;
      double cosEta1 = 0.5;
      double sinEta1 = 0.5;
      double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
      double anglePerSegment = sweep / numSegments;

      for (int i = 0; i < numSegments; i++) {
        count++;
      }
      if (numSegments != count) {
        return 1;
      }
      return 0;
    }

    public static void main(String[] args) {
      for (int i = 0; i < 100; i++) {
        System.out.println(new Reproduction().test());
      }
    }
  }

  // Reproduction from b/77496850 with exception handler.
  public static class ReproductionWithExceptionHandler {
    public int test() {
      int count = 0;
      for (int i = 0; i < 1000; i++){
        count += arcToBezier(1.0, 1.0, 2.0);
      }
      return count;
    }

    private static int arcToBezier(double a, double b, double sweep) {
      try {
        int count = 0;

        int numSegments = (int) sweep;

        double cosTheta = 0.5;
        double sinTheta = 0.5;
        double cosEta1 = 0.5;
        double sinEta1 = 0.5;
        double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
        double anglePerSegment = sweep / numSegments;

        for (int i = 0; i < numSegments; i++) {
          count++;
        }
        if (numSegments != count) {
          return 1;
        }
        return 0;
      } catch (Throwable t) {
        return 1;
      }
    }

    public static void main(String[] args) {
      for (int i = 0; i < 100; i++) {
        System.out.println(new Reproduction().test());
      }
    }
  }

  private int countInvokeDoubleIsNan(DexItemFactory factory, DexCode code) {
    int count = 0;
    DexMethod doubleIsNaN = factory.createMethod(
        factory.createString("Ljava/lang/Double;"),
        factory.createString("isNaN"),
        factory.booleanDescriptor,
        new DexString[]{factory.doubleDescriptor});
    for (int i = 0; i < code.instructions.length; i++) {
      if (code.instructions[i] instanceof InvokeStatic) {
        InvokeStatic invoke = (InvokeStatic) code.instructions[i];
        if (invoke.getMethod() == doubleIsNaN) {
          count++;
        }
      }
    }
    return count;
  }

  private void checkPathParserMethods(AndroidApp app, Class testClass, int a, int b)
      throws Exception {
    CodeInspector inspector = new CodeInspector(app);
    DexItemFactory factory = inspector.getFactory();
    ClassSubject clazz = inspector.clazz(testClass);
    MethodSubject drawArc = clazz.method(
        "void",
        "drawArc",
        ImmutableList.of(
            getClass().getCanonicalName() + "$Path",
            "float", "float", "float", "float", "float", "float", "float", "boolean", "boolean"));
    MethodSubject arcToBezier = clazz.method(
        "void",
        "arcToBezier",
        ImmutableList.of(
            getClass().getCanonicalName() + "$Path",
            "double", "double", "double", "double", "double", "double",
            "double", "double", "double"));
    assertEquals(a, countInvokeDoubleIsNan(factory, drawArc.getMethod().getCode().asDexCode()));
    assertEquals(b, countInvokeDoubleIsNan(factory, arcToBezier.getMethod().getCode().asDexCode()));
  }

  private void runTestPathParser(
      Tool compiler, Class testClass, AndroidApiLevel apiLevel, int a, int b)
      throws Exception {
    AndroidApp app = readClasses(Path.class, Log.class, testClass);
    if (compiler == Tool.D8) {
      app = compileWithD8(app, o -> o.minApiLevel = apiLevel.getLevel());
    } else {
      assert compiler == Tool.R8;
      app = compileWithR8(app, "-keep class * { *; }", o -> o.minApiLevel = apiLevel.getLevel());
    }
    checkPathParserMethods(app, testClass, a, b);
  }

  @Test
  public void testSupportLibraryPathParser() throws Exception{
    for (Tool tool : Tool.valuesR8andD8()) {
      runTestPathParser(tool, PathParser.class, AndroidApiLevel.K, 14, 1);
      runTestPathParser(tool, PathParser.class, AndroidApiLevel.L, 0, 0);
      runTestPathParser(tool, PathParserWithExceptionHandler.class, AndroidApiLevel.K, 14, 1);
      runTestPathParser(tool, PathParserWithExceptionHandler.class, AndroidApiLevel.L, 0, 0);
    }
  }

  private void runTestReproduction(
      Tool compiler, Class testClass, AndroidApiLevel apiLevel, int expectedInvokeDoubleIsNanCount)
      throws Exception {
    AndroidApp app = readClasses(testClass);
    if (compiler == Tool.D8) {
      app = compileWithD8(app, o -> o.minApiLevel = apiLevel.getLevel());
    } else {
      assert compiler == Tool.R8;
      app = compileWithR8(app, "-keep class * { *; }", o -> o.minApiLevel = apiLevel.getLevel());
    }
    CodeInspector inspector = new CodeInspector(app);
    DexItemFactory factory = inspector.getFactory();
    ClassSubject clazz = inspector.clazz(testClass);
    MethodSubject arcToBezier = clazz.method(
        "int", "arcToBezier", ImmutableList.of("double", "double", "double"));
    assertEquals(
      expectedInvokeDoubleIsNanCount,
      countInvokeDoubleIsNan(factory, arcToBezier.getMethod().getCode().asDexCode()));
  }

  @Test
  public void testReproduction() throws Exception{
    for (Tool tool : Tool.valuesR8andD8()) {
      runTestReproduction(tool, Reproduction.class, AndroidApiLevel.K, tool == Tool.D8 ? 1 : 0);
      runTestReproduction(tool, Reproduction.class, AndroidApiLevel.L, 0);
      runTestReproduction(
          tool, ReproductionWithExceptionHandler.class, AndroidApiLevel.K, tool == Tool.D8 ? 1 : 0);
      runTestReproduction(tool, ReproductionWithExceptionHandler.class, AndroidApiLevel.L, 0);
    }
  }
}
