/*
 * Copyright (C) 2017 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.notification.row;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.metrics.LogMaker;
import android.os.Bundle;
import android.provider.Settings;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.util.KeyValueListParser;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class NotificationSnooze extends LinearLayout
        implements NotificationGuts.GutsContent, View.OnClickListener {

    private static final String TAG = "NotificationSnooze";
    /**
     * If this changes more number increases, more assistant action resId's should be defined for
     * accessibility purposes, see {@link #setSnoozeOptions(List)}
     */
    private static final int MAX_ASSISTANT_SUGGESTIONS = 1;
    private static final String KEY_DEFAULT_SNOOZE = "default";
    private static final String KEY_OPTIONS = "options_array";
    private static final LogMaker OPTIONS_OPEN_LOG =
            new LogMaker(MetricsEvent.NOTIFICATION_SNOOZE_OPTIONS)
                    .setType(MetricsEvent.TYPE_OPEN);
    private static final LogMaker OPTIONS_CLOSE_LOG =
            new LogMaker(MetricsEvent.NOTIFICATION_SNOOZE_OPTIONS)
                    .setType(MetricsEvent.TYPE_CLOSE);
    private static final LogMaker UNDO_LOG =
            new LogMaker(MetricsEvent.NOTIFICATION_UNDO_SNOOZE)
                    .setType(MetricsEvent.TYPE_ACTION);
    private NotificationGuts mGutsContainer;
    private NotificationSwipeActionHelper mSnoozeListener;
    private StatusBarNotification mSbn;

    private TextView mSelectedOptionText;
    private TextView mUndoButton;
    private ImageView mExpandButton;
    private View mDivider;
    private ViewGroup mSnoozeOptionContainer;
    private List<SnoozeOption> mSnoozeOptions;
    private int mCollapsedHeight;
    private SnoozeOption mDefaultOption;
    private SnoozeOption mSelectedOption;
    private boolean mSnoozing;
    private boolean mExpanded;
    private AnimatorSet mExpandAnimation;
    private KeyValueListParser mParser;

    private final static int[] sAccessibilityActions = {
            R.id.action_snooze_shorter,
            R.id.action_snooze_short,
            R.id.action_snooze_long,
            R.id.action_snooze_longer,
    };

    private MetricsLogger mMetricsLogger = new MetricsLogger();

    public NotificationSnooze(Context context, AttributeSet attrs) {
        super(context, attrs);
        mParser = new KeyValueListParser(',');
    }

    @VisibleForTesting
    SnoozeOption getDefaultOption()
    {
        return mDefaultOption;
    }

    @VisibleForTesting
    void setKeyValueListParser(KeyValueListParser parser) {
        mParser = parser;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.snooze_snackbar_min_height);
        findViewById(R.id.notification_snooze).setOnClickListener(this);
        mSelectedOptionText = (TextView) findViewById(R.id.snooze_option_default);
        mUndoButton = (TextView) findViewById(R.id.undo);
        mUndoButton.setOnClickListener(this);
        mExpandButton = (ImageView) findViewById(R.id.expand_button);
        mDivider = findViewById(R.id.divider);
        mDivider.setAlpha(0f);
        mSnoozeOptionContainer = (ViewGroup) findViewById(R.id.snooze_options);
        mSnoozeOptionContainer.setVisibility(View.INVISIBLE);
        mSnoozeOptionContainer.setAlpha(0f);

        // Create the different options based on list
        mSnoozeOptions = getDefaultSnoozeOptions();
        createOptionViews();

        setSelected(mDefaultOption, false);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        logOptionSelection(MetricsEvent.NOTIFICATION_SNOOZE_CLICKED, mDefaultOption);
    }

    @Override
    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(event);
        if (mGutsContainer != null && mGutsContainer.isExposed()) {
            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
                event.getText().add(mSelectedOptionText.getText());
            }
        }
    }

    @Override
    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
        super.onInitializeAccessibilityNodeInfo(info);
        info.addAction(new AccessibilityAction(R.id.action_snooze_undo,
                getResources().getString(R.string.snooze_undo)));
        int count = mSnoozeOptions.size();
        for (int i = 0; i < count; i++) {
            AccessibilityAction action = mSnoozeOptions.get(i).getAccessibilityAction();
            if (action != null) {
                info.addAction(action);
            }
        }
    }

    @Override
    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
        if (super.performAccessibilityActionInternal(action, arguments)) {
            return true;
        }
        if (action == R.id.action_snooze_undo) {
            undoSnooze(mUndoButton);
            return true;
        }
        for (int i = 0; i < mSnoozeOptions.size(); i++) {
            SnoozeOption so = mSnoozeOptions.get(i);
            if (so.getAccessibilityAction() != null
                    && so.getAccessibilityAction().getId() == action) {
                setSelected(so, true);
                return true;
            }
        }
        return false;
    }

    public void setSnoozeOptions(final List<SnoozeCriterion> snoozeList) {
        if (snoozeList == null) {
            return;
        }
        mSnoozeOptions.clear();
        mSnoozeOptions = getDefaultSnoozeOptions();
        final int count = Math.min(MAX_ASSISTANT_SUGGESTIONS, snoozeList.size());
        for (int i = 0; i < count; i++) {
            SnoozeCriterion sc = snoozeList.get(i);
            AccessibilityAction action = new AccessibilityAction(
                    R.id.action_snooze_assistant_suggestion_1, sc.getExplanation());
            mSnoozeOptions.add(new NotificationSnoozeOption(sc, 0, sc.getExplanation(),
                    sc.getConfirmation(), action));
        }
        createOptionViews();
    }

    public boolean isExpanded() {
        return mExpanded;
    }

    public void setSnoozeListener(NotificationSwipeActionHelper listener) {
        mSnoozeListener = listener;
    }

    public void setStatusBarNotification(StatusBarNotification sbn) {
        mSbn = sbn;
    }

    @VisibleForTesting
    ArrayList<SnoozeOption> getDefaultSnoozeOptions() {
        final Resources resources = getContext().getResources();
        ArrayList<SnoozeOption> options = new ArrayList<>();
        try {
            final String config = Settings.Global.getString(getContext().getContentResolver(),
                    Settings.Global.NOTIFICATION_SNOOZE_OPTIONS);
            mParser.setString(config);
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Bad snooze constants");
        }

        final int defaultSnooze = mParser.getInt(KEY_DEFAULT_SNOOZE,
                resources.getInteger(R.integer.config_notification_snooze_time_default));
        final int[] snoozeTimes = mParser.getIntArray(KEY_OPTIONS,
                resources.getIntArray(R.array.config_notification_snooze_times));

        for (int i = 0; i < snoozeTimes.length && i < sAccessibilityActions.length; i++) {
            int snoozeTime = snoozeTimes[i];
            SnoozeOption option = createOption(snoozeTime, sAccessibilityActions[i]);
            if (i == 0 || snoozeTime == defaultSnooze) {
                mDefaultOption = option;
            }
            options.add(option);
        }
        return options;
    }

    private SnoozeOption createOption(int minutes, int accessibilityActionId) {
        Resources res = getResources();
        boolean showInHours = minutes >= 60;
        int pluralResId = showInHours
                ? R.plurals.snoozeHourOptions
                : R.plurals.snoozeMinuteOptions;
        int count = showInHours ? (minutes / 60) : minutes;
        String description = res.getQuantityString(pluralResId, count, count);
        String resultText = String.format(res.getString(R.string.snoozed_for_time), description);
        AccessibilityAction action = new AccessibilityAction(accessibilityActionId, description);
        final int index = resultText.indexOf(description);
        if (index == -1) {
            return new NotificationSnoozeOption(null, minutes, description, resultText, action);
        }
        SpannableString string = new SpannableString(resultText);
        string.setSpan(new StyleSpan(Typeface.BOLD),
                index, index + description.length(), 0 /* flags */);
        return new NotificationSnoozeOption(null, minutes, description, string,
                action);
    }

    private void createOptionViews() {
        mSnoozeOptionContainer.removeAllViews();
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        for (int i = 0; i < mSnoozeOptions.size(); i++) {
            SnoozeOption option = mSnoozeOptions.get(i);
            TextView tv = (TextView) inflater.inflate(R.layout.notification_snooze_option,
                    mSnoozeOptionContainer, false);
            mSnoozeOptionContainer.addView(tv);
            tv.setText(option.getDescription());
            tv.setTag(option);
            tv.setOnClickListener(this);
        }
    }

    private void hideSelectedOption() {
        final int childCount = mSnoozeOptionContainer.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = mSnoozeOptionContainer.getChildAt(i);
            child.setVisibility(child.getTag() == mSelectedOption ? View.GONE : View.VISIBLE);
        }
    }

    private void showSnoozeOptions(boolean show) {
        int drawableId = show ? com.android.internal.R.drawable.ic_collapse_notification
                : com.android.internal.R.drawable.ic_expand_notification;
        mExpandButton.setImageResource(drawableId);
        if (mExpanded != show) {
            mExpanded = show;
            animateSnoozeOptions(show);
            if (mGutsContainer != null) {
                mGutsContainer.onHeightChanged();
            }
        }
    }

    private void animateSnoozeOptions(boolean show) {
        if (mExpandAnimation != null) {
            mExpandAnimation.cancel();
        }
        ObjectAnimator dividerAnim = ObjectAnimator.ofFloat(mDivider, View.ALPHA,
                mDivider.getAlpha(), show ? 1f : 0f);
        ObjectAnimator optionAnim = ObjectAnimator.ofFloat(mSnoozeOptionContainer, View.ALPHA,
                mSnoozeOptionContainer.getAlpha(), show ? 1f : 0f);
        mSnoozeOptionContainer.setVisibility(View.VISIBLE);
        mExpandAnimation = new AnimatorSet();
        mExpandAnimation.playTogether(dividerAnim, optionAnim);
        mExpandAnimation.setDuration(150);
        mExpandAnimation.setInterpolator(show ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
        mExpandAnimation.addListener(new AnimatorListenerAdapter() {
            boolean cancelled = false;

            @Override
            public void onAnimationCancel(Animator animation) {
                cancelled = true;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (!show && !cancelled) {
                    mSnoozeOptionContainer.setVisibility(View.INVISIBLE);
                    mSnoozeOptionContainer.setAlpha(0f);
                }
            }
        });
        mExpandAnimation.start();
    }

    private void setSelected(SnoozeOption option, boolean userAction) {
        mSelectedOption = option;
        mSelectedOptionText.setText(option.getConfirmation());
        showSnoozeOptions(false);
        hideSelectedOption();
        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
        if (userAction) {
            logOptionSelection(MetricsEvent.NOTIFICATION_SELECT_SNOOZE, option);
        }
    }

    private void logOptionSelection(int category, SnoozeOption option) {
        int index = mSnoozeOptions.indexOf(option);
        long duration = TimeUnit.MINUTES.toMillis(option.getMinutesToSnoozeFor());
        mMetricsLogger.write(new LogMaker(category)
                .setType(MetricsEvent.TYPE_ACTION)
                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_SNOOZE_INDEX, index)
                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_SNOOZE_DURATION_MS, duration));
    }

    @Override
    public void onClick(View v) {
        if (mGutsContainer != null) {
            mGutsContainer.resetFalsingCheck();
        }
        final int id = v.getId();
        final SnoozeOption tag = (SnoozeOption) v.getTag();
        if (tag != null) {
            setSelected(tag, true);
        } else if (id == R.id.notification_snooze) {
            // Toggle snooze options
            showSnoozeOptions(!mExpanded);
            mMetricsLogger.write(!mExpanded ? OPTIONS_OPEN_LOG : OPTIONS_CLOSE_LOG);
        } else {
            // Undo snooze was selected
            undoSnooze(v);
            mMetricsLogger.write(UNDO_LOG);
        }
    }

    private void undoSnooze(View v) {
        mSelectedOption = null;
        int[] parentLoc = new int[2];
        int[] targetLoc = new int[2];
        mGutsContainer.getLocationOnScreen(parentLoc);
        v.getLocationOnScreen(targetLoc);
        final int centerX = v.getWidth() / 2;
        final int centerY = v.getHeight() / 2;
        final int x = targetLoc[0] - parentLoc[0] + centerX;
        final int y = targetLoc[1] - parentLoc[1] + centerY;
        showSnoozeOptions(false);
        mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
    }

    @Override
    public int getActualHeight() {
        return mExpanded ? getHeight() : mCollapsedHeight;
    }

    @Override
    public boolean willBeRemoved() {
        return mSnoozing;
    }

    @Override
    public View getContentView() {
        // Reset the view before use
        setSelected(mDefaultOption, false);
        return this;
    }

    @Override
    public void setGutsParent(NotificationGuts guts) {
        mGutsContainer = guts;
    }

    @Override
    public boolean handleCloseControls(boolean save, boolean force) {
        if (mExpanded && !force) {
            // Collapse expanded state on outside touch
            showSnoozeOptions(false);
            return true;
        } else if (mSnoozeListener != null && mSelectedOption != null) {
            // Snooze option selected so commit it
            mSnoozing = true;
            mSnoozeListener.snooze(mSbn, mSelectedOption);
            return true;
        } else {
            // The view should actually be closed
            setSelected(mSnoozeOptions.get(0), false);
            return false; // Return false here so that guts handles closing the view
        }
    }

    @Override
    public boolean isLeavebehind() {
        return true;
    }

    @Override
    public boolean shouldBeSaved() {
        return true;
    }

    public class NotificationSnoozeOption implements SnoozeOption {
        private SnoozeCriterion mCriterion;
        private int mMinutesToSnoozeFor;
        private CharSequence mDescription;
        private CharSequence mConfirmation;
        private AccessibilityAction mAction;

        public NotificationSnoozeOption(SnoozeCriterion sc, int minToSnoozeFor,
                CharSequence description,
                CharSequence confirmation, AccessibilityAction action) {
            mCriterion = sc;
            mMinutesToSnoozeFor = minToSnoozeFor;
            mDescription = description;
            mConfirmation = confirmation;
            mAction = action;
        }

        @Override
        public SnoozeCriterion getSnoozeCriterion() {
            return mCriterion;
        }

        @Override
        public CharSequence getDescription() {
            return mDescription;
        }

        @Override
        public CharSequence getConfirmation() {
            return mConfirmation;
        }

        @Override
        public int getMinutesToSnoozeFor() {
            return mMinutesToSnoozeFor;
        }

        @Override
        public AccessibilityAction getAccessibilityAction() {
            return mAction;
        }

    }
}
