/*
 * Copyright (C) 2018 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.launcher3.touch;

import android.graphics.PointF;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;

import java.util.function.Consumer;

/**
 * To minimize the size of the MotionEvent, historic events are not copied and passed via the
 * listener.
 */
public class TouchEventTranslator {

    private static final String TAG = "TouchEventTranslator";
    private static final boolean DEBUG = false;

    private class DownState {
        long timeStamp;
        float downX;
        float downY;
        public DownState(long timeStamp, float downX, float downY) {
            this.timeStamp = timeStamp;
            this.downX = downX;
            this.downY = downY;
        }
    };
    private final DownState ZERO = new DownState(0, 0f, 0f);

    private final Consumer<MotionEvent> mListener;

    private final SparseArray<DownState> mDownEvents;
    private final SparseArray<PointF> mFingers;

    private final SparseArray<Pair<PointerProperties[], PointerCoords[]>> mCache;

    public TouchEventTranslator(Consumer<MotionEvent> listener) {
        mDownEvents = new SparseArray<>();
        mFingers = new SparseArray<>();
        mCache = new SparseArray<>();

        mListener = listener;
    }

    public void reset() {
        mDownEvents.clear();
        mFingers.clear();
    }

    public float getDownX() {
        return mDownEvents.get(0).downX;
    }

    public float getDownY() {
        return mDownEvents.get(0).downY;
    }

    public void setDownParameters(int idx, MotionEvent e) {
        DownState ev = new DownState(e.getEventTime(), e.getX(idx), e.getY(idx));
        mDownEvents.append(idx, ev);
    }

    public void dispatchDownEvents(MotionEvent ev) {
        for(int i = 0; i < ev.getPointerCount() && i < mDownEvents.size(); i++) {
            int pid = ev.getPointerId(i);
            put(pid, i, ev.getX(i), 0, mDownEvents.get(i).timeStamp, ev);
        }
    }

    public void processMotionEvent(MotionEvent ev) {
        if (DEBUG) {
            printSamples(TAG + " processMotionEvent", ev);
        }
        int index = ev.getActionIndex();
        float x = ev.getX(index);
        float y = ev.getY(index) - mDownEvents.get(index, ZERO).downY;
        switch (ev.getActionMasked()) {
            case MotionEvent.ACTION_POINTER_DOWN:
                int pid = ev.getPointerId(index);
                if(mFingers.get(pid, null) != null) {
                    for(int i=0; i < ev.getPointerCount(); i++) {
                        pid = ev.getPointerId(i);
                        position(pid, x, y);
                    }
                    generateEvent(ev.getAction(), ev);
                } else {
                    put(pid, index, x, y, ev);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                for(int i=0; i < ev.getPointerCount(); i++) {
                    pid = ev.getPointerId(i);
                    position(pid, x, y);
                }
                generateEvent(ev.getAction(), ev);
                break;
            case MotionEvent.ACTION_POINTER_UP:
            case MotionEvent.ACTION_UP:
                pid = ev.getPointerId(index);
                lift(pid, index, x, y, ev);
                break;
            case MotionEvent.ACTION_CANCEL:
                cancel(ev);
                break;
            default:
                Log.v(TAG, "Didn't process ");
                printSamples(TAG, ev);

        }
    }

    private TouchEventTranslator put(int id, int index, float x, float y, MotionEvent ev) {
        return put(id, index, x, y, ev.getEventTime(), ev);
    }

    private TouchEventTranslator put(int id, int index, float x, float y, long ms, MotionEvent ev) {
        checkFingerExistence(id, false);
        boolean isInitialDown = (mFingers.size() == 0);

        mFingers.put(id, new PointF(x, y));
        int n = mFingers.size();

        if (mCache.get(n) == null) {
            PointerProperties[] properties = new PointerProperties[n];
            PointerCoords[] coords = new PointerCoords[n];
            for (int i = 0; i < n; i++) {
                properties[i] = new PointerProperties();
                coords[i] = new PointerCoords();
            }
            mCache.put(n, new Pair(properties, coords));
        }

        int action;
        if (isInitialDown) {
            action = MotionEvent.ACTION_DOWN;
        } else {
            action = MotionEvent.ACTION_POINTER_DOWN;
            // Set the id of the changed pointer.
            action |= index << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        }
        generateEvent(action, ms, ev);
        return this;
    }

    public TouchEventTranslator position(int id, float x, float y) {
        checkFingerExistence(id, true);
        mFingers.get(id).set(x, y);
        return this;
    }

    private TouchEventTranslator lift(int id, int index, MotionEvent ev) {
        checkFingerExistence(id, true);
        boolean isFinalUp = (mFingers.size() == 1);
        int action;
        if (isFinalUp) {
            action = MotionEvent.ACTION_UP;
        } else {
            action = MotionEvent.ACTION_POINTER_UP;
            // Set the id of the changed pointer.
            action |= index << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        }
        generateEvent(action, ev);
        mFingers.remove(id);
        return this;
    }

    private TouchEventTranslator lift(int id, int index, float x, float y, MotionEvent ev) {
        checkFingerExistence(id, true);
        mFingers.get(id).set(x, y);
        return lift(id, index, ev);
    }

    public TouchEventTranslator cancel(MotionEvent ev) {
        generateEvent(MotionEvent.ACTION_CANCEL, ev);
        mFingers.clear();
        return this;
    }

    private void checkFingerExistence(int id, boolean shouldExist) {
        if (shouldExist != (mFingers.get(id, null) != null)) {
            throw new IllegalArgumentException(
                    shouldExist ? "Finger does not exist" : "Finger already exists");
        }
    }


    /**
     * Used to debug MotionEvents being sent/received.
     */
    public void printSamples(String msg, MotionEvent ev) {
        System.out.printf("%s %s", msg, MotionEvent.actionToString(ev.getActionMasked()));
        final int pointerCount = ev.getPointerCount();
        System.out.printf("#%d/%d", ev.getActionIndex(), pointerCount);
        System.out.printf(" t=%d:", ev.getEventTime());
        for (int p = 0; p < pointerCount; p++) {
            System.out.printf("  id=%d: (%f,%f)",
                    ev.getPointerId(p), ev.getX(p), ev.getY(p));
        }
        System.out.println();
    }

    private void generateEvent(int action, MotionEvent ev) {
        generateEvent(action, ev.getEventTime(), ev);
    }

    private void generateEvent(int action, long ms, MotionEvent ev) {
        Pair<PointerProperties[], PointerCoords[]> state = getFingerState();
        MotionEvent event = MotionEvent.obtain(
                mDownEvents.get(0).timeStamp,
                ms,
                action,
                state.first.length,
                state.first,
                state.second,
                ev.getMetaState(),
                ev.getButtonState() /* buttonState */,
                ev.getXPrecision() /* xPrecision */,
                ev.getYPrecision() /* yPrecision */,
                ev.getDeviceId(),
                ev.getEdgeFlags(),
                ev.getSource(),
                ev.getFlags() /* flags */);
        if (DEBUG) {
            printSamples(TAG + " generateEvent", event);
        }
        if (event.getPointerId(event.getActionIndex()) < 0) {
            printSamples(TAG + "generateEvent", event);
            throw new IllegalStateException(event.getActionIndex() + " not found in MotionEvent");
        }
        mListener.accept(event);
        event.recycle();
    }

    /**
     * Returns the description of the fingers' state expected by MotionEvent.
     */
    private Pair<PointerProperties[], PointerCoords[]> getFingerState() {
        int nFingers = mFingers.size();

        Pair<PointerProperties[], PointerCoords[]> result = mCache.get(nFingers);
        PointerProperties[] properties = result.first;
        PointerCoords[] coordinates = result.second;

        int index = 0;
        for (int i = 0; i < mFingers.size(); i++) {
            int id = mFingers.keyAt(i);
            PointF location = mFingers.get(id);

            PointerProperties property = properties[i];
            property.id = id;
            property.toolType = MotionEvent.TOOL_TYPE_FINGER;
            properties[index] = property;

            PointerCoords coordinate = coordinates[i];
            coordinate.x = location.x;
            coordinate.y = location.y;
            coordinate.pressure = 1.0f;
            coordinates[index] = coordinate;

            index++;
        }
        return mCache.get(nFingers);
    }
}
