/*
 * Copyright (C) 2014 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.systemui.statusbar.phone;

import static com.android.systemui.statusbar.notification.NotificationUtils.interpolate;

import android.content.res.Resources;
import android.graphics.Path;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.PathInterpolator;

import com.android.systemui.R;

/**
 * Utility class to calculate the clock position and top padding of notifications on Keyguard.
 */
public class KeyguardClockPositionAlgorithm {

    private static final float SLOW_DOWN_FACTOR = 0.4f;

    private static final float CLOCK_RUBBERBAND_FACTOR_MIN = 0.08f;
    private static final float CLOCK_RUBBERBAND_FACTOR_MAX = 0.8f;
    private static final float CLOCK_SCALE_FADE_START = 0.95f;
    private static final float CLOCK_SCALE_FADE_END = 0.75f;
    private static final float CLOCK_SCALE_FADE_END_NO_NOTIFS = 0.5f;

    private static final float CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MIN = 1.4f;
    private static final float CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MAX = 3.2f;

    private static final long MILLIS_PER_MINUTES = 1000 * 60;
    private static final float BURN_IN_PREVENTION_PERIOD_Y = 521;
    private static final float BURN_IN_PREVENTION_PERIOD_X = 83;

    private int mClockNotificationsMarginMin;
    private int mClockNotificationsMarginMax;
    private float mClockYFractionMin;
    private float mClockYFractionMax;
    private int mMaxKeyguardNotifications;
    private int mMaxPanelHeight;
    private float mExpandedHeight;
    private int mNotificationCount;
    private int mHeight;
    private int mKeyguardStatusHeight;
    private float mEmptyDragAmount;
    private float mDensity;
    private int mBurnInPreventionOffsetX;
    private int mBurnInPreventionOffsetY;

    /**
     * The number (fractional) of notifications the "more" card counts when calculating how many
     * notifications are currently visible for the y positioning of the clock.
     */
    private float mMoreCardNotificationAmount;

    private static final PathInterpolator sSlowDownInterpolator;

    static {
        Path path = new Path();
        path.moveTo(0, 0);
        path.cubicTo(0.3f, 0.875f, 0.6f, 1f, 1f, 1f);
        sSlowDownInterpolator = new PathInterpolator(path);
    }

    private AccelerateInterpolator mAccelerateInterpolator = new AccelerateInterpolator();
    private int mClockBottom;
    private float mDarkAmount;
    private int mDozingStackPadding;

    /**
     * Refreshes the dimension values.
     */
    public void loadDimens(Resources res) {
        mClockNotificationsMarginMin = res.getDimensionPixelSize(
                R.dimen.keyguard_clock_notifications_margin_min);
        mClockNotificationsMarginMax = res.getDimensionPixelSize(
                R.dimen.keyguard_clock_notifications_margin_max);
        mClockYFractionMin = res.getFraction(R.fraction.keyguard_clock_y_fraction_min, 1, 1);
        mClockYFractionMax = res.getFraction(R.fraction.keyguard_clock_y_fraction_max, 1, 1);
        mMoreCardNotificationAmount =
                (float) res.getDimensionPixelSize(R.dimen.notification_shelf_height) /
                        res.getDimensionPixelSize(R.dimen.notification_min_height);
        mDensity = res.getDisplayMetrics().density;
        mBurnInPreventionOffsetX = res.getDimensionPixelSize(
                R.dimen.burn_in_prevention_offset_x);
        mBurnInPreventionOffsetY = res.getDimensionPixelSize(
                R.dimen.burn_in_prevention_offset_y);
        mDozingStackPadding = res.getDimensionPixelSize(R.dimen.dozing_stack_padding);
    }

    public void setup(int maxKeyguardNotifications, int maxPanelHeight, float expandedHeight,
            int notificationCount, int height, int keyguardStatusHeight, float emptyDragAmount,
            int clockBottom, float dark) {
        mMaxKeyguardNotifications = maxKeyguardNotifications;
        mMaxPanelHeight = maxPanelHeight;
        mExpandedHeight = expandedHeight;
        mNotificationCount = notificationCount;
        mHeight = height;
        mKeyguardStatusHeight = keyguardStatusHeight;
        mEmptyDragAmount = emptyDragAmount;
        mClockBottom = clockBottom;
        mDarkAmount = dark;
    }

    public float getMinStackScrollerPadding(int height, int keyguardStatusHeight) {
        return mClockYFractionMin * height + keyguardStatusHeight / 2
                + mClockNotificationsMarginMin;
    }

    public void run(Result result) {
        int y = getClockY() - mKeyguardStatusHeight / 2;
        float clockAdjustment = getClockYExpansionAdjustment();
        float topPaddingAdjMultiplier = getTopPaddingAdjMultiplier();
        result.stackScrollerPaddingAdjustment = (int) (clockAdjustment*topPaddingAdjMultiplier);
        int clockNotificationsPadding = getClockNotificationsPadding()
                + result.stackScrollerPaddingAdjustment;
        int padding = y + clockNotificationsPadding;
        result.clockY = y;
        result.stackScrollerPadding = mKeyguardStatusHeight + padding;
        result.clockScale = getClockScale(result.stackScrollerPadding,
                result.clockY,
                y + getClockNotificationsPadding() + mKeyguardStatusHeight);
        result.clockAlpha = getClockAlpha(result.clockScale);

        result.stackScrollerPadding = (int) interpolate(
                result.stackScrollerPadding,
                mClockBottom + y + mDozingStackPadding,
                mDarkAmount);

        result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount);
    }

    private float getClockScale(int notificationPadding, int clockY, int startPadding) {
        float scaleMultiplier = getNotificationAmountT() == 0 ? 6.0f : 5.0f;
        float scaleEnd = clockY - mKeyguardStatusHeight * scaleMultiplier;
        float distanceToScaleEnd = notificationPadding - scaleEnd;
        float progress = distanceToScaleEnd / (startPadding - scaleEnd);
        progress = Math.max(0.0f, Math.min(progress, 1.0f));
        progress = mAccelerateInterpolator.getInterpolation(progress);
        progress *= Math.pow(1 + mEmptyDragAmount / mDensity / 300, 0.3f);
        return interpolate(progress, 1, mDarkAmount);
    }

    private int getClockNotificationsPadding() {
        float t = getNotificationAmountT();
        t = Math.min(t, 1.0f);
        return (int) (t * mClockNotificationsMarginMin + (1 - t) * mClockNotificationsMarginMax);
    }

    private float getClockYFraction() {
        float t = getNotificationAmountT();
        t = Math.min(t, 1.0f);
        return (1 - t) * mClockYFractionMax + t * mClockYFractionMin;
    }

    private int getClockY() {
        // Dark: Align the bottom edge of the clock at one third:
        // clockBottomEdge = result - mKeyguardStatusHeight / 2 + mClockBottom
        float clockYDark = (0.33f * mHeight + (float) mKeyguardStatusHeight / 2 - mClockBottom)
                + burnInPreventionOffsetY();
        float clockYRegular = getClockYFraction() * mHeight;
        return (int) interpolate(clockYRegular, clockYDark, mDarkAmount);
    }

    private float burnInPreventionOffsetY() {
        return zigzag(System.currentTimeMillis() / MILLIS_PER_MINUTES,
                mBurnInPreventionOffsetY * 2,
                BURN_IN_PREVENTION_PERIOD_Y)
                - mBurnInPreventionOffsetY;
    }

    private float burnInPreventionOffsetX() {
        return zigzag(System.currentTimeMillis() / MILLIS_PER_MINUTES,
                mBurnInPreventionOffsetX * 2,
                BURN_IN_PREVENTION_PERIOD_X)
                - mBurnInPreventionOffsetX;
    }

    /**
     * Implements a continuous, piecewise linear, periodic zig-zag function
     *
     * Can be thought of as a linear approximation of abs(sin(x)))
     *
     * @param period period of the function, ie. zigzag(x + period) == zigzag(x)
     * @param amplitude maximum value of the function
     * @return a value between 0 and amplitude
     */
    private float zigzag(float x, float amplitude, float period) {
        float xprime = (x % period) / (period / 2);
        float interpolationAmount = (xprime <= 1) ? xprime : (2 - xprime);
        return interpolate(0, amplitude, interpolationAmount);
    }

    private float getClockYExpansionAdjustment() {
        float rubberbandFactor = getClockYExpansionRubberbandFactor();
        float value = (rubberbandFactor * (mMaxPanelHeight - mExpandedHeight));
        float t = value / mMaxPanelHeight;
        float slowedDownValue = -sSlowDownInterpolator.getInterpolation(t) * SLOW_DOWN_FACTOR
                * mMaxPanelHeight;
        if (mNotificationCount == 0) {
            return (-2*value + slowedDownValue)/3;
        } else {
            return slowedDownValue;
        }
    }

    private float getClockYExpansionRubberbandFactor() {
        float t = getNotificationAmountT();
        t = Math.min(t, 1.0f);
        t = (float) Math.pow(t, 0.3f);
        return (1 - t) * CLOCK_RUBBERBAND_FACTOR_MAX + t * CLOCK_RUBBERBAND_FACTOR_MIN;
    }

    private float getTopPaddingAdjMultiplier() {
        float t = getNotificationAmountT();
        t = Math.min(t, 1.0f);
        return (1 - t) * CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MIN
                + t * CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MAX;
    }

    private float getClockAlpha(float scale) {
        float fadeEnd = getNotificationAmountT() == 0.0f
                ? CLOCK_SCALE_FADE_END_NO_NOTIFS
                : CLOCK_SCALE_FADE_END;
        float alpha = (scale - fadeEnd)
                / (CLOCK_SCALE_FADE_START - fadeEnd);
        return Math.max(0, Math.min(1, alpha));
    }

    /**
     * @return a value from 0 to 1 depending on how many notification there are
     */
    private float getNotificationAmountT() {
        return mNotificationCount
                / (mMaxKeyguardNotifications + mMoreCardNotificationAmount);
    }

    public static class Result {

        /**
         * The y translation of the clock.
         */
        public int clockY;

        /**
         * The scale of the Clock
         */
        public float clockScale;

        /**
         * The alpha value of the clock.
         */
        public float clockAlpha;

        /**
         * The top padding of the stack scroller, in pixels.
         */
        public int stackScrollerPadding;

        /**
         * The top padding adjustment of the stack scroller, in pixels. This value is used to adjust
         * the padding, but not the overall panel size.
         */
        public int stackScrollerPaddingAdjustment;

        /** The x translation of the clock. */
        public int clockX;
    }
}
