// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package org.mozc.android.inputmethod.japanese.keyboard;

import org.mozc.android.inputmethod.japanese.KeyboardSpecificationName;
import org.mozc.android.inputmethod.japanese.MozcLog;
import org.mozc.android.inputmethod.japanese.MozcUtil;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Input.TouchAction;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Input.TouchEvent;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Input.TouchPosition;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.KeyEvent.ProbableKeyEvent;
import org.mozc.android.inputmethod.japanese.util.LeastRecentlyUsedCacheMap;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.os.Handler;
import android.os.Looper;
import android.util.FloatMath;
import android.util.SparseArray;
import android.util.SparseIntArray;

import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * An object which guesses probable key events for typing correction feature.
 *
 * <p>We can use following values as touch event statistics, which are store in the file system.
 * <ul>
 * <li>Average of start position (X and Y).
 * <li>Variance of start position (X and Y).
 * <li>Average of delta (X and Y).
 * <li>Variance of delta (X and Y).
 * </ul>
 * We use probability distribution of 4-dimentional Gaussian distribution
 * as likelihood function.
 * We cannot use covariance so we assume that each elements are orthogonal (covariance is 0).
 *
 */
public class ProbableKeyEventGuesser {

  /**
   * Accessor for stats files.
   *
   * Extracted as an interface for testing.
   */
  @VisibleForTesting
  interface StatsFileAccessor {
    InputStream openStream(Keyboard keyboard, Configuration configuration)
        throws IOException;
  }

  /**
   * Concrete implementation of StatsFileAccessor, using AssetManager.
   */
  @VisibleForTesting
  static final class StatsFileAccessorImpl implements StatsFileAccessor {

    private final AssetManager assetManager;
    private final List<String> assetFileNames;

    StatsFileAccessorImpl(AssetManager assetManager) {
      this.assetManager = Preconditions.checkNotNull(assetManager);
      this.assetFileNames = Preconditions.checkNotNull(getAssetFileNameList(assetManager));
    }

    private static List<String> getAssetFileNameList(AssetManager assetManager) {
      try {
        return Collections.unmodifiableList(Arrays.asList(assetManager.list("")));
      } catch (IOException e) {
        MozcLog.e("Accessing asset is failed.");
      }
      return Collections.emptyList();
    }

    @Override
    public InputStream openStream(Keyboard keyboard, Configuration configuration)
        throws IOException {
      Preconditions.checkNotNull(keyboard);
      Preconditions.checkNotNull(configuration);

      String baseName =
          keyboard.getSpecification().getKeyboardSpecificationName().baseName;
      String orientation = KeyboardSpecificationName.getDeviceOrientationString(configuration);
      String fileName = String.format("%s_%s.touch_stats", baseName, orientation);
      Preconditions.checkArgument(
          fileName.indexOf(File.separator) == -1, "fileName shouldn't include separator.");
      for (String file : assetFileNames) {
        if (file.equals(fileName)) {
          return assetManager.open(fileName);
        }
      }
      throw new IOException(String.format("%s is not found.", fileName));
    }
  }

  /**
   * Calculator of likelihood.
   *
   * <p>Extracted as an interface for testing.
   */
  @VisibleForTesting
  static interface LikelihoodCalculator {

    public double getLikelihood(float firstX, float firstY, float deltaX, float deltaY,
        float[] probableEvent);
  }

  /**
   * Concrete implementation of LikelihoodCalculator.
   */
  @VisibleForTesting
  static final class LikelihoodCalculatorImpl implements LikelihoodCalculator {

    @Override
    public double getLikelihood(float firstX, float firstY, float deltaX, float deltaY,
        float[] probableEvent) {
      Preconditions.checkNotNull(probableEvent);

      float sdx = firstX - probableEvent[START_X_AVG];
      float sdy = firstY - probableEvent[START_Y_AVG];
      // Keys that are too far away from user's touch-down position
      // are not considered as possibilities
      if (Math.abs(sdx) > START_POSITION_THRESHOLD || Math.abs(sdy) > START_POSITION_THRESHOLD) {
        return 0;
      }
      double sdx2 = sdx * sdx;
      double sdy2 = sdy * sdy;

      float ddx = deltaX - probableEvent[DELTA_X_AVG];
      float ddy = deltaY - probableEvent[DELTA_Y_AVG];
      double ddx2 = ddx * ddx;
      double ddy2 = ddy * ddy;
      return Math.exp(-(
          sdx2 / (probableEvent[START_X_VAR])
          + sdy2 / (probableEvent[START_Y_VAR])
          + ddx2 / (probableEvent[DELTA_X_VAR])
          + ddy2 / (probableEvent[DELTA_X_VAR])) / 2d) / probableEvent[PRECALCULATED_DENOMINATOR];
      }
  }

  /**
   * A Runnable to load a stats file and calls back a {@link UpdateStatsListener} with loaded stats.
   *
   * <p>File access itself and updating the stats (via UpdateStatsListener) are
   * done on the caller's thread (so worker thread can be applicable).
   * So if you want to run the process asyncnously,
   * <ul>
   * <li>Run this on a worker thread.
   * <li>Make UpdateStatsListener thread safe or make it run on the UI thread.
   * </ul>
   */
  @VisibleForTesting
  static final class StatisticsLoader implements Runnable {

    @VisibleForTesting
    interface UpdateStatsListener {
      void updateStats(String formattedKeyboardName, SparseArray<float[]> stats);
    }

    private final Keyboard keyboard;
    private final Configuration configuration;
    private final StatsFileAccessor statsFileAccessor;
    private final UpdateStatsListener updateStatsListener;

    /**
     * @param statsFileAccessor an accessor for stats files. Must be non-null.
     * @param keyboard a {@link Keyboard} to specify the file to be loaded.
     * @param configuration a {@link Configuration} to specify the file to be loaded
     * @param formattedKeyboardNameToStats a {@link Map} to be updated. Must be non-null.
     * @param updateStatsExecutor an Executor on which the result is propagated
     */
    private StatisticsLoader(
        StatsFileAccessor statsFileAccessor,
        Keyboard keyboard,
        Configuration configuration,
        final Map<String, SparseArray<float[]>> formattedKeyboardNameToStats,
        final Executor updateStatsExecutor) {
      this(
          statsFileAccessor,
          keyboard,
          configuration,
          new UpdateStatsListener() {
            @Override
            public void updateStats(final String formattedKeyboardName,
                                    final SparseArray<float[]> stats) {
              Preconditions.checkNotNull(formattedKeyboardName);
              Preconditions.checkNotNull(stats);
              updateStatsExecutor.execute(new Runnable() {
                @Override
                public void run() {
                  formattedKeyboardNameToStats.put(formattedKeyboardName, stats);
                }
              });
            }
          });
    }

    @VisibleForTesting
    StatisticsLoader(StatsFileAccessor statsFileAccessor,
        Keyboard keyboard,
        Configuration configuration,
        UpdateStatsListener updateStatsListener) {
      this.statsFileAccessor = Preconditions.checkNotNull(statsFileAccessor);
      this.keyboard = Preconditions.checkNotNull(keyboard);
      this.configuration = Preconditions.checkNotNull(configuration);
      this.updateStatsListener = Preconditions.checkNotNull(updateStatsListener);
    }

    /**
     * Reads an {@link InputStream} and updates given {@link SparseArray}.
     *
     * @param stream an {@link InputStream} to be read
     * @param statsToUpdate a {@link SparseArray} which maps source_id to the values.
     *                      Expected to be empty.
     * @throws IOException when stream access fails
     */
    private void readStream(DataInputStream stream, SparseArray<float[]> statsToUpdate)
        throws IOException {
      int length = stream.readInt();
      for (int i = 0; i < length; ++i) {
        int sourceId = stream.readInt();
        float[] stats = new float[9];
        for (int j = 0; j < 8; ++j) {
          stats[j] = stream.readFloat();
        }
        stats[PRECALCULATED_DENOMINATOR] =
            FloatMath.sqrt(stats[START_X_VAR] * stats[START_Y_VAR]
                           * stats[DELTA_X_VAR] * stats[DELTA_Y_VAR]);
        statsToUpdate.put(sourceId, stats);
      }
    }

    @Override
    public void run() {
      SparseArray<float[]> result = new SparseArray<float[]>(MAX_KEY_NUMBER_IN_KEYBOARD);
      InputStream inputStream = null;
      try {
        inputStream = statsFileAccessor.openStream(keyboard, configuration);
        readStream(new DataInputStream(inputStream), result);
      } catch (IOException e) {
        MozcLog.d("Stream access fails.", e);
        return;
      } finally {
        try {
          if (inputStream != null) {
            MozcUtil.close(inputStream, true);
          }
        } catch (IOException e) {
          // Never reach here.
        }
      }
      // Successfully loaded the file so call back updateStatsListener.
      String formattedKeyboardName = keyboard.getSpecification()
          .getKeyboardSpecificationName().formattedKeyboardName(configuration);
      updateStatsListener.updateStats(formattedKeyboardName, result);
    }
  }

  // Tags for stats data.
  // The file format is
  // size : int
  // repeat for #size {
  //   source_id : int
  //   values : float[8]
  // }
  // The values should be accessed via below tags.
  private static final int START_X_AVG = 0;
  private static final int START_Y_AVG = 1;
  private static final int START_X_VAR = 2;
  private static final int START_Y_VAR = 3;
  private static final int DELTA_X_AVG = 4;
  private static final int DELTA_Y_AVG = 5;
  private static final int DELTA_X_VAR = 6;
  private static final int DELTA_Y_VAR = 7;
  // Pre-calculated value for the probability calculation.
  private static final int PRECALCULATED_DENOMINATOR = 8;

  // Threshold of likelihood. Such probable events of which likelihood is under the threshold
  // are not sent to the server.
  private static final double LIKELIHOOD_THRESHOLD = 1E-30;

  // Threshold of start position. Far probable events than the threshold are not sent.
  private static final double START_POSITION_THRESHOLD = 0.25;

  // Loaded stats are cached. This value is the size of the LRU cache.
  private static final int MAX_LRU_CACHE_CAPACITY = 6;

  // Estimated maximum number of keys in a keyboard.
  // Currently 64 is enough because even in mobile-qwerty keyboard has less than 40 keys.
  // Even if there are more keys than this, nothing will happen except for (very) small
  // performance change.
  private static final int MAX_KEY_NUMBER_IN_KEYBOARD = 64;

  // LRU cache of the stats.
  // formattedKeyboardName -> souce_id -> statistic values.
  private final Map<String, SparseArray<float[]>> formattedKeyboardNameToStats =
      new LeastRecentlyUsedCacheMap<String, SparseArray<float[]>>(MAX_LRU_CACHE_CAPACITY);

  // LRU cache of mapping table.
  // formattedKeyboardName -> souce_id -> keyCode.
  @VisibleForTesting final Map<String, SparseIntArray> formattedKeyboardNameToKeycodeMapper =
      new LeastRecentlyUsedCacheMap<String, SparseIntArray>(MAX_LRU_CACHE_CAPACITY);

  // StatsFileAccessor to access the files under assets/ directory.
  private final StatsFileAccessor statsFileAccessor;

  // An Executor to load the statistic files asynchronously.
  private final ThreadPoolExecutor dataLoadExecutor;

  // An Executor to propagate loaded statistics data.
  // Invoked from the thread which dataLoadExecutor uses.
  private final Executor dataPropagationExecutor;

  // Current Keyboard.
  private Optional<Keyboard> keyboard = Optional.absent();

  // Current Configuration.
  private Optional<Configuration> configuration = Optional.absent();

  // Formatted keyboard name.
  // This can be calculated from keyboard and configuration so is derivative variable.
  // Just for cache.
  private Optional<String> formattedKeyboardName = Optional.absent();

  // Threshold of very small likelihood.
  private final double likelihoodThreshold;

  // A Calculator of likelihood.
  private final LikelihoodCalculator likelihoodCalculator;

  /**
   * @param assetManager an AssertManager to access the stats files. Must be non-null.
   */
  public ProbableKeyEventGuesser(final AssetManager assetManager) {
    Preconditions.checkNotNull(assetManager);
    this.statsFileAccessor = new StatsFileAccessorImpl(assetManager);
    this.likelihoodThreshold = LIKELIHOOD_THRESHOLD;

    // Execute file loading on another thread.
    // Typically once commonly used keyboard's stats are loaded,
    // file access will not be done any more typically.
    // Thus corePoolSize = 0.
    this.dataLoadExecutor =
        new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1));

    // Execute propagation of read stats data on current thread.
    // By this we can avoid from synchronized keywords.
    this.dataPropagationExecutor = new Executor() {
      private final Handler mainloopHandler = new Handler(Looper.getMainLooper());
      @Override
      public void execute(Runnable command) {
        mainloopHandler.post(command);
      }
    };

    this.likelihoodCalculator = new LikelihoodCalculatorImpl();
  }

  @VisibleForTesting
  ProbableKeyEventGuesser(StatsFileAccessor statsFileAccessor,
                          double likelyhoodThreshold,
                          ThreadPoolExecutor dataLoadExecutor,
                          Executor dataPropagationExecutor,
                          LikelihoodCalculator likelihoodCalculator) {
    this.statsFileAccessor = Preconditions.checkNotNull(statsFileAccessor);
    this.likelihoodThreshold = likelyhoodThreshold;
    this.dataLoadExecutor = Preconditions.checkNotNull(dataLoadExecutor);
    this.dataPropagationExecutor = Preconditions.checkNotNull(dataPropagationExecutor);
    this.likelihoodCalculator = Preconditions.checkNotNull(likelihoodCalculator);
  }

  /**
   * Sets a {@link Keyboard}.
   *
   * This invocation might load a stats data file (typically) asynchronously.
   * Before the loading has finished
   * {@link #getProbableKeyEvents(List)} cannot return any probable key events.
   * @see #getProbableKeyEvents(List)
   * @param keyboard a {@link Keyboard} to be set.
   */
  public void setKeyboard(Keyboard keyboard) {
    this.keyboard = Optional.of(keyboard);
    updateFormattedKeyboardName();
    maybeUpdateEventStatistics();
  }

  /**
   * Sets a {@link Configuration}.
   *
   * Behaves almost the same as {@link #setKeyboard(Keyboard)}.
   * @param configuration a {@link Configuration} to be set.
   */
  public void setConfiguration(Optional<Configuration> configuration) {
    this.configuration = Preconditions.checkNotNull(configuration);
    updateFormattedKeyboardName();
    maybeUpdateEventStatistics();
  }

  /**
   * Updates (cached) {@link #formattedKeyboardName}.
   */
  private void updateFormattedKeyboardName() {
    if (!keyboard.isPresent() || !configuration.isPresent()) {
      formattedKeyboardName = Optional.absent();
      return;
    }
    formattedKeyboardName = Optional.of(keyboard.get()
                                                        .getSpecification()
                                                        .getKeyboardSpecificationName()
                                                        .formattedKeyboardName(
                                                            configuration.get()));
  }

  /**
   * If stats for current {@code Keyboard} and {@code Configuration} has not been loaded,
   * load and update it asynchronously.
   *
   * Loading queue contains only the latest task.
   * Older ones are discarded.
   */
  private void maybeUpdateEventStatistics() {
    if (!formattedKeyboardName.isPresent()
        || !keyboard.isPresent()
        || !configuration.isPresent()) {
      return;
    }
    if (!formattedKeyboardNameToStats.containsKey(formattedKeyboardName.get())) {
      for (Runnable runnable : dataLoadExecutor.getQueue()) {
        dataLoadExecutor.remove(runnable);
      }
      dataLoadExecutor.execute(
          new StatisticsLoader(
              statsFileAccessor, keyboard.get(), configuration.get(),
              formattedKeyboardNameToStats,
              dataPropagationExecutor));
    }
  }

  /**
   * Calculates probable key events for given {@code touchEventList}.
   *
   * If corresponding stats data has not been loaded yet (file access is done asynchronously),
   * empty list is returned.
   *
   * TODO(matsuzakit): Change the caller side which expects null-return-value,
   *                   before submitting this CL.
   *
   * @param touchEventList a List of TouchEvents.
   */
  public List<ProbableKeyEvent> getProbableKeyEvents(List<TouchEvent> touchEventList) {
    Preconditions.checkNotNull(touchEventList);

    // This method's responsibility is to pre-check the condition.
    // Calculation itself is done in getProbableKeyEventsInternal method.
    if (!keyboard.isPresent() || !configuration.isPresent()) {
      // Keyboard has not been set up.
      return Collections.emptyList();
    }
    if (touchEventList.size() != 1) {
      // If size == 0 , we can do nothing.
      // If size >= 2, this is special situation (saturating touch event) so do nothing.
      return Collections.emptyList();
    }
    SparseArray<float[]> eventStatistics = formattedKeyboardNameToStats.get(
        formattedKeyboardName.get());
    if (eventStatistics == null) {
      // No corresponding stats is available. Returning null.
      // The stats we need might be pushed out from the LRU cache because of bulk-updates of
      // Keyboard or Configuration.
      // For such case we invoke maybeUpdateEventStatistics method to load the stats.
      // This is very rare (and usually not happen) but just in case.
      maybeUpdateEventStatistics();
      return Collections.emptyList();
    }
    TouchEvent event = touchEventList.get(0);
    if (event.getStrokeCount() < 2) {
      // TOUCH_DOWN and TOUCH_UP should be included so at least two strokes should be in the event.
      return Collections.emptyList();
    }
    TouchPosition firstPosition = event.getStroke(0);
    TouchPosition lastPosition = event.getStroke(event.getStrokeCount() - 1);
    // The sequence of TouchPositions must start with TOUCH_DOWN action and
    // end with TOUCH_UP action.
    // Otherwise the sequence is special case so we do nothing.
    if (firstPosition.getAction() != TouchAction.TOUCH_DOWN
        || lastPosition.getAction() != TouchAction.TOUCH_UP) {
      return Collections.emptyList();
    }
    float firstX = firstPosition.getX();
    float firstY = firstPosition.getY();
    float deltaX = lastPosition.getX() - firstX;
    float deltaY = lastPosition.getY() - firstY;

    // Calculates a map, keyCode -> likelihood.
    SparseArray<Double> likelihoodArray =
        getLikelihoodArray(eventStatistics, firstX, firstY, deltaX, deltaY);
    double sumLikelihood = 0;
    for (int i = 0; i < likelihoodArray.size(); ++i) {
      sumLikelihood += likelihoodArray.valueAt(i);
    }
    // If no probable events are available or something wrong happened on the calculation,
    // return empty list.
    if (sumLikelihood <= likelihoodThreshold || Double.isNaN(sumLikelihood)) {
      return Collections.emptyList();
    }
    // Construct the result list, converting from likelihood to probability.
    List<ProbableKeyEvent> result = new ArrayList<ProbableKeyEvent>(likelihoodArray.size());
    for (int i = 0; i < likelihoodArray.size(); ++i) {
      int keyCode = likelihoodArray.keyAt(i);
      double likelihood = likelihoodArray.valueAt(i);
      ProbableKeyEvent probableKeyEvent = ProbableKeyEvent.newBuilder()
          .setProbability(likelihood / sumLikelihood)
          .setKeyCode(keyCode)
          .build();
      result.add(probableKeyEvent);
    }
    return result;
  }

  /**
   * Returns a SparseArray which maps from keyCode to likelihood.
   *
   * @return a SparseArray (non-null). The size might be 0. Its values are not NaN.
   */
  private SparseArray<Double> getLikelihoodArray(SparseArray<float[]> eventStatistics,
                                                 float firstX, float firstY,
                                                 float deltaX, float deltaY) {
    Preconditions.checkNotNull(eventStatistics);
    Preconditions.checkState(keyboard.isPresent());

    SparseArray<Double> result = new SparseArray<Double>(eventStatistics.size());
    Keyboard keyboard = this.keyboard.get();
    for (int i = 0; i < eventStatistics.size(); ++i) {
      int sourceId = eventStatistics.keyAt(i);
      int keyCode = keyboard.getKeyCode(sourceId);
      // Special key or non-existent-key.
      // Don't produce probable key events.
      if (keyCode <= 0) {
        continue;
      }
      double likelihood =
          likelihoodCalculator.getLikelihood(
              firstX, firstY, deltaX, deltaY, eventStatistics.get(sourceId));
      // Filter out too small likelihood and invalid value.
      if (likelihood <= likelihoodThreshold || Double.isNaN(likelihood)) {
        continue;
      }
      result.put(keyCode, likelihood);
    }
    return result;
  }
}
