/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.android.inputmethod.research;

import android.util.JsonReader;
import android.util.Log;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;

import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.define.ProductionFlag;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class MotionEventReader {
    private static final String TAG = MotionEventReader.class.getSimpleName();
    private static final boolean DEBUG = false
            && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
    // Assumes that MotionEvent.ACTION_MASK does not have all bits set.`
    private static final int UNINITIALIZED_ACTION = ~MotionEvent.ACTION_MASK;
    // No legitimate int is negative
    private static final int UNINITIALIZED_INT = -1;
    // No legitimate long is negative
    private static final long UNINITIALIZED_LONG = -1L;
    // No legitimate float is negative
    private static final float UNINITIALIZED_FLOAT = -1.0f;

    public ReplayData readMotionEventData(final File file) {
        final ReplayData replayData = new ReplayData();
        try {
            // Read file
            final JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(
                    new FileInputStream(file))));
            jsonReader.beginArray();
            while (jsonReader.hasNext()) {
                readLogStatement(jsonReader, replayData);
            }
            jsonReader.endArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return replayData;
    }

    @UsedForTesting
    static class ReplayData {
        final ArrayList<Integer> mActions = new ArrayList<Integer>();
        final ArrayList<PointerProperties[]> mPointerPropertiesArrays
                = new ArrayList<PointerProperties[]>();
        final ArrayList<PointerCoords[]> mPointerCoordsArrays = new ArrayList<PointerCoords[]>();
        final ArrayList<Long> mTimes = new ArrayList<Long>();
    }

    /**
     * Read motion data from a logStatement and store it in {@code replayData}.
     *
     * Two kinds of logStatements can be read.  In the first variant, the MotionEvent data is
     * represented as attributes at the top level like so:
     *
     * <pre>
     * {
     *   "_ct": 1359590400000,
     *   "_ut": 4381933,
     *   "_ty": "MotionEvent",
     *   "action": "UP",
     *   "isLoggingRelated": false,
     *   "x": 100,
     *   "y": 200
     * }
     * </pre>
     *
     * In the second variant, there is a separate attribute for the MotionEvent that includes
     * historical data if present:
     *
     * <pre>
     * {
     *   "_ct": 135959040000,
     *   "_ut": 4382702,
     *   "_ty": "MotionEvent",
     *   "action": "MOVE",
     *   "isLoggingRelated": false,
     *   "motionEvent": {
     *     "pointerIds": [
     *       0
     *     ],
     *     "xyt": [
     *       {
     *         "t": 4382551,
     *         "d": [
     *           {
     *             "x": 141.25,
     *             "y": 151.8485107421875,
     *             "toma": 101.82337188720703,
     *             "tomi": 101.82337188720703,
     *             "o": 0.0
     *           }
     *         ]
     *       },
     *       {
     *         "t": 4382559,
     *         "d": [
     *           {
     *             "x": 140.7266082763672,
     *             "y": 151.8485107421875,
     *             "toma": 101.82337188720703,
     *             "tomi": 101.82337188720703,
     *             "o": 0.0
     *           }
     *         ]
     *       }
     *     ]
     *   }
     * },
     * </pre>
     */
    @UsedForTesting
    /* package for test */ void readLogStatement(final JsonReader jsonReader,
            final ReplayData replayData) throws IOException {
        String logStatementType = null;
        int actionType = UNINITIALIZED_ACTION;
        int x = UNINITIALIZED_INT;
        int y = UNINITIALIZED_INT;
        long time = UNINITIALIZED_LONG;
        boolean isLoggingRelated = false;

        jsonReader.beginObject();
        while (jsonReader.hasNext()) {
            final String key = jsonReader.nextName();
            if (key.equals("_ty")) {
                logStatementType = jsonReader.nextString();
            } else if (key.equals("_ut")) {
                time = jsonReader.nextLong();
            } else if (key.equals("x")) {
                x = jsonReader.nextInt();
            } else if (key.equals("y")) {
                y = jsonReader.nextInt();
            } else if (key.equals("action")) {
                final String s = jsonReader.nextString();
                if (s.equals("UP")) {
                    actionType = MotionEvent.ACTION_UP;
                } else if (s.equals("DOWN")) {
                    actionType = MotionEvent.ACTION_DOWN;
                } else if (s.equals("MOVE")) {
                    actionType = MotionEvent.ACTION_MOVE;
                }
            } else if (key.equals("loggingRelated")) {
                isLoggingRelated = jsonReader.nextBoolean();
            } else if (logStatementType != null && logStatementType.equals("MotionEvent")
                    && key.equals("motionEvent")) {
                if (actionType == UNINITIALIZED_ACTION) {
                    Log.e(TAG, "no actionType assigned in MotionEvent json");
                }
                // Second variant of LogStatement.
                if (isLoggingRelated) {
                    jsonReader.skipValue();
                } else {
                    readEmbeddedMotionEvent(jsonReader, replayData, actionType);
                }
            } else {
                if (DEBUG) {
                    Log.w(TAG, "Unknown JSON key in LogStatement: " + key);
                }
                jsonReader.skipValue();
            }
        }
        jsonReader.endObject();

        if (logStatementType != null && time != UNINITIALIZED_LONG && x != UNINITIALIZED_INT
                && y != UNINITIALIZED_INT && actionType != UNINITIALIZED_ACTION
                && logStatementType.equals("MotionEvent") && !isLoggingRelated) {
            // First variant of LogStatement.
            final PointerProperties pointerProperties = new PointerProperties();
            pointerProperties.id = 0;
            pointerProperties.toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
            final PointerProperties[] pointerPropertiesArray = {
                pointerProperties
            };
            final PointerCoords pointerCoords = new PointerCoords();
            pointerCoords.x = x;
            pointerCoords.y = y;
            pointerCoords.pressure = 1.0f;
            pointerCoords.size = 1.0f;
            final PointerCoords[] pointerCoordsArray = {
                pointerCoords
            };
            addMotionEventData(replayData, actionType, time, pointerPropertiesArray,
                    pointerCoordsArray);
        }
    }

    private void readEmbeddedMotionEvent(final JsonReader jsonReader, final ReplayData replayData,
            final int actionType) throws IOException {
        jsonReader.beginObject();
        PointerProperties[] pointerPropertiesArray = null;
        while (jsonReader.hasNext()) {  // pointerIds/xyt
            final String name = jsonReader.nextName();
            if (name.equals("pointerIds")) {
                pointerPropertiesArray = readPointerProperties(jsonReader);
            } else if (name.equals("xyt")) {
                readPointerData(jsonReader, replayData, actionType, pointerPropertiesArray);
            }
        }
        jsonReader.endObject();
    }

    private PointerProperties[] readPointerProperties(final JsonReader jsonReader)
            throws IOException {
        final ArrayList<PointerProperties> pointerPropertiesArrayList =
                new ArrayList<PointerProperties>();
        jsonReader.beginArray();
        while (jsonReader.hasNext()) {
            final PointerProperties pointerProperties = new PointerProperties();
            pointerProperties.id = jsonReader.nextInt();
            pointerProperties.toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
            pointerPropertiesArrayList.add(pointerProperties);
        }
        jsonReader.endArray();
        return pointerPropertiesArrayList.toArray(
                new PointerProperties[pointerPropertiesArrayList.size()]);
    }

    private void readPointerData(final JsonReader jsonReader, final ReplayData replayData,
            final int actionType, final PointerProperties[] pointerPropertiesArray)
            throws IOException {
        if (pointerPropertiesArray == null) {
            Log.e(TAG, "PointerIDs must be given before xyt data in json for MotionEvent");
            jsonReader.skipValue();
            return;
        }
        long time = UNINITIALIZED_LONG;
        jsonReader.beginArray();
        while (jsonReader.hasNext()) {  // Array of historical data
            jsonReader.beginObject();
            final ArrayList<PointerCoords> pointerCoordsArrayList = new ArrayList<PointerCoords>();
            while (jsonReader.hasNext()) {  // Time/data object
                final String name = jsonReader.nextName();
                if (name.equals("t")) {
                    time = jsonReader.nextLong();
                } else if (name.equals("d")) {
                    jsonReader.beginArray();
                    while (jsonReader.hasNext()) {  // array of data per pointer
                        final PointerCoords pointerCoords = readPointerCoords(jsonReader);
                        if (pointerCoords != null) {
                            pointerCoordsArrayList.add(pointerCoords);
                        }
                    }
                    jsonReader.endArray();
                } else {
                    jsonReader.skipValue();
                }
            }
            jsonReader.endObject();
            // Data was recorded as historical events, but must be split apart into
            // separate MotionEvents for replaying
            if (time != UNINITIALIZED_LONG) {
                addMotionEventData(replayData, actionType, time, pointerPropertiesArray,
                        pointerCoordsArrayList.toArray(
                                new PointerCoords[pointerCoordsArrayList.size()]));
            } else {
                Log.e(TAG, "Time not assigned in json for MotionEvent");
            }
        }
        jsonReader.endArray();
    }

    private PointerCoords readPointerCoords(final JsonReader jsonReader) throws IOException {
        jsonReader.beginObject();
        float x = UNINITIALIZED_FLOAT;
        float y = UNINITIALIZED_FLOAT;
        while (jsonReader.hasNext()) {  // x,y
            final String name = jsonReader.nextName();
            if (name.equals("x")) {
                x = (float) jsonReader.nextDouble();
            } else if (name.equals("y")) {
                y = (float) jsonReader.nextDouble();
            } else {
                jsonReader.skipValue();
            }
        }
        jsonReader.endObject();

        if (Float.compare(x, UNINITIALIZED_FLOAT) == 0
                || Float.compare(y, UNINITIALIZED_FLOAT) == 0) {
            Log.w(TAG, "missing x or y value in MotionEvent json");
            return null;
        }
        final PointerCoords pointerCoords = new PointerCoords();
        pointerCoords.x = x;
        pointerCoords.y = y;
        pointerCoords.pressure = 1.0f;
        pointerCoords.size = 1.0f;
        return pointerCoords;
    }

    /**
     * Tests that {@code x} is uninitialized.
     *
     * Assumes that {@code x} will never be given a valid value less than 0, and that
     * UNINITIALIZED_FLOAT is less than 0.0f.
     */
    private boolean isUninitializedFloat(final float x) {
        return x < 0.0f;
    }

    private void addMotionEventData(final ReplayData replayData, final int actionType,
            final long time, final PointerProperties[] pointerProperties,
            final PointerCoords[] pointerCoords) {
        replayData.mActions.add(actionType);
        replayData.mTimes.add(time);
        replayData.mPointerPropertiesArrays.add(pointerProperties);
        replayData.mPointerCoordsArrays.add(pointerCoords);
    }
}
