/*
 * Copyright (C) 2016 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.internal.widget;

import android.annotation.Nullable;
import android.annotation.Px;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.os.Build;
import android.os.Trace;
import android.util.AttributeSet;
import android.view.RemotableViewMethod;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.RemoteViews;

import com.android.internal.R;

/**
 * A custom-built layout for the Notification.MessagingStyle.
 *
 * Evicts children until they all fit.
 */
@RemoteViews.RemoteView
public class MessagingLinearLayout extends ViewGroup {

    /**
     * Spacing to be applied between views.
     */
    private int mSpacing;

    private int mMaxDisplayedLines = Integer.MAX_VALUE;

    private static final boolean TRACE_ONMEASURE = Build.isDebuggable();

    public MessagingLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        final TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.MessagingLinearLayout, 0,
                0);

        final int N = a.getIndexCount();
        for (int i = 0; i < N; i++) {
            int attr = a.getIndex(i);
            switch (attr) {
                case R.styleable.MessagingLinearLayout_spacing:
                    mSpacing = a.getDimensionPixelSize(i, 0);
                    break;
            }
        }

        a.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (TRACE_ONMEASURE) {
            Trace.beginSection("MessagingLinearLayout#onMeasure");
            trackMeasureSpecs(widthMeasureSpec, heightMeasureSpec);
        }
        // This is essentially a bottom-up linear layout that only adds children that fit entirely
        // up to a maximum height.
        int targetHeight = MeasureSpec.getSize(heightMeasureSpec);
        switch (MeasureSpec.getMode(heightMeasureSpec)) {
            case MeasureSpec.UNSPECIFIED:
                targetHeight = Integer.MAX_VALUE;
                break;
        }

        // Now that we know which views to take, fix up the indents and see what width we get.
        int measuredWidth = mPaddingLeft + mPaddingRight;
        final int count = getChildCount();
        int totalHeight;
        for (int i = 0; i < count; ++i) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            lp.hide = true;
            if (child instanceof MessagingChild) {
                MessagingChild messagingChild = (MessagingChild) child;
                // Whenever we encounter the message first, it's always first in the layout
                messagingChild.setIsFirstInLayout(true);
            }
        }

        totalHeight = mPaddingTop + mPaddingBottom;
        boolean first = true;
        int linesRemaining = mMaxDisplayedLines;
        // Starting from the bottom: we measure every view as if it were the only one. If it still
        // fits, we take it, otherwise we stop there.
        MessagingChild previousChild = null;
        View previousView = null;
        int previousChildHeight = 0;
        int previousTotalHeight = 0;
        int previousLinesConsumed = 0;
        for (int i = count - 1; i >= 0 && totalHeight < targetHeight; i--) {
            if (getChildAt(i).getVisibility() == GONE) {
                continue;
            }
            final View child = getChildAt(i);
            LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
            MessagingChild messagingChild = null;
            int spacing = mSpacing;
            int previousChildIncrease = 0;
            if (child instanceof MessagingChild) {
                // We need to remeasure the previous child again if it's not the first anymore
                if (previousChild != null && previousChild.hasDifferentHeightWhenFirst()) {
                    previousChild.setIsFirstInLayout(false);
                    measureChildWithMargins(previousView, widthMeasureSpec, 0, heightMeasureSpec,
                            previousTotalHeight - previousChildHeight);
                    previousChildIncrease = previousView.getMeasuredHeight() - previousChildHeight;
                    linesRemaining -= previousChild.getConsumedLines() - previousLinesConsumed;
                }
                messagingChild = (MessagingChild) child;
                messagingChild.setMaxDisplayedLines(linesRemaining);
                spacing += messagingChild.getExtraSpacing();
            }
            spacing = first ? 0 : spacing;
            measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, totalHeight
                    - mPaddingTop - mPaddingBottom + spacing);

            final int childHeight = child.getMeasuredHeight();
            int newHeight = Math.max(totalHeight, totalHeight + childHeight + lp.topMargin +
                    lp.bottomMargin + spacing + previousChildIncrease);
            int measureType = MessagingChild.MEASURED_NORMAL;
            if (messagingChild != null) {
                measureType = messagingChild.getMeasuredType();
            }

            // We never measure the first item as too small, we want to at least show something.
            boolean isTooSmall = measureType == MessagingChild.MEASURED_TOO_SMALL && !first;
            boolean isShortened = measureType == MessagingChild.MEASURED_SHORTENED
                    || measureType == MessagingChild.MEASURED_TOO_SMALL && first;
            boolean showView = newHeight <= targetHeight && !isTooSmall;
            if (showView) {
                if (messagingChild != null) {
                    previousLinesConsumed = messagingChild.getConsumedLines();
                    linesRemaining -= previousLinesConsumed;
                    previousChild = messagingChild;
                    previousView = child;
                    previousChildHeight = childHeight;
                    previousTotalHeight = totalHeight;
                }
                totalHeight = newHeight;
                measuredWidth = Math.max(measuredWidth,
                        child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin
                                + mPaddingLeft + mPaddingRight);
                lp.hide = false;
                if (isShortened || linesRemaining <= 0) {
                    break;
                }
            } else {
                // We now became too short, let's make sure to reset any previous views to be first
                // and remeasure it.
                if (previousChild != null && previousChild.hasDifferentHeightWhenFirst()) {
                    previousChild.setIsFirstInLayout(true);
                    // We need to remeasure the previous child again since it became first
                    measureChildWithMargins(previousView, widthMeasureSpec, 0, heightMeasureSpec,
                            previousTotalHeight - previousChildHeight);
                    // The totalHeight is already correct here since we only set it during the
                    // first pass
                }
                break;
            }
            first = false;
        }

        setMeasuredDimension(
                resolveSize(Math.max(getSuggestedMinimumWidth(), measuredWidth),
                        widthMeasureSpec),
                Math.max(getSuggestedMinimumHeight(), totalHeight));
        if (TRACE_ONMEASURE) {
            Trace.endSection();
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        final int paddingLeft = mPaddingLeft;

        int childTop;

        // Where right end of child should go
        final int width = right - left;
        final int childRight = width - mPaddingRight;

        final int layoutDirection = getLayoutDirection();
        final int count = getChildCount();

        childTop = mPaddingTop;

        boolean first = true;
        final boolean shown = isShown();
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            MessagingChild messagingChild = (MessagingChild) child;

            final int childWidth = child.getMeasuredWidth();
            final int childHeight = child.getMeasuredHeight();

            int childLeft;
            if (layoutDirection == LAYOUT_DIRECTION_RTL) {
                childLeft = childRight - childWidth - lp.rightMargin;
            } else {
                childLeft = paddingLeft + lp.leftMargin;
            }
            if (lp.hide) {
                if (shown && lp.visibleBefore) {
                    // We still want to lay out the child to have great animations
                    child.layout(childLeft, childTop, childLeft + childWidth,
                            childTop + lp.lastVisibleHeight);
                    messagingChild.hideAnimated();
                }
                lp.visibleBefore = false;
                continue;
            } else {
                lp.visibleBefore = true;
                lp.lastVisibleHeight = childHeight;
            }

            if (!first) {
                childTop += mSpacing;
            }

            childTop += lp.topMargin;
            child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);

            childTop += childHeight + lp.bottomMargin;

            first = false;
        }
    }

    private void trackMeasureSpecs(int widthMeasureSpec, int heightMeasureSpec) {
        if (!TRACE_ONMEASURE) {
            return;
        }

        final int availableWidth = MeasureSpec.getSize(widthMeasureSpec);
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        final int availableHeight = MeasureSpec.getSize(heightMeasureSpec);
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        Trace.setCounter("MessagingLinearLayout#onMeasure_widthMeasureSpecSize",
                availableWidth);
        Trace.setCounter("MessagingLinearLayout#onMeasure_widthMeasureSpecMode",
                widthMode);
        Trace.setCounter("MessagingLinearLayout#onMeasure_heightMeasureSpecSize",
                availableHeight);
        Trace.setCounter("MessagingLinearLayout#onMeasure_heightMeasureSpecMode",
                heightMode);
    }

    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
        if (lp.hide) {
            MessagingChild messagingChild = (MessagingChild) child;
            if (!messagingChild.isHidingAnimated()) {
                return true;
            }
        }
        return super.drawChild(canvas, child, drawingTime);
    }

    /**
     * Set the spacing to be applied between views.
     */
    public void setSpacing(@Px int spacing) {
        if (mSpacing != spacing) {
            mSpacing = spacing;
            requestLayout();
        }
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(mContext, attrs);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

    }

    @Override
    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
        LayoutParams copy = new LayoutParams(lp.width, lp.height);
        if (lp instanceof MarginLayoutParams) {
            copy.copyMarginsFrom((MarginLayoutParams) lp);
        }
        return copy;
    }

    public static boolean isGone(View view) {
        if (view.getVisibility() == View.GONE) {
            return true;
        }
        final ViewGroup.LayoutParams lp = view.getLayoutParams();
        if (lp instanceof MessagingLinearLayout.LayoutParams
                && ((MessagingLinearLayout.LayoutParams) lp).hide) {
            return true;
        }
        return false;
    }

    /**
     * Sets how many lines should be displayed at most
     */
    @RemotableViewMethod
    public void setMaxDisplayedLines(int numberLines) {
        mMaxDisplayedLines = numberLines;
    }

    public IMessagingLayout getMessagingLayout() {
        View view = this;
        while (true) {
            ViewParent p = view.getParent();
            if (p instanceof View) {
                view = (View) p;
                if (view instanceof IMessagingLayout) {
                    return (IMessagingLayout) view;
                }
            } else {
                return null;
            }
        }
    }

    @Override
    public int getBaseline() {
        // When placed in a horizontal linear layout (as is the case in a single-line MessageGroup),
        // align with the last visible child (which is the one that will be displayed in the single-
        // line group.
        int childCount = getChildCount();
        for (int i = childCount - 1; i >= 0; i--) {
            final View child = getChildAt(i);
            if (isGone(child)) {
                continue;
            }
            final int childBaseline = child.getBaseline();
            if (childBaseline == -1) {
                return -1;
            }
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            return lp.topMargin + childBaseline;
        }
        return super.getBaseline();
    }

    public interface MessagingChild {
        int MEASURED_NORMAL = 0;
        int MEASURED_SHORTENED = 1;
        int MEASURED_TOO_SMALL = 2;

        int getMeasuredType();
        int getConsumedLines();
        void setMaxDisplayedLines(int lines);
        void hideAnimated();
        boolean isHidingAnimated();

        /**
         * Set that this view is first in layout. Relevant and only set if
         * {@link #hasDifferentHeightWhenFirst()}.
         * @param first is this first?
         */
        default void setIsFirstInLayout(boolean first) {}

        /**
         * @return if this layout has different height it is first in the layout
         */
        default boolean hasDifferentHeightWhenFirst() {
            return false;
        }
        default int getExtraSpacing() {
            return 0;
        }
        void recycle();
    }

    public static class LayoutParams extends MarginLayoutParams {

        public boolean hide = false;
        public boolean visibleBefore = false;
        public int lastVisibleHeight;

        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
        }

        public LayoutParams(int width, int height) {
            super(width, height);
        }
    }
}
