/*
 * Copyright (C) 2012 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.gallery3d.util;

import android.annotation.TargetApi;
import android.graphics.Matrix;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;

import com.android.gallery3d.common.ApiHelper;

public final class MotionEventHelper {
    private MotionEventHelper() {}

    public static MotionEvent transformEvent(MotionEvent e, Matrix m) {
        // We try to use the new transform method if possible because it uses
        // less memory.
        if (ApiHelper.HAS_MOTION_EVENT_TRANSFORM) {
            return transformEventNew(e, m);
        } else {
            return transformEventOld(e, m);
        }
    }

    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
    private static MotionEvent transformEventNew(MotionEvent e, Matrix m) {
        MotionEvent newEvent = MotionEvent.obtain(e);
        newEvent.transform(m);
        return newEvent;
    }

    // This is copied from Input.cpp in the android framework.
    private static MotionEvent transformEventOld(MotionEvent e, Matrix m) {
        long downTime = e.getDownTime();
        long eventTime = e.getEventTime();
        int action = e.getAction();
        int pointerCount = e.getPointerCount();
        int[] pointerIds = getPointerIds(e);
        PointerCoords[] pointerCoords = getPointerCoords(e);
        int metaState = e.getMetaState();
        float xPrecision = e.getXPrecision();
        float yPrecision = e.getYPrecision();
        int deviceId = e.getDeviceId();
        int edgeFlags = e.getEdgeFlags();
        int source = e.getSource();
        int flags = e.getFlags();

        // Copy the x and y coordinates into an array, map them, and copy back.
        float[] xy = new float[pointerCoords.length * 2];
        for (int i = 0; i < pointerCount;i++) {
            xy[2 * i] = pointerCoords[i].x;
            xy[2 * i + 1] = pointerCoords[i].y;
        }
        m.mapPoints(xy);
        for (int i = 0; i < pointerCount;i++) {
            pointerCoords[i].x = xy[2 * i];
            pointerCoords[i].y = xy[2 * i + 1];
            pointerCoords[i].orientation = transformAngle(
                m, pointerCoords[i].orientation);
        }

        MotionEvent n = MotionEvent.obtain(downTime, eventTime, action,
                pointerCount, pointerIds, pointerCoords, metaState, xPrecision,
                yPrecision, deviceId, edgeFlags, source, flags);

        return n;
    }

    private static int[] getPointerIds(MotionEvent e) {
        int n = e.getPointerCount();
        int[] r = new int[n];
        for (int i = 0; i < n; i++) {
            r[i] = e.getPointerId(i);
        }
        return r;
    }

    private static PointerCoords[] getPointerCoords(MotionEvent e) {
        int n = e.getPointerCount();
        PointerCoords[] r = new PointerCoords[n];
        for (int i = 0; i < n; i++) {
            r[i] = new PointerCoords();
            e.getPointerCoords(i, r[i]);
        }
        return r;
    }

    private static float transformAngle(Matrix m, float angleRadians) {
        // Construct and transform a vector oriented at the specified clockwise
        // angle from vertical.  Coordinate system: down is increasing Y, right is
        // increasing X.
        float[] v = new float[2];
        v[0] = FloatMath.sin(angleRadians);
        v[1] = -FloatMath.cos(angleRadians);
        m.mapVectors(v);

        // Derive the transformed vector's clockwise angle from vertical.
        float result = (float) Math.atan2(v[0], -v[1]);
        if (result < -Math.PI / 2) {
            result += Math.PI;
        } else if (result > Math.PI / 2) {
            result -= Math.PI;
        }
        return result;
    }
}
