/*
 * 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.deskclock.data;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.support.annotation.VisibleForTesting;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;

import com.android.deskclock.AlarmUtils;
import com.android.deskclock.R;
import com.android.deskclock.Utils;
import com.android.deskclock.events.Events;
import com.android.deskclock.timer.ExpiredTimersActivity;
import com.android.deskclock.timer.TimerService;

import java.util.List;

import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;

/**
 * Builds KK, L, or M-style notifications to reflect the latest state of the unexpired timers.
 */
class TimerNotificationBuilderPreN implements TimerModel.NotificationBuilder {

    @Override
    public Notification build(Context context, NotificationModel nm, List<Timer> unexpired) {
        final Timer timer = unexpired.get(0);
        final long remainingTime = timer.getRemainingTime();

        // Generate some descriptive text, a title, and some actions based on timer states.
        final String contentText;
        final String contentTitle;
        @DrawableRes int firstActionIconId, secondActionIconId = 0;
        @StringRes int firstActionTitleId, secondActionTitleId = 0;
        Intent firstActionIntent, secondActionIntent = null;

        if (unexpired.size() == 1) {
            contentText = formatElapsedTimeUntilExpiry(context, remainingTime);

            if (timer.isRunning()) {
                // Single timer is running.
                if (TextUtils.isEmpty(timer.getLabel())) {
                    contentTitle = context.getString(R.string.timer_notification_label);
                } else {
                    contentTitle = timer.getLabel();
                }

                firstActionIconId = R.drawable.ic_pause_24dp;
                firstActionTitleId = R.string.timer_pause;
                firstActionIntent = new Intent(context, TimerService.class)
                        .setAction(TimerService.ACTION_PAUSE_TIMER)
                        .putExtra(TimerService.EXTRA_TIMER_ID, timer.getId());

                secondActionIconId = R.drawable.ic_add_24dp;
                secondActionTitleId = R.string.timer_plus_1_min;
                secondActionIntent = new Intent(context, TimerService.class)
                        .setAction(TimerService.ACTION_ADD_MINUTE_TIMER)
                        .putExtra(TimerService.EXTRA_TIMER_ID, timer.getId());
            } else {
                // Single timer is paused.
                contentTitle = context.getString(R.string.timer_paused);

                firstActionIconId = R.drawable.ic_start_24dp;
                firstActionTitleId = R.string.sw_resume_button;
                firstActionIntent = new Intent(context, TimerService.class)
                        .setAction(TimerService.ACTION_START_TIMER)
                        .putExtra(TimerService.EXTRA_TIMER_ID, timer.getId());

                secondActionIconId = R.drawable.ic_reset_24dp;
                secondActionTitleId = R.string.sw_reset_button;
                secondActionIntent = new Intent(context, TimerService.class)
                        .setAction(TimerService.ACTION_RESET_TIMER)
                        .putExtra(TimerService.EXTRA_TIMER_ID, timer.getId());
            }
        } else {
            if (timer.isRunning()) {
                // At least one timer is running.
                final String timeRemaining = formatElapsedTimeUntilExpiry(context, remainingTime);
                contentText = context.getString(R.string.next_timer_notif, timeRemaining);
                contentTitle = context.getString(R.string.timers_in_use, unexpired.size());
            } else {
                // All timers are paused.
                contentText = context.getString(R.string.all_timers_stopped_notif);
                contentTitle = context.getString(R.string.timers_stopped, unexpired.size());
            }

            firstActionIconId = R.drawable.ic_reset_24dp;
            firstActionTitleId = R.string.timer_reset_all;
            firstActionIntent = TimerService.createResetUnexpiredTimersIntent(context);
        }

        // Intent to load the app and show the timer when the notification is tapped.
        final Intent showApp = new Intent(context, TimerService.class)
                .setAction(TimerService.ACTION_SHOW_TIMER)
                .putExtra(TimerService.EXTRA_TIMER_ID, timer.getId())
                .putExtra(Events.EXTRA_EVENT_LABEL, R.string.label_notification);

        final PendingIntent pendingShowApp = PendingIntent.getService(context, 0, showApp,
                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);

        final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                .setOngoing(true)
                .setLocalOnly(true)
                .setShowWhen(false)
                .setAutoCancel(false)
                .setContentText(contentText)
                .setContentTitle(contentTitle)
                .setContentIntent(pendingShowApp)
                .setSmallIcon(R.drawable.stat_notify_timer)
                .setSortKey(nm.getTimerNotificationSortKey())
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setCategory(NotificationCompat.CATEGORY_ALARM)
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setColor(ContextCompat.getColor(context, R.color.default_background));

        final PendingIntent action1 = Utils.pendingServiceIntent(context, firstActionIntent);
        final String action1Title = context.getString(firstActionTitleId);
        builder.addAction(firstActionIconId, action1Title, action1);

        if (secondActionIntent != null) {
            final PendingIntent action2 = Utils.pendingServiceIntent(context, secondActionIntent);
            final String action2Title = context.getString(secondActionTitleId);
            builder.addAction(secondActionIconId, action2Title, action2);
        }

        final AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        final Intent updateNotification = TimerService.createUpdateNotificationIntent(context);
        if (timer.isRunning() && remainingTime > MINUTE_IN_MILLIS) {
            // Schedule a callback to update the time-sensitive information of the running timer.
            final PendingIntent pi =
                    PendingIntent.getService(context, REQUEST_CODE_UPCOMING, updateNotification,
                            PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);

            final long nextMinuteChange = remainingTime % MINUTE_IN_MILLIS;
            final long triggerTime = SystemClock.elapsedRealtime() + nextMinuteChange;
            TimerModel.schedulePendingIntent(am, triggerTime, pi);
        } else {
            // Cancel the update notification callback.
            final PendingIntent pi = PendingIntent.getService(context, 0, updateNotification,
                    PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_NO_CREATE);
            if (pi != null) {
                am.cancel(pi);
                pi.cancel();
            }
        }

        return builder.build();
    }

    @Override
    public Notification buildHeadsUp(Context context, List<Timer> expired) {
        // Generate some descriptive text, a title, and an action name based on the timer count.
        final int timerId;
        final String contentText;
        final String contentTitle;
        final String resetActionTitle;
        final int count = expired.size();

        if (count == 1) {
            final Timer timer = expired.get(0);
            timerId = timer.getId();
            resetActionTitle = context.getString(R.string.timer_stop);
            contentText = context.getString(R.string.timer_times_up);

            final String label = timer.getLabel();
            if (TextUtils.isEmpty(label)) {
                contentTitle = context.getString(R.string.timer_notification_label);
            } else {
                contentTitle = label;
            }
        } else {
            timerId = -1;
            contentText = context.getString(R.string.timer_multi_times_up, count);
            contentTitle = context.getString(R.string.timer_notification_label);
            resetActionTitle = context.getString(R.string.timer_stop_all);
        }

        // Content intent shows the expired timers full screen when clicked.
        final Intent content = new Intent(context, ExpiredTimersActivity.class);
        final PendingIntent pendingContent = Utils.pendingActivityIntent(context, content);

        // Full screen intent has flags so it is different than the content intent.
        final Intent fullScreen = new Intent(context, ExpiredTimersActivity.class)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
        final PendingIntent pendingFullScreen = Utils.pendingActivityIntent(context, fullScreen);

        // Left button: Reset timer / Reset all timers
        final Intent reset = TimerService.createResetExpiredTimersIntent(context);
        final PendingIntent pendingReset = Utils.pendingServiceIntent(context, reset);

        final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                .setOngoing(true)
                .setLocalOnly(true)
                .setShowWhen(false)
                .setAutoCancel(false)
                .setContentText(contentText)
                .setContentTitle(contentTitle)
                .setContentIntent(pendingContent)
                .setSmallIcon(R.drawable.stat_notify_timer)
                .setFullScreenIntent(pendingFullScreen, true)
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setDefaults(NotificationCompat.DEFAULT_LIGHTS)
                .addAction(R.drawable.ic_stop_24dp, resetActionTitle, pendingReset)
                .setColor(ContextCompat.getColor(context, R.color.default_background));

        // Add a second action if only a single timer is expired.
        if (count == 1) {
            // Right button: Add minute
            final Intent addMinute = TimerService.createAddMinuteTimerIntent(context, timerId);
            final PendingIntent pendingAddMinute = Utils.pendingServiceIntent(context, addMinute);
            final String addMinuteTitle = context.getString(R.string.timer_plus_1_min);
            builder.addAction(R.drawable.ic_add_24dp, addMinuteTitle, pendingAddMinute);
        }

        return builder.build();
    }

    @Override
    public Notification buildMissed(Context context, NotificationModel nm,
                                    List<Timer> missedTimers) {
        final Timer timer = missedTimers.get(0);
        final long expirationTime = timer.getWallClockExpirationTime();

        // Generate a title, and some actions based on timer states.
        final String contentTitle;
        final String contentText;
        final @DrawableRes int firstActionIconId;
        final @StringRes int firstActionTitleId;
        final Intent firstActionIntent;

        if (missedTimers.size() == 1) {
            // Single timer is missed.
            contentText = AlarmUtils.getFormattedTime(context, expirationTime);
            if (TextUtils.isEmpty(timer.getLabel())) {
                contentTitle = context.getString(R.string.missed_timer_notification_label);
            } else {
                contentTitle = context.getString(R.string.missed_named_timer_notification_label,
                        timer.getLabel());
            }

            firstActionIconId = R.drawable.ic_reset_24dp;
            firstActionTitleId = R.string.timer_reset;
            firstActionIntent = new Intent(context, TimerService.class)
                    .setAction(TimerService.ACTION_RESET_TIMER)
                    .putExtra(TimerService.EXTRA_TIMER_ID, timer.getId());
        } else {
            // Multiple missed timers.
            contentText = AlarmUtils.getFormattedTime(context, expirationTime);
            contentTitle = context.getString(R.string.timer_multi_missed, missedTimers.size());

            firstActionIconId = R.drawable.ic_reset_24dp;
            firstActionTitleId = R.string.timer_reset_all;
            firstActionIntent = TimerService.createResetMissedTimersIntent(context);
        }

        // Intent to load the app and show the timer when the notification is tapped.
        final Intent showApp = new Intent(context, TimerService.class)
                .setAction(TimerService.ACTION_SHOW_TIMER)
                .putExtra(TimerService.EXTRA_TIMER_ID, timer.getId())
                .putExtra(Events.EXTRA_EVENT_LABEL, R.string.label_notification);

        final PendingIntent pendingShowApp = PendingIntent.getService(context, 0, showApp,
                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);

        final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                .setLocalOnly(true)
                .setShowWhen(false)
                .setAutoCancel(false)
                .setContentText(contentText)
                .setContentTitle(contentTitle)
                .setContentIntent(pendingShowApp)
                .setSmallIcon(R.drawable.stat_notify_timer)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setCategory(NotificationCompat.CATEGORY_ALARM)
                .setSortKey(nm.getTimerNotificationMissedSortKey())
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setColor(ContextCompat.getColor(context, R.color.default_background));

        final PendingIntent action1 = Utils.pendingServiceIntent(context, firstActionIntent);
        final String action1Title = context.getString(firstActionTitleId);
        builder.addAction(firstActionIconId, action1Title, action1);

        return builder.build();
    }

    /**
     * Format "7 hours 52 minutes remaining"
     */
    @VisibleForTesting
    static String formatElapsedTimeUntilExpiry(Context context, long remainingTime) {
        final int hours = (int) remainingTime / (int) HOUR_IN_MILLIS;
        final int minutes = (int) remainingTime / ((int) MINUTE_IN_MILLIS) % 60;

        String minSeq = Utils.getNumberFormattedQuantityString(context, R.plurals.minutes, minutes);
        String hourSeq = Utils.getNumberFormattedQuantityString(context, R.plurals.hours, hours);

        // The verb "remaining" may have to change tense for singular subjects in some languages.
        final String verb = context.getString((minutes > 1 || hours > 1)
                ? R.string.timer_remaining_multiple
                : R.string.timer_remaining_single);

        final boolean showHours = hours > 0;
        final boolean showMinutes = minutes > 0;

        int formatStringId;
        if (showHours) {
            if (showMinutes) {
                formatStringId = R.string.timer_notifications_hours_minutes;
            } else {
                formatStringId = R.string.timer_notifications_hours;
            }
        } else if (showMinutes) {
            formatStringId = R.string.timer_notifications_minutes;
        } else {
            formatStringId = R.string.timer_notifications_less_min;
        }
        return String.format(context.getString(formatStringId), hourSeq, minSeq, verb);
    }
}
