/*
 * 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;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.TextView;

import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper;
import com.android.systemui.statusbar.phone.NotificationPanelView;

import java.util.ArrayList;

/**
 * Wraps a notification view inflated from a template.
 */
public class NotificationTemplateViewWrapper extends NotificationViewWrapper {

    private final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
    private final PorterDuffColorFilter mIconColorFilter = new PorterDuffColorFilter(
            0, PorterDuff.Mode.SRC_ATOP);
    private final int mIconDarkAlpha;
    private final int mIconDarkColor;
    private final Interpolator mLinearOutSlowInInterpolator;

    private int mColor;
    private ViewInvertHelper mInvertHelper;
    private ImageView mIcon;
    protected ImageView mPicture;

    /**
     * Whether the icon needs to be forced grayscale when in dark mode.
     */
    private boolean mIconForceGraysaleWhenDark;
    private TextView mSubText;
    private TextView mInfoText;
    private View mProfileBadge;
    private View mThirdLine;
    private ImageView mExpandButton;
    private View mNotificationHeader;
    private View.OnClickListener mExpandClickListener;
    private HeaderTouchListener mHeaderTouchListener;

    protected NotificationTemplateViewWrapper(Context ctx, View view) {
        super(view);
        mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
        mIconDarkColor =
                ctx.getColor(R.color.doze_small_icon_background_color);
        mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(ctx,
                android.R.interpolator.linear_out_slow_in);
        resolveViews();
    }

    private void resolveViews() {
        View mainColumn = mView.findViewById(com.android.internal.R.id.notification_main_column);
        mInvertHelper = mainColumn != null
                ? new ViewInvertHelper(mainColumn, NotificationPanelView.DOZE_ANIMATION_DURATION)
                : null;
        mIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon);
        mPicture = (ImageView) mView.findViewById(com.android.internal.R.id.right_icon);
        mSubText = (TextView) mView.findViewById(com.android.internal.R.id.text);
        mInfoText = (TextView) mView.findViewById(com.android.internal.R.id.info);
        mProfileBadge = mView.findViewById(com.android.internal.R.id.profile_badge_line3);
        mThirdLine = mView.findViewById(com.android.internal.R.id.line3);
        mExpandButton = (ImageView) mView.findViewById(com.android.internal.R.id.expand_button);
        mColor = resolveColor(mExpandButton);
        mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
        // Post to make sure the parent lays out its children before we get their bounds
        mHeaderTouchListener = new HeaderTouchListener();
        mExpandButton.post(new Runnable() {
            @Override
            public void run() {
                // let's set up our touch regions
                mHeaderTouchListener.bindTouchRects(mNotificationHeader, mIcon, mExpandButton);
            }
        });

        // If the icon already has a color filter, we assume that we already forced the icon to be
        // white when we created the notification.
        final Drawable iconDrawable = mIcon != null ? mIcon.getDrawable() : null;
        mIconForceGraysaleWhenDark = iconDrawable != null && iconDrawable.getColorFilter() != null;
    }

    private int resolveColor(ImageView icon) {
        if (icon != null && icon.getDrawable() != null) {
            ColorFilter filter = icon.getDrawable().getColorFilter();
            if (filter instanceof PorterDuffColorFilter) {
                return ((PorterDuffColorFilter) filter).getColor();
            }
        }
        return 0;
    }

    @Override
    public void notifyContentUpdated() {
        super.notifyContentUpdated();

        // Reinspect the notification.
        resolveViews();
    }

    @Override
    public void setDark(boolean dark, boolean fade, long delay) {
        if (mInvertHelper != null) {
            if (fade) {
                mInvertHelper.fade(dark, delay);
            } else {
                mInvertHelper.update(dark);
            }
        }
        if (mIcon != null) {
            if (fade) {
                fadeIconColorFilter(mIcon, dark, delay);
                fadeIconAlpha(mIcon, dark, delay);
                if (!mIconForceGraysaleWhenDark) {
                    fadeGrayscale(mIcon, dark, delay);
                }
            } else {
                updateIconColorFilter(mIcon, dark);
                updateIconAlpha(mIcon, dark);
                if (!mIconForceGraysaleWhenDark) {
                    updateGrayscale(mIcon, dark);
                }
            }
        }
        setPictureGrayscale(dark, fade, delay);
    }

    protected void setPictureGrayscale(boolean grayscale, boolean fade, long delay) {
        if (mPicture != null) {
            if (fade) {
                fadeGrayscale(mPicture, grayscale, delay);
            } else {
                updateGrayscale(mPicture, grayscale);
            }
        }
    }

    private void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
            boolean dark, long delay, Animator.AnimatorListener listener) {
        float startIntensity = dark ? 0f : 1f;
        float endIntensity = dark ? 1f : 0f;
        ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
        animator.addUpdateListener(updateListener);
        animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
        animator.setInterpolator(mLinearOutSlowInInterpolator);
        animator.setStartDelay(delay);
        if (listener != null) {
            animator.addListener(listener);
        }
        animator.start();
    }

    private void fadeIconColorFilter(final ImageView target, boolean dark, long delay) {
        startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                updateIconColorFilter(target, (Float) animation.getAnimatedValue());
            }
        }, dark, delay, null /* listener */);
    }

    private void fadeIconAlpha(final ImageView target, boolean dark, long delay) {
        startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float t = (float) animation.getAnimatedValue();
                target.setImageAlpha((int) (255 * (1f - t) + mIconDarkAlpha * t));
            }
        }, dark, delay, null /* listener */);
    }

    protected void fadeGrayscale(final ImageView target, final boolean dark, long delay) {
        startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                updateGrayscaleMatrix((float) animation.getAnimatedValue());
                target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
            }
        }, dark, delay, new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                if (!dark) {
                    target.setColorFilter(null);
                }
            }
        });
    }

    private void updateIconColorFilter(ImageView target, boolean dark) {
        updateIconColorFilter(target, dark ? 1f : 0f);
    }

    private void updateIconColorFilter(ImageView target, float intensity) {
        int color = interpolateColor(mColor, mIconDarkColor, intensity);
        mIconColorFilter.setColor(color);
        Drawable iconDrawable = target.getDrawable();

        // The background might be null for legacy notifications. Also, the notification might have
        // been modified during the animation, so background might be null here.
        if (iconDrawable != null) {
            iconDrawable.mutate().setColorFilter(mIconColorFilter);
        }
    }

    private void updateIconAlpha(ImageView target, boolean dark) {
        target.setImageAlpha(dark ? mIconDarkAlpha : 255);
    }

    protected void updateGrayscale(ImageView target, boolean dark) {
        if (dark) {
            updateGrayscaleMatrix(1f);
            target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
        } else {
            target.setColorFilter(null);
        }
    }

    @Override
    public void setSubTextVisible(boolean visible) {
        if (mSubText == null) {
            return;
        }
        boolean subTextAvailable = !TextUtils.isEmpty(mSubText.getText());
        if (visible && subTextAvailable) {
            mSubText.setVisibility(View.VISIBLE);
        } else {
            mSubText.setVisibility(View.GONE);
        }
        // TODO: figure out what to do with the number (same place as contentInfo)
        // work profile badge. For now we hide it since it looks nicer.
        boolean infoAvailable = !TextUtils.isEmpty(mInfoText.getText());
        if (visible && infoAvailable) {
            mInfoText.setVisibility(View.VISIBLE);
        } else {
            mInfoText.setVisibility(View.GONE);
        }
        boolean showThirdLine = (visible && (infoAvailable || subTextAvailable))
                || mProfileBadge.getVisibility() == View.VISIBLE;
        if (mThirdLine != null) {
            if (showThirdLine) {
                mThirdLine.setVisibility(View.VISIBLE);
            } else {
                mThirdLine.setVisibility(View.GONE);
            }
        }
    }

    @Override
    public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {
        mExpandButton.setVisibility(expandable ? View.VISIBLE : View.GONE);
        mNotificationHeader.setOnTouchListener(expandable ? mHeaderTouchListener : null);
        mExpandClickListener = onClickListener;
    }

    private void updateGrayscaleMatrix(float intensity) {
        mGrayscaleColorMatrix.setSaturation(1 - intensity);
    }

    private static int interpolateColor(int source, int target, float t) {
        int aSource = Color.alpha(source);
        int rSource = Color.red(source);
        int gSource = Color.green(source);
        int bSource = Color.blue(source);
        int aTarget = Color.alpha(target);
        int rTarget = Color.red(target);
        int gTarget = Color.green(target);
        int bTarget = Color.blue(target);
        return Color.argb(
                (int) (aSource * (1f - t) + aTarget * t),
                (int) (rSource * (1f - t) + rTarget * t),
                (int) (gSource * (1f - t) + gTarget * t),
                (int) (bSource * (1f - t) + bTarget * t));
    }

    public class HeaderTouchListener implements View.OnTouchListener {

        private final ArrayList<Rect> mTouchRects = new ArrayList<>();
        private int mTouchSlop;
        private boolean mTrackGesture;
        private float mDownX;
        private float mDownY;

        public HeaderTouchListener() {
        }

        public void bindTouchRects(View parent, View icon, View expandButton) {
            mTouchRects.clear();
            addRectAroundViewView(icon);
            addRectAroundViewView(expandButton);
            addInBetweenRect(parent);
            mTouchSlop = ViewConfiguration.get(parent.getContext()).getScaledTouchSlop();
        }

        private void addInBetweenRect(View parent) {
            final Rect r = new Rect();
            r.top = 0;
            r.bottom = (int) (32 * parent.getResources().getDisplayMetrics().density);
            Rect leftRect = mTouchRects.get(0);
            r.left = leftRect.right;
            Rect rightRect = mTouchRects.get(1);
            r.right = rightRect.left;
            mTouchRects.add(r);
        }

        private void addRectAroundViewView(View view) {
            final Rect r = getRectAroundView(view);
            mTouchRects.add(r);
        }

        private Rect getRectAroundView(View view) {
            float size = 48 * view.getResources().getDisplayMetrics().density;
            final Rect r = new Rect();
            r.top = (int) ((view.getTop() + view.getBottom()) / 2.0f - size / 2.0f);
            r.bottom = (int) (r.top + size);
            r.left = (int) ((view.getLeft() + view.getRight()) / 2.0f - size / 2.0f);
            r.right = (int) (r.left + size);
            return r;
        }

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            float x = event.getX();
            float y = event.getY();
            switch (event.getActionMasked() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    mTrackGesture = false;
                    if (isInside(x, y)) {
                        mTrackGesture = true;
                        return true;
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mTrackGesture) {
                        if (Math.abs(mDownX - x) > mTouchSlop
                                || Math.abs(mDownY - y) > mTouchSlop) {
                            mTrackGesture = false;
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (mTrackGesture) {
                        mExpandClickListener.onClick(mNotificationHeader);
                    }
                    break;
            }
            return mTrackGesture;
        }

        private boolean isInside(float x, float y) {
            for (int i = 0; i < mTouchRects.size(); i++) {
                Rect r = mTouchRects.get(i);
                if (r.contains((int) x, (int) y)) {
                    mDownX = x;
                    mDownY = y;
                    return true;
                }
            }
            return false;
        }
    }
}
