/*
 * Copyright (C) 2010 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.
 */

#define LOG_TAG "PointerController"

//#define LOG_NDEBUG 0

// Log debug messages about pointer updates
#define DEBUG_POINTER_UPDATES 0

#include "PointerController.h"

#include <cutils/log.h>

#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkColor.h>
#include <SkPaint.h>
#include <SkXfermode.h>

namespace android {

// --- PointerController ---

// Time to wait before starting the fade when the pointer is inactive.
static const nsecs_t INACTIVITY_FADE_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
static const nsecs_t INACTIVITY_FADE_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds

// Time to spend fading out the pointer completely.
static const nsecs_t FADE_DURATION = 500 * 1000000LL; // 500 ms

// Time to wait between frames.
static const nsecs_t FADE_FRAME_INTERVAL = 1000000000LL / 60;

// Amount to subtract from alpha per frame.
static const float FADE_DECAY_PER_FRAME = float(FADE_FRAME_INTERVAL) / FADE_DURATION;


PointerController::PointerController(const sp<Looper>& looper, int32_t pointerLayer) :
        mLooper(looper), mPointerLayer(pointerLayer) {
    AutoMutex _l(mLock);

    mLocked.displayWidth = -1;
    mLocked.displayHeight = -1;
    mLocked.displayOrientation = DISPLAY_ORIENTATION_0;

    mLocked.pointerX = 0;
    mLocked.pointerY = 0;
    mLocked.buttonState = 0;

    mLocked.iconBitmap = NULL;
    mLocked.iconHotSpotX = 0;
    mLocked.iconHotSpotY = 0;

    mLocked.fadeAlpha = 1;
    mLocked.inactivityFadeDelay = INACTIVITY_FADE_DELAY_NORMAL;

    mLocked.wantVisible = false;
    mLocked.visible = false;
    mLocked.drawn = false;

    mHandler = new WeakMessageHandler(this);
}

PointerController::~PointerController() {
    mLooper->removeMessages(mHandler);

    if (mSurfaceControl != NULL) {
        mSurfaceControl->clear();
        mSurfaceControl.clear();
    }

    if (mSurfaceComposerClient != NULL) {
        mSurfaceComposerClient->dispose();
        mSurfaceComposerClient.clear();
    }

    delete mLocked.iconBitmap;
}

bool PointerController::getBounds(float* outMinX, float* outMinY,
        float* outMaxX, float* outMaxY) const {
    AutoMutex _l(mLock);

    return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
}

bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
        float* outMaxX, float* outMaxY) const {
    if (mLocked.displayWidth <= 0 || mLocked.displayHeight <= 0) {
        return false;
    }

    *outMinX = 0;
    *outMinY = 0;
    switch (mLocked.displayOrientation) {
    case DISPLAY_ORIENTATION_90:
    case DISPLAY_ORIENTATION_270:
        *outMaxX = mLocked.displayHeight - 1;
        *outMaxY = mLocked.displayWidth - 1;
        break;
    default:
        *outMaxX = mLocked.displayWidth - 1;
        *outMaxY = mLocked.displayHeight - 1;
        break;
    }
    return true;
}

void PointerController::move(float deltaX, float deltaY) {
#if DEBUG_POINTER_UPDATES
    LOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
#endif
    if (deltaX == 0.0f && deltaY == 0.0f) {
        return;
    }

    AutoMutex _l(mLock);

    setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
}

void PointerController::setButtonState(uint32_t buttonState) {
#if DEBUG_POINTER_UPDATES
    LOGD("Set button state 0x%08x", buttonState);
#endif
    AutoMutex _l(mLock);

    if (mLocked.buttonState != buttonState) {
        mLocked.buttonState = buttonState;
        unfadeBeforeUpdateLocked();
        updateLocked();
    }
}

uint32_t PointerController::getButtonState() const {
    AutoMutex _l(mLock);

    return mLocked.buttonState;
}

void PointerController::setPosition(float x, float y) {
#if DEBUG_POINTER_UPDATES
    LOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
#endif
    AutoMutex _l(mLock);

    setPositionLocked(x, y);
}

void PointerController::setPositionLocked(float x, float y) {
    float minX, minY, maxX, maxY;
    if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
        if (x <= minX) {
            mLocked.pointerX = minX;
        } else if (x >= maxX) {
            mLocked.pointerX = maxX;
        } else {
            mLocked.pointerX = x;
        }
        if (y <= minY) {
            mLocked.pointerY = minY;
        } else if (y >= maxY) {
            mLocked.pointerY = maxY;
        } else {
            mLocked.pointerY = y;
        }
        unfadeBeforeUpdateLocked();
        updateLocked();
    }
}

void PointerController::getPosition(float* outX, float* outY) const {
    AutoMutex _l(mLock);

    *outX = mLocked.pointerX;
    *outY = mLocked.pointerY;
}

void PointerController::fade() {
    AutoMutex _l(mLock);

    startFadeLocked();
}

void PointerController::unfade() {
    AutoMutex _l(mLock);

    if (unfadeBeforeUpdateLocked()) {
        updateLocked();
    }
}

void PointerController::setInactivityFadeDelay(InactivityFadeDelay inactivityFadeDelay) {
    AutoMutex _l(mLock);

    if (mLocked.inactivityFadeDelay != inactivityFadeDelay) {
        mLocked.inactivityFadeDelay = inactivityFadeDelay;
        startInactivityFadeDelayLocked();
    }
}

void PointerController::updateLocked() {
    bool wantVisibleAndHavePointerIcon = mLocked.wantVisible && mLocked.iconBitmap;

    if (wantVisibleAndHavePointerIcon) {
        // Want the pointer to be visible.
        // Ensure the surface is created and drawn.
        if (!createSurfaceIfNeededLocked() || !drawPointerIfNeededLocked()) {
            return;
        }
    } else {
        // Don't want the pointer to be visible.
        // If it is not visible then we are done.
        if (mSurfaceControl == NULL || !mLocked.visible) {
            return;
        }
    }

    status_t status = mSurfaceComposerClient->openTransaction();
    if (status) {
        LOGE("Error opening surface transaction to update pointer surface.");
        return;
    }

    if (wantVisibleAndHavePointerIcon) {
        status = mSurfaceControl->setPosition(
                mLocked.pointerX - mLocked.iconHotSpotX,
                mLocked.pointerY - mLocked.iconHotSpotY);
        if (status) {
            LOGE("Error %d moving pointer surface.", status);
            goto CloseTransaction;
        }

        status = mSurfaceControl->setAlpha(mLocked.fadeAlpha);
        if (status) {
            LOGE("Error %d setting pointer surface alpha.", status);
            goto CloseTransaction;
        }

        if (!mLocked.visible) {
            status = mSurfaceControl->setLayer(mPointerLayer);
            if (status) {
                LOGE("Error %d setting pointer surface layer.", status);
                goto CloseTransaction;
            }

            status = mSurfaceControl->show(mPointerLayer);
            if (status) {
                LOGE("Error %d showing pointer surface.", status);
                goto CloseTransaction;
            }

            mLocked.visible = true;
        }
    } else {
        if (mLocked.visible) {
            status = mSurfaceControl->hide();
            if (status) {
                LOGE("Error %d hiding pointer surface.", status);
                goto CloseTransaction;
            }

            mLocked.visible = false;
        }
    }

CloseTransaction:
    status = mSurfaceComposerClient->closeTransaction();
    if (status) {
        LOGE("Error closing surface transaction to update pointer surface.");
    }
}

void PointerController::setDisplaySize(int32_t width, int32_t height) {
    AutoMutex _l(mLock);

    if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
        mLocked.displayWidth = width;
        mLocked.displayHeight = height;

        float minX, minY, maxX, maxY;
        if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
            mLocked.pointerX = (minX + maxX) * 0.5f;
            mLocked.pointerY = (minY + maxY) * 0.5f;
        } else {
            mLocked.pointerX = 0;
            mLocked.pointerY = 0;
        }

        updateLocked();
    }
}

void PointerController::setDisplayOrientation(int32_t orientation) {
    AutoMutex _l(mLock);

    if (mLocked.displayOrientation != orientation) {
        // Apply offsets to convert from the pixel top-left corner position to the pixel center.
        // This creates an invariant frame of reference that we can easily rotate when
        // taking into account that the pointer may be located at fractional pixel offsets.
        float x = mLocked.pointerX + 0.5f;
        float y = mLocked.pointerY + 0.5f;
        float temp;

        // Undo the previous rotation.
        switch (mLocked.displayOrientation) {
        case DISPLAY_ORIENTATION_90:
            temp = x;
            x = mLocked.displayWidth - y;
            y = temp;
            break;
        case DISPLAY_ORIENTATION_180:
            x = mLocked.displayWidth - x;
            y = mLocked.displayHeight - y;
            break;
        case DISPLAY_ORIENTATION_270:
            temp = x;
            x = y;
            y = mLocked.displayHeight - temp;
            break;
        }

        // Perform the new rotation.
        switch (orientation) {
        case DISPLAY_ORIENTATION_90:
            temp = x;
            x = y;
            y = mLocked.displayWidth - x;
            break;
        case DISPLAY_ORIENTATION_180:
            x = mLocked.displayWidth - x;
            y = mLocked.displayHeight - y;
            break;
        case DISPLAY_ORIENTATION_270:
            temp = x;
            x = mLocked.displayHeight - y;
            y = temp;
            break;
        }

        // Apply offsets to convert from the pixel center to the pixel top-left corner position
        // and save the results.
        mLocked.pointerX = x - 0.5f;
        mLocked.pointerY = y - 0.5f;
        mLocked.displayOrientation = orientation;

        updateLocked();
    }
}

void PointerController::setPointerIcon(const SkBitmap* bitmap, float hotSpotX, float hotSpotY) {
    AutoMutex _l(mLock);

    if (mLocked.iconBitmap) {
        delete mLocked.iconBitmap;
        mLocked.iconBitmap = NULL;
    }

    if (bitmap) {
        mLocked.iconBitmap = new SkBitmap();
        bitmap->copyTo(mLocked.iconBitmap, SkBitmap::kARGB_8888_Config);
    }

    mLocked.iconHotSpotX = hotSpotX;
    mLocked.iconHotSpotY = hotSpotY;
    mLocked.drawn = false;
}

bool PointerController::createSurfaceIfNeededLocked() {
    if (!mLocked.iconBitmap) {
        // If we don't have a pointer icon, then no point allocating a surface now.
        return false;
    }

    if (mSurfaceComposerClient == NULL) {
        mSurfaceComposerClient = new SurfaceComposerClient();
    }

    if (mSurfaceControl == NULL) {
        mSurfaceControl = mSurfaceComposerClient->createSurface(getpid(),
                String8("Pointer Icon"), 0,
                mLocked.iconBitmap->width(), mLocked.iconBitmap->height(),
                PIXEL_FORMAT_RGBA_8888);
        if (mSurfaceControl == NULL) {
            LOGE("Error creating pointer surface.");
            return false;
        }
    }
    return true;
}

bool PointerController::drawPointerIfNeededLocked() {
    if (!mLocked.drawn) {
        if (!mLocked.iconBitmap) {
            return false;
        }

        if (!resizeSurfaceLocked(mLocked.iconBitmap->width(), mLocked.iconBitmap->height())) {
            return false;
        }

        sp<Surface> surface = mSurfaceControl->getSurface();

        Surface::SurfaceInfo surfaceInfo;
        status_t status = surface->lock(&surfaceInfo);
        if (status) {
            LOGE("Error %d locking pointer surface before drawing.", status);
            return false;
        }

        SkBitmap surfaceBitmap;
        ssize_t bpr = surfaceInfo.s * bytesPerPixel(surfaceInfo.format);
        surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config, surfaceInfo.w, surfaceInfo.h, bpr);
        surfaceBitmap.setPixels(surfaceInfo.bits);

        SkCanvas surfaceCanvas;
        surfaceCanvas.setBitmapDevice(surfaceBitmap);

        SkPaint paint;
        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
        surfaceCanvas.drawBitmap(*mLocked.iconBitmap, 0, 0, &paint);

        status = surface->unlockAndPost();
        if (status) {
            LOGE("Error %d unlocking pointer surface after drawing.", status);
            return false;
        }
    }

    mLocked.drawn = true;
    return true;
}

bool PointerController::resizeSurfaceLocked(int32_t width, int32_t height) {
    status_t status = mSurfaceComposerClient->openTransaction();
    if (status) {
        LOGE("Error opening surface transaction to resize pointer surface.");
        return false;
    }

    status = mSurfaceControl->setSize(width, height);
    if (status) {
        LOGE("Error %d setting pointer surface size.", status);
        return false;
    }

    status = mSurfaceComposerClient->closeTransaction();
    if (status) {
        LOGE("Error closing surface transaction to resize pointer surface.");
        return false;
    }

    return true;
}

void PointerController::handleMessage(const Message& message) {
    switch (message.what) {
    case MSG_FADE_STEP: {
        AutoMutex _l(mLock);
        fadeStepLocked();
        break;
    }
    }
}

bool PointerController::unfadeBeforeUpdateLocked() {
    sendFadeStepMessageDelayedLocked(getInactivityFadeDelayTimeLocked());

    if (isFadingLocked()) {
        mLocked.wantVisible = true;
        mLocked.fadeAlpha = 1;
        return true; // update required to effect the unfade
    }
    return false; // update not required
}

void PointerController::startFadeLocked() {
    if (!isFadingLocked()) {
        sendFadeStepMessageDelayedLocked(0);
    }
}

void PointerController::startInactivityFadeDelayLocked() {
    if (!isFadingLocked()) {
        sendFadeStepMessageDelayedLocked(getInactivityFadeDelayTimeLocked());
    }
}

void PointerController::fadeStepLocked() {
    if (mLocked.wantVisible) {
        mLocked.fadeAlpha -= FADE_DECAY_PER_FRAME;
        if (mLocked.fadeAlpha < 0) {
            mLocked.fadeAlpha = 0;
            mLocked.wantVisible = false;
        } else {
            sendFadeStepMessageDelayedLocked(FADE_FRAME_INTERVAL);
        }
        updateLocked();
    }
}

bool PointerController::isFadingLocked() {
    return !mLocked.wantVisible || mLocked.fadeAlpha != 1;
}

nsecs_t PointerController::getInactivityFadeDelayTimeLocked() {
    return mLocked.inactivityFadeDelay == INACTIVITY_FADE_DELAY_SHORT
            ? INACTIVITY_FADE_DELAY_TIME_SHORT : INACTIVITY_FADE_DELAY_TIME_NORMAL;
}

void PointerController::sendFadeStepMessageDelayedLocked(nsecs_t delayTime) {
    mLooper->removeMessages(mHandler, MSG_FADE_STEP);
    mLooper->sendMessageDelayed(delayTime, mHandler, Message(MSG_FADE_STEP));
}

} // namespace android
