#!/usr/bin/env python3
# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
Generates Java code to declare SPLINE_POSITION and SPLINE_TIME as precomputed
array.

Run this and paste the output into //chrome/android/java/src/org/chromium/
chrome/browser/compositor/overlays/strip/StackScroller.java
"""

import math
import sys


def Main():
  # Keep these in sync with the values in //chrome/android/java/src/org/
  # chromium/chrome/browser/compositor/overlays/strip/StackScroller.java
  NB_SAMPLES = 100
  INFLEXION = 0.35  # Tension lines cross at (INFLEXION, 1)

  START_TENSION = 0.5
  END_TENSION = 1.0
  P1 = START_TENSION * INFLEXION
  P2 = 1.0 - END_TENSION * (1.0 - INFLEXION)

  spline_time = []
  spline_position = []

  xMin = 0.0
  yMin = 0.0
  for i in range(NB_SAMPLES):
    alpha = float(i) / NB_SAMPLES

    xMax = 1.0
    while 1:
      x = xMin + (xMax - xMin) / 2.0
      coef = 3.0 * x * (1.0 - x)
      tx = coef * ((1.0 - x) * P1 + x * P2) + x * x * x
      if math.fabs(tx - alpha) < 1e-5:
        break
      if tx > alpha:
        xMax = x
      else:
        xMin = x

    spline_position.append(coef * ((1.0 - x) * START_TENSION + x) + x * x * x)

    yMax = 1.0
    while 1:
      y = yMin + (yMax - yMin) / 2.0
      coef = 3.0 * y * (1.0 - y)
      dy = coef * ((1.0 - y) * START_TENSION + y) + y * y * y
      if math.fabs(dy - alpha) < 1e-5:
        break
      if dy > alpha:
        yMax = y
      else:
        yMin = y

    spline_time.append(coef * ((1.0 - y) * P1 + y * P2) + y * y * y)

  spline_position.append(1.0)
  spline_time.append(1.0)

  print(WriteJavaArrayDeclaration('SPLINE_POSITION', spline_position))
  print(WriteJavaArrayDeclaration('SPLINE_TIME', spline_time))

  return 0


def WriteJavaArrayDeclaration(name, float_list):
  MAX_CHARS_PER_LINE = 100
  INDENT_LEVELS = 2
  SPACES_PER_INDENT_LEVEL = 4
  DECLARATION_PREAMBLE = ' ' * SPACES_PER_INDENT_LEVEL * INDENT_LEVELS
  VALUES_PREAMBLE = ' ' * SPACES_PER_INDENT_LEVEL * (INDENT_LEVELS + 2)

  # Default precision is 6 decimal plates.
  FLOAT_LENGTH = len('0.123456, ')

  # +1 accounts for the trimmed space at the end.
  FLOATS_PER_LINE = (
    MAX_CHARS_PER_LINE - len(VALUES_PREAMBLE) + 1
  ) // FLOAT_LENGTH

  chunks = []
  for i in range(0, len(float_list), FLOATS_PER_LINE):
    float_chunk = float_list[i : i + FLOATS_PER_LINE]
    values = ', '.join(['%ff' % f for f in float_chunk])
    chunks.append(VALUES_PREAMBLE + values)

  s = DECLARATION_PREAMBLE + 'private static final float[] %s = {\n' % name
  s += ',\n'.join(chunks)
  s += '\n'
  s += DECLARATION_PREAMBLE + '};'
  return s


if __name__ == '__main__':
  sys.exit(Main())
