/*
 * Copyright (C) 2015 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.server.policy;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.os.SystemClock;
import android.util.Slog;
import android.view.Display;
import android.view.animation.LinearInterpolator;

import com.android.server.LocalServices;

import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

public class BurnInProtectionHelper implements DisplayManager.DisplayListener,
        Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener {
    private static final String TAG = "BurnInProtection";

    // Default value when max burnin radius is not set.
    public static final int BURN_IN_MAX_RADIUS_DEFAULT = -1;

    private static final long BURNIN_PROTECTION_FIRST_WAKEUP_INTERVAL_MS =
            TimeUnit.MINUTES.toMillis(1);
    private static final long BURNIN_PROTECTION_SUBSEQUENT_WAKEUP_INTERVAL_MS =
            TimeUnit.MINUTES.toMillis(2);
    private static final long BURNIN_PROTECTION_MINIMAL_INTERVAL_MS = TimeUnit.SECONDS.toMillis(10);

    private static final boolean DEBUG = false;

    private static final String ACTION_BURN_IN_PROTECTION =
            "android.internal.policy.action.BURN_IN_PROTECTION";

    private static final int BURN_IN_SHIFT_STEP = 2;
    private static final long CENTERING_ANIMATION_DURATION_MS = 100;
    private final ValueAnimator mCenteringAnimator;

    private boolean mBurnInProtectionActive;
    private boolean mFirstUpdate;

    private final int mMinHorizontalBurnInOffset;
    private final int mMaxHorizontalBurnInOffset;
    private final int mMinVerticalBurnInOffset;
    private final int mMaxVerticalBurnInOffset;

    private final int mBurnInRadiusMaxSquared;

    private int mLastBurnInXOffset = 0;
    /* 1 means increasing, -1 means decreasing */
    private int mXOffsetDirection = 1;
    private int mLastBurnInYOffset = 0;
    /* 1 means increasing, -1 means decreasing */
    private int mYOffsetDirection = 1;

    private int mAppliedBurnInXOffset = 0;
    private int mAppliedBurnInYOffset = 0;

    private final AlarmManager mAlarmManager;
    private final PendingIntent mBurnInProtectionIntent;
    private final DisplayManagerInternal mDisplayManagerInternal;
    private final Display mDisplay;

    private BroadcastReceiver mBurnInProtectionReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (DEBUG) {
                Slog.d(TAG, "onReceive " + intent);
            }
            updateBurnInProtection();
        }
    };

    public BurnInProtectionHelper(Context context, int minHorizontalOffset,
            int maxHorizontalOffset, int minVerticalOffset, int maxVerticalOffset,
            int maxOffsetRadius) {
        mMinHorizontalBurnInOffset = minHorizontalOffset;
        mMaxHorizontalBurnInOffset = maxHorizontalOffset;
        mMinVerticalBurnInOffset = minVerticalOffset;
        mMaxVerticalBurnInOffset = maxVerticalOffset;
        if (maxOffsetRadius != BURN_IN_MAX_RADIUS_DEFAULT) {
            mBurnInRadiusMaxSquared = maxOffsetRadius * maxOffsetRadius;
        } else {
            mBurnInRadiusMaxSquared = BURN_IN_MAX_RADIUS_DEFAULT;
        }

        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        context.registerReceiver(mBurnInProtectionReceiver,
                new IntentFilter(ACTION_BURN_IN_PROTECTION));
        Intent intent = new Intent(ACTION_BURN_IN_PROTECTION);
        intent.setPackage(context.getPackageName());
        intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        mBurnInProtectionIntent = PendingIntent.getBroadcast(context, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);
        DisplayManager displayManager =
                (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
        mDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
        displayManager.registerDisplayListener(this, null /* handler */);

        mCenteringAnimator = ValueAnimator.ofFloat(1f, 0f);
        mCenteringAnimator.setDuration(CENTERING_ANIMATION_DURATION_MS);
        mCenteringAnimator.setInterpolator(new LinearInterpolator());
        mCenteringAnimator.addListener(this);
        mCenteringAnimator.addUpdateListener(this);
    }

    public void startBurnInProtection() {
        if (!mBurnInProtectionActive) {
            mBurnInProtectionActive = true;
            mFirstUpdate = true;
            mCenteringAnimator.cancel();
            updateBurnInProtection();
        }
    }

    private void updateBurnInProtection() {
        if (mBurnInProtectionActive) {
            // We don't want to adjust offsets immediately after the device goes into ambient mode.
            // Instead, we want to wait until it's more likely that the user is not observing the
            // screen anymore.
            final long interval = mFirstUpdate
                ? BURNIN_PROTECTION_FIRST_WAKEUP_INTERVAL_MS
                : BURNIN_PROTECTION_SUBSEQUENT_WAKEUP_INTERVAL_MS;
            if (mFirstUpdate) {
                mFirstUpdate = false;
            } else {
                adjustOffsets();
                mAppliedBurnInXOffset = mLastBurnInXOffset;
                mAppliedBurnInYOffset = mLastBurnInYOffset;
                mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(),
                        mLastBurnInXOffset, mLastBurnInYOffset);
            }
            // We use currentTimeMillis to compute the next wakeup time since we want to wake up at
            // the same time as we wake up to update ambient mode to minimize power consumption.
            // However, we use elapsedRealtime to schedule the alarm so that setting the time can't
            // disable burn-in protection for extended periods.
            final long nowWall = System.currentTimeMillis();
            final long nowElapsed = SystemClock.elapsedRealtime();
            // Next adjustment at least ten seconds in the future.
            long nextWall = nowWall + BURNIN_PROTECTION_MINIMAL_INTERVAL_MS;
            // And aligned to the minute.
            nextWall = (nextWall - (nextWall % interval)) + interval;
            // Use elapsed real time that is adjusted to full minute on wall clock.
            final long nextElapsed = nowElapsed + (nextWall - nowWall);
            if (DEBUG) {
                Slog.d(TAG, "scheduling next wake-up, now wall time " + nowWall
                        + ", next wall: " + nextWall + ", now elapsed: " + nowElapsed
                        + ", next elapsed: " + nextElapsed);
            }
            mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, nextElapsed,
                    mBurnInProtectionIntent);
        } else {
            mAlarmManager.cancel(mBurnInProtectionIntent);
            mCenteringAnimator.start();
        }
    }

    public void cancelBurnInProtection() {
        if (mBurnInProtectionActive) {
            mBurnInProtectionActive = false;
            updateBurnInProtection();
        }
    }

    /**
     * Gently shifts current burn-in offsets, minimizing the change for the user.
     *
     * Shifts are applied in following fashion:
     * 1) shift horizontally from minimum to the maximum;
     * 2) shift vertically by one from minimum to the maximum;
     * 3) shift horizontally from maximum to the minimum;
     * 4) shift vertically by one from minimum to the maximum.
     * 5) if you reach the maximum vertically, start shifting back by one from maximum to minimum.
     *
     * On top of that, stay within specified radius. If the shift distance from the center is
     * higher than the radius, skip these values and go the next position that is within the radius.
     */
    private void adjustOffsets() {
        do {
            // By default, let's just shift the X offset.
            final int xChange = mXOffsetDirection * BURN_IN_SHIFT_STEP;
            mLastBurnInXOffset += xChange;
            if (mLastBurnInXOffset > mMaxHorizontalBurnInOffset
                    || mLastBurnInXOffset < mMinHorizontalBurnInOffset) {
                // Whoops, we went too far horizontally. Let's retract..
                mLastBurnInXOffset -= xChange;
                // change horizontal direction..
                mXOffsetDirection *= -1;
                // and let's shift the Y offset.
                final int yChange = mYOffsetDirection * BURN_IN_SHIFT_STEP;
                mLastBurnInYOffset += yChange;
                if (mLastBurnInYOffset > mMaxVerticalBurnInOffset
                        || mLastBurnInYOffset < mMinVerticalBurnInOffset) {
                    // Whoops, we went to far vertically. Let's retract..
                    mLastBurnInYOffset -= yChange;
                    // and change vertical direction.
                    mYOffsetDirection *= -1;
                }
            }
            // If we are outside of the radius, let's try again.
        } while (mBurnInRadiusMaxSquared != BURN_IN_MAX_RADIUS_DEFAULT
                && mLastBurnInXOffset * mLastBurnInXOffset + mLastBurnInYOffset * mLastBurnInYOffset
                        > mBurnInRadiusMaxSquared);
    }

    public void dump(String prefix, PrintWriter pw) {
        pw.println(prefix + TAG);
        prefix += "  ";
        pw.println(prefix + "mBurnInProtectionActive=" + mBurnInProtectionActive);
        pw.println(prefix + "mHorizontalBurnInOffsetsBounds=(" + mMinHorizontalBurnInOffset + ", "
                + mMaxHorizontalBurnInOffset + ")");
        pw.println(prefix + "mVerticalBurnInOffsetsBounds=(" + mMinVerticalBurnInOffset + ", "
                + mMaxVerticalBurnInOffset + ")");
        pw.println(prefix + "mBurnInRadiusMaxSquared=" + mBurnInRadiusMaxSquared);
        pw.println(prefix + "mLastBurnInOffset=(" + mLastBurnInXOffset + ", "
                + mLastBurnInYOffset + ")");
        pw.println(prefix + "mOfsetChangeDirections=(" + mXOffsetDirection + ", "
                + mYOffsetDirection + ")");
    }

    @Override
    public void onDisplayAdded(int i) {
    }

    @Override
    public void onDisplayRemoved(int i) {
    }

    @Override
    public void onDisplayChanged(int displayId) {
        if (displayId == mDisplay.getDisplayId()) {
            if (mDisplay.getState() == Display.STATE_DOZE
                    || mDisplay.getState() == Display.STATE_DOZE_SUSPEND
                    || mDisplay.getState() == Display.STATE_ON_SUSPEND) {
                startBurnInProtection();
            } else {
                cancelBurnInProtection();
            }
        }
    }

    @Override
    public void onAnimationStart(Animator animator) {
    }

    @Override
    public void onAnimationEnd(Animator animator) {
        if (animator == mCenteringAnimator && !mBurnInProtectionActive) {
            mAppliedBurnInXOffset = 0;
            mAppliedBurnInYOffset = 0;
            // No matter how the animation finishes, we want to zero the offsets.
            mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(), 0, 0);
        }
    }

    @Override
    public void onAnimationCancel(Animator animator) {
    }

    @Override
    public void onAnimationRepeat(Animator animator) {
    }

    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        if (!mBurnInProtectionActive) {
            final float value = (Float) valueAnimator.getAnimatedValue();
            mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(),
                    (int) (mAppliedBurnInXOffset * value), (int) (mAppliedBurnInYOffset * value));
        }
    }
}
