/*
 * Copyright (C) 2007 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.calendar;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.provider.Calendar.CalendarAlerts;

/**
 * Receives android.intent.action.EVENT_REMINDER intents and handles
 * event reminders.  The intent URI specifies an alert id in the 
 * CalendarAlerts database table.  This class also receives the
 * BOOT_COMPLETED intent so that it can add a status bar notification
 * if there are Calendar event alarms that have not been dismissed.
 * It also receives the TIME_CHANGED action so that it can fire off
 * snoozed alarms that have become ready.  The real work is done in
 * the AlertService class.
 */
public class AlertReceiver extends BroadcastReceiver {
    private static final String[] ALERT_PROJECTION = new String[] { 
        CalendarAlerts.TITLE,           // 0
        CalendarAlerts.EVENT_LOCATION,  // 1
    };
    private static final int ALERT_INDEX_TITLE = 0;
    private static final int ALERT_INDEX_EVENT_LOCATION = 1;
    
    private static final String DELETE_ACTION = "delete";
    
    static final Object mStartingServiceSync = new Object();
    static PowerManager.WakeLock mStartingService;
    
    @Override
    public void onReceive(Context context, Intent intent) {
        if (DELETE_ACTION.equals(intent.getAction())) {
            
            /* The user has clicked the "Clear All Notifications"
             * buttons so dismiss all Calendar alerts.
             */
            // TODO Grab a wake lock here?
            Intent serviceIntent = new Intent(context, DismissAllAlarmsService.class);
            context.startService(serviceIntent);
        } else {
            Intent i = new Intent();
            i.setClass(context, AlertService.class);
            i.putExtras(intent);
            i.putExtra("action", intent.getAction());
            Uri uri = intent.getData();
            
            // This intent might be a BOOT_COMPLETED so it might not have a Uri.
            if (uri != null) {
                i.putExtra("uri", uri.toString());
            }
            beginStartingService(context, i);
        }
    }

    /**
     * Start the service to process the current event notifications, acquiring
     * the wake lock before returning to ensure that the service will run.
     */
    public static void beginStartingService(Context context, Intent intent) {
        synchronized (mStartingServiceSync) {
            if (mStartingService == null) {
                PowerManager pm =
                    (PowerManager)context.getSystemService(Context.POWER_SERVICE);
                mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                        "StartingAlertService");
                mStartingService.setReferenceCounted(false);
            }
            mStartingService.acquire();
            context.startService(intent);
        }
    }
    
    /**
     * Called back by the service when it has finished processing notifications,
     * releasing the wake lock if the service is now stopping.
     */
    public static void finishStartingService(Service service, int startId) {
        synchronized (mStartingServiceSync) {
            if (mStartingService != null) {
                if (service.stopSelfResult(startId)) {
                    mStartingService.release();
                }
            }
        }
    }
    
    public static void updateAlertNotification(Context context) {
        // This can be called regularly to synchronize the alert notification
        // with the contents of the CalendarAlerts table.
        
        ContentResolver cr = context.getContentResolver();
        
        if (cr == null) {
            return;
        }
        
        String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.FIRED;
        Cursor alertCursor = CalendarAlerts.query(cr, ALERT_PROJECTION, selection, null);
        
        NotificationManager nm = 
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        
        if (alertCursor == null) {
            nm.cancel(AlertActivity.NOTIFICATION_ID);
            return;
        }

        if (!alertCursor.moveToFirst()) {
            alertCursor.close();
            nm.cancel(AlertActivity.NOTIFICATION_ID);
            return;
        }

        // Check the settings to see if alerts are disabled
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        String reminderType = prefs.getString(CalendarPreferenceActivity.KEY_ALERTS_TYPE,
                CalendarPreferenceActivity.ALERT_TYPE_STATUS_BAR);
        if (reminderType.equals(CalendarPreferenceActivity.ALERT_TYPE_OFF)) {
            return;
        }

        String title = alertCursor.getString(ALERT_INDEX_TITLE);
        String location = alertCursor.getString(ALERT_INDEX_EVENT_LOCATION);
        
        Notification notification = AlertReceiver.makeNewAlertNotification(context, title, 
                location, alertCursor.getCount());
        alertCursor.close();
        
        nm.notify(0, notification);
    }
    
    public static Notification makeNewAlertNotification(Context context, String title, 
            String location, int numReminders) {
        Resources res = context.getResources();
        
        // Create an intent triggered by clicking on the status icon.
        Intent clickIntent = new Intent();
        clickIntent.setClass(context, AlertActivity.class);
        clickIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        
        // Create an intent triggered by clicking on the "Clear All Notifications" button
        Intent deleteIntent = new Intent();
        deleteIntent.setClass(context, AlertReceiver.class);
        deleteIntent.setAction(DELETE_ACTION);
        
        if (title == null || title.length() == 0) {
            title = res.getString(R.string.no_title_label);
        }
        
        String helperString;
        if (numReminders > 1) {
            String format;
            if (numReminders == 2) {
                format = res.getString(R.string.alert_missed_events_single);
            } else {
                format = res.getString(R.string.alert_missed_events_multiple);
            }
            helperString = String.format(format, numReminders - 1);
        } else {
            helperString = location;
        }
        
        Notification notification = new Notification(
                R.drawable.stat_notify_calendar,
                null,
                System.currentTimeMillis());
        notification.setLatestEventInfo(context,
                title,
                helperString,
                PendingIntent.getActivity(context, 0, clickIntent, 0));
        notification.deleteIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);
        
        return notification;
    }
}

