/*
 * 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.storagemanager.automatic;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.SystemProperties;
import android.provider.Settings;
import androidx.annotation.VisibleForTesting;
import androidx.core.os.BuildCompat;

import com.android.storagemanager.R;

import java.util.concurrent.TimeUnit;

/**
 * NotificationController handles the responses to the Automatic Storage Management low storage
 * notification.
 */
public class NotificationController extends BroadcastReceiver {
    /**
     * Intent action for if the user taps "Turn on" for the automatic storage manager.
     */
    public static final String INTENT_ACTION_ACTIVATE_ASM =
            "com.android.storagemanager.automatic.ACTIVATE";

    /**
     * Intent action for if the user swipes the notification away.
     */
    public static final String INTENT_ACTION_DISMISS =
            "com.android.storagemanager.automatic.DISMISS";

    /**
     * Intent action for if the user explicitly hits "No thanks" on the notification.
     */
    public static final String INTENT_ACTION_NO_THANKS =
            "com.android.storagemanager.automatic.NO_THANKS";

    /**
     * Intent action to maybe show the ASM upsell notification.
     */
    public static final String INTENT_ACTION_SHOW_NOTIFICATION =
            "com.android.storagemanager.automatic.show_notification";

    /**
     * Intent action for forcefully showing the notification, even if the conditions are not valid.
     */
    private static final String INTENT_ACTION_DEBUG_NOTIFICATION =
            "com.android.storagemanager.automatic.DEBUG_SHOW_NOTIFICATION";

    /** Intent action for if the user taps on the notification. */
    @VisibleForTesting
    static final String INTENT_ACTION_TAP = "com.android.storagemanager.automatic.SHOW_SETTINGS";

    /**
     * Intent extra for the notification id.
     */
    public static final String INTENT_EXTRA_ID = "id";

    private static final String SHARED_PREFERENCES_NAME = "NotificationController";
    private static final String NOTIFICATION_NEXT_SHOW_TIME = "notification_next_show_time";
    private static final String NOTIFICATION_SHOWN_COUNT = "notification_shown_count";
    private static final String NOTIFICATION_DISMISS_COUNT = "notification_dismiss_count";
    private static final String STORAGE_MANAGER_PROPERTY = "ro.storage_manager.enabled";
    private static final String CHANNEL_ID = "storage";

    private static final long DISMISS_DELAY = TimeUnit.DAYS.toMillis(14);
    private static final long NO_THANKS_DELAY = TimeUnit.DAYS.toMillis(90);
    private static final long MAXIMUM_SHOWN_COUNT = 4;
    private static final long MAXIMUM_DISMISS_COUNT = 9;
    private static final int NOTIFICATION_ID = 0;

    // Keeps the time for test purposes.
    private Clock mClock;

    @Override
    public void onReceive(Context context, Intent intent) {
        switch (intent.getAction()) {
            case INTENT_ACTION_ACTIVATE_ASM:
                Settings.Secure.putInt(
                        context.getContentResolver(),
                        Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
                        1);
                // Provide a warning if storage manager is not defaulted on.
                if (!SystemProperties.getBoolean(STORAGE_MANAGER_PROPERTY, false)) {
                    Intent warningIntent = new Intent(context, WarningDialogActivity.class);
                    warningIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(warningIntent);
                }
                break;
            case INTENT_ACTION_NO_THANKS:
                delayNextNotification(context, NO_THANKS_DELAY);
                break;
            case INTENT_ACTION_DISMISS:
                delayNextNotification(context, DISMISS_DELAY);
                break;
            case INTENT_ACTION_SHOW_NOTIFICATION:
                maybeShowNotification(context);
                return;
            case INTENT_ACTION_DEBUG_NOTIFICATION:
                showNotification(context);
                return;
            case INTENT_ACTION_TAP:
                Intent storageIntent = new Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
                storageIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(storageIntent);
                break;
        }
        cancelNotification(context, intent);
    }

    /**
     * Sets a time provider for the controller.
     * @param clock The time provider.
     */
    protected void setClock(Clock clock) {
        mClock = clock;
    }

    /**
     * If the conditions for showing the activation notification are met, show the activation
     * notification.
     * @param context Context to use for getting resources and to display the notification.
     */
    private void maybeShowNotification(Context context) {
        if (shouldShowNotification(context)) {
            showNotification(context);
        }
    }

    private boolean shouldShowNotification(Context context) {
        boolean showNotificationConfigEnabled =
                context.getResources().getBoolean(R.bool.enable_low_storage_notification);
        if (!showNotificationConfigEnabled) {
            return false;
        }

        SharedPreferences sp = context.getSharedPreferences(
                SHARED_PREFERENCES_NAME,
                Context.MODE_PRIVATE);
        int timesShown = sp.getInt(NOTIFICATION_SHOWN_COUNT, 0);
        int timesDismissed = sp.getInt(NOTIFICATION_DISMISS_COUNT, 0);
        if (timesShown >= MAXIMUM_SHOWN_COUNT || timesDismissed >= MAXIMUM_DISMISS_COUNT) {
            return false;
        }

        long nextTimeToShow = sp.getLong(NOTIFICATION_NEXT_SHOW_TIME, 0);

        return getCurrentTime() >= nextTimeToShow;
    }

    private void showNotification(Context context) {
        Resources res = context.getResources();
        Intent noThanksIntent = getBaseIntent(context, INTENT_ACTION_NO_THANKS);
        noThanksIntent.putExtra(INTENT_EXTRA_ID, NOTIFICATION_ID);
        Notification.Action.Builder cancelAction = new Notification.Action.Builder(null,
                res.getString(R.string.automatic_storage_manager_cancel_button),
                PendingIntent.getBroadcast(context, 0, noThanksIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));


        Intent activateIntent = getBaseIntent(context, INTENT_ACTION_ACTIVATE_ASM);
        activateIntent.putExtra(INTENT_EXTRA_ID, NOTIFICATION_ID);
        Notification.Action.Builder activateAutomaticAction = new Notification.Action.Builder(null,
                res.getString(R.string.automatic_storage_manager_activate_button),
                PendingIntent.getBroadcast(context, 0, activateIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));

        Intent dismissIntent = getBaseIntent(context, INTENT_ACTION_DISMISS);
        dismissIntent.putExtra(INTENT_EXTRA_ID, NOTIFICATION_ID);
        PendingIntent deleteIntent = PendingIntent.getBroadcast(context, 0,
                dismissIntent,
                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);

        Intent contentIntent = getBaseIntent(context, INTENT_ACTION_TAP);
        contentIntent.putExtra(INTENT_EXTRA_ID, NOTIFICATION_ID);
        PendingIntent tapIntent = PendingIntent.getBroadcast(context, 0,  contentIntent,
                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);

        Notification.Builder builder;
        // We really should only have the path with the notification channel set. The other path is
        // only for legacy Robolectric reasons -- Robolectric does not have the Notification
        // builder with a channel id, so it crashes when it hits that code path.
        if (BuildCompat.isAtLeastO()) {
            makeNotificationChannel(context);
            builder = new Notification.Builder(context, CHANNEL_ID);
        } else {
            builder = new Notification.Builder(context);
        }

        builder.setSmallIcon(R.drawable.ic_settings_24dp)
                .setContentTitle(
                        res.getString(R.string.automatic_storage_manager_notification_title))
                .setContentText(
                        res.getString(R.string.automatic_storage_manager_notification_summary))
                .setStyle(
                        new Notification.BigTextStyle()
                                .bigText(
                                        res.getString(
                                                R.string
                                                        .automatic_storage_manager_notification_summary)))
                .addAction(cancelAction.build())
                .addAction(activateAutomaticAction.build())
                .setContentIntent(tapIntent)
                .setDeleteIntent(deleteIntent)
                .setLocalOnly(true);

        NotificationManager manager =
                ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE));
        manager.notify(NOTIFICATION_ID, builder.build());
    }

    private void makeNotificationChannel(Context context) {
        final NotificationManager nm = context.getSystemService(NotificationManager.class);
        final NotificationChannel channel =
                new NotificationChannel(
                        CHANNEL_ID,
                        context.getString(R.string.app_name),
                        NotificationManager.IMPORTANCE_LOW);
        nm.createNotificationChannel(channel);
    }

    private void cancelNotification(Context context, Intent intent) {
        if (intent.getAction() == INTENT_ACTION_DISMISS) {
            incrementNotificationDismissedCount(context);
        } else {
            incrementNotificationShownCount(context);
        }

        int id = intent.getIntExtra(INTENT_EXTRA_ID, -1);
        if (id == -1) {
            return;
        }
        NotificationManager manager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        manager.cancel(id);
    }

    private void incrementNotificationShownCount(Context context) {
        SharedPreferences sp = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        int shownCount = sp.getInt(NotificationController.NOTIFICATION_SHOWN_COUNT, 0) + 1;
        editor.putInt(NotificationController.NOTIFICATION_SHOWN_COUNT, shownCount);
        editor.apply();
    }

    private void incrementNotificationDismissedCount(Context context) {
        SharedPreferences sp = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        int dismissCount = sp.getInt(NOTIFICATION_DISMISS_COUNT, 0) + 1;
        editor.putInt(NOTIFICATION_DISMISS_COUNT, dismissCount);
        editor.apply();
    }

    private void delayNextNotification(Context context, long timeInMillis) {
        SharedPreferences sp = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putLong(NOTIFICATION_NEXT_SHOW_TIME,
                getCurrentTime() + timeInMillis);
        editor.apply();
    }

    private long getCurrentTime() {
        if (mClock == null) {
            mClock = new Clock();
        }

        return mClock.currentTimeMillis();
    }

    @VisibleForTesting
    Intent getBaseIntent(Context context, String action) {
        return new Intent(context, NotificationController.class).setAction(action);
    }

    /**
     * Clock provides the current time.
     */
    protected static class Clock {
        /**
         * Returns the current time in milliseconds.
         */
        public long currentTimeMillis() {
            return System.currentTimeMillis();
        }
    }
}
