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

import android.app.Activity;
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.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.CalendarContract.CalendarAlerts;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Events;
import android.util.Log;
import android.util.Pair;

import com.android.calendar.CloudNotificationBackplane;
import com.android.calendar.ExtensionsFactory;
import com.android.calendar.R;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Utilities for managing notification dismissal across devices.
 */
public class GlobalDismissManager extends BroadcastReceiver {
    private static final String TAG = "GlobalDismissManager";
    private static final String GOOGLE_ACCOUNT_TYPE = "com.google";
    private static final String GLOBAL_DISMISS_MANAGER_PREFS = "com.android.calendar.alerts.GDM";
    private static final String ACCOUNT_KEY = "known_accounts";
    protected static final long FOUR_WEEKS = 60 * 60 * 24 * 7 * 4;

    static final String[] EVENT_PROJECTION = new String[] {
            Events._ID,
            Events.CALENDAR_ID
    };
    static final String[] EVENT_SYNC_PROJECTION = new String[] {
            Events._ID,
            Events._SYNC_ID
    };
    static final String[] CALENDARS_PROJECTION = new String[] {
            Calendars._ID,
            Calendars.ACCOUNT_NAME,
            Calendars.ACCOUNT_TYPE
    };

    public static final String KEY_PREFIX = "com.android.calendar.alerts.";
    public static final String SYNC_ID = KEY_PREFIX + "sync_id";
    public static final String START_TIME = KEY_PREFIX + "start_time";
    public static final String ACCOUNT_NAME = KEY_PREFIX + "account_name";
    public static final String DISMISS_INTENT = KEY_PREFIX + "DISMISS";

    public static class AlarmId {
        public long mEventId;
        public long mStart;
         public AlarmId(long id, long start) {
             mEventId = id;
             mStart = start;
         }
    }

    /**
     * Look for unknown accounts in a set of events and associate with them.
     * Returns immediately, processing happens in the background.
     * 
     * @param context application context
     * @param eventIds IDs for events that have posted notifications that may be
     *            dismissed.
     */
    public static void processEventIds(final Context context, final Set<Long> eventIds) {
        final String senderId = context.getResources().getString(R.string.notification_sender_id);
        if (senderId == null || senderId.isEmpty()) {
            Log.i(TAG, "no sender configured");
            return;
        }
        new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... params) {

                Map<Long, Long> eventsToCalendars = lookupEventToCalendarMap(context, eventIds);
                Set<Long> calendars = new LinkedHashSet<Long>();
                calendars.addAll(eventsToCalendars.values());
                if (calendars.isEmpty()) {
                    Log.d(TAG, "foudn no calendars for events");
                    return null;
                }

                Map<Long, Pair<String, String>> calendarsToAccounts =
                        lookupCalendarToAccountMap(context, calendars);

                if (calendarsToAccounts.isEmpty()) {
                    Log.d(TAG, "found no accounts for calendars");
                    return null;
                }

                // filter out non-google accounts (necessary?)
                Set<String> accounts = new LinkedHashSet<String>();
                for (Pair<String, String> accountPair : calendarsToAccounts.values()) {
                    if (GOOGLE_ACCOUNT_TYPE.equals(accountPair.first)) {
                        accounts.add(accountPair.second);
                    }
                }

                // filter out accounts we already know about
                SharedPreferences prefs =
                        context.getSharedPreferences(GLOBAL_DISMISS_MANAGER_PREFS,
                                Context.MODE_PRIVATE);
                Set<String> existingAccounts = prefs.getStringSet(ACCOUNT_KEY,
                        new HashSet<String>());
                accounts.removeAll(existingAccounts);

                if (accounts.isEmpty()) {
                    return null;
                }

                // subscribe to remaining accounts
                CloudNotificationBackplane cnb =
                        ExtensionsFactory.getCloudNotificationBackplane();
                if (cnb.open(context)) {
                    for (String account : accounts) {
                        try {
                            if (cnb.subscribeToGroup(senderId, account, account)) {
                                existingAccounts.add(account);
                            }
                        } catch (IOException e) {
                            // Try again, next time the account triggers and alert.
                        }
                    }
                    cnb.close();
                    prefs.edit()
                    .putStringSet(ACCOUNT_KEY, existingAccounts)
                    .commit();
                }
                return null;
            }
        }.execute();
    }

    /**
     * Globally dismiss notifications that are backed by the same events.
     * 
     * @param context application context
     * @param alarmIds Unique identifiers for events that have been dismissed by the user.
     * @return true if notification_sender_id is available
     */
    public static void dismissGlobally(final Context context, final List<AlarmId> alarmIds) {
        final String senderId = context.getResources().getString(R.string.notification_sender_id);
        if ("".equals(senderId)) {
            Log.i(TAG, "no sender configured");
            return;
        }
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                Set<Long> eventIds = new HashSet<Long>(alarmIds.size());
                for (AlarmId alarmId: alarmIds) {
                    eventIds.add(alarmId.mEventId);
                }
                // find the mapping between calendars and events
                Map<Long, Long> eventsToCalendars = lookupEventToCalendarMap(context, eventIds);

                if (eventsToCalendars.isEmpty()) {
                    Log.d(TAG, "found no calendars for events");
                    return null;
                }

                Set<Long> calendars = new LinkedHashSet<Long>();
                calendars.addAll(eventsToCalendars.values());

                // find the accounts associated with those calendars
                Map<Long, Pair<String, String>> calendarsToAccounts =
                        lookupCalendarToAccountMap(context, calendars);

                if (calendarsToAccounts.isEmpty()) {
                    Log.d(TAG, "found no accounts for calendars");
                    return null;
                }

                // TODO group by account to reduce queries
                Map<String, String> syncIdToAccount = new HashMap<String, String>();
                Map<Long, String> eventIdToSyncId = new HashMap<Long, String>();
                ContentResolver resolver = context.getContentResolver();
                for (Long eventId : eventsToCalendars.keySet()) {
                    Long calendar = eventsToCalendars.get(eventId);
                    Pair<String, String> account = calendarsToAccounts.get(calendar);
                    if (GOOGLE_ACCOUNT_TYPE.equals(account.first)) {
                        Uri uri = asSync(Events.CONTENT_URI, account.first, account.second);
                        Cursor cursor = resolver.query(uri, EVENT_SYNC_PROJECTION,
                                Events._ID + " = " + eventId, null, null);
                        try {
                            cursor.moveToPosition(-1);
                            int sync_id_idx = cursor.getColumnIndex(Events._SYNC_ID);
                            if (sync_id_idx != -1) {
                                while (cursor.moveToNext()) {
                                    String syncId = cursor.getString(sync_id_idx);
                                    syncIdToAccount.put(syncId, account.second);
                                    eventIdToSyncId.put(eventId, syncId);
                                }
                            }
                        } finally {
                            cursor.close();
                        }
                    }
                }

                if (syncIdToAccount.isEmpty()) {
                    Log.d(TAG, "found no syncIds for events");
                    return null;
                }

                // TODO group by account to reduce packets
                CloudNotificationBackplane cnb = ExtensionsFactory.getCloudNotificationBackplane();
                if (cnb.open(context)) {
                    for (AlarmId alarmId: alarmIds) {
                        String syncId = eventIdToSyncId.get(alarmId.mEventId);
                        String account = syncIdToAccount.get(syncId);
                        Bundle data = new Bundle();
                        data.putString(SYNC_ID, syncId);
                        data.putString(START_TIME, Long.toString(alarmId.mStart));
                        data.putString(ACCOUNT_NAME, account);
                        try {
                            cnb.send(account, syncId + ":" + alarmId.mStart, data);
                        } catch (IOException e) {
                            // TODO save a note to try again later
                        }
                    }
                    cnb.close();
                }
                return null;
            }
        }.execute();
    }

    private static Uri asSync(Uri uri, String accountType, String account) {
        return uri
                .buildUpon()
                .appendQueryParameter(
                        android.provider.CalendarContract.CALLER_IS_SYNCADAPTER, "true")
                .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
                .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
    }

    /**
     * build a selection over a set of row IDs
     * 
     * @param ids row IDs to select
     * @param key row name for the table
     * @return a selection string suitable for a resolver query.
     */
    private static String buildMultipleIdQuery(Set<Long> ids, String key) {
        StringBuilder selection = new StringBuilder();
        boolean first = true;
        for (Long id : ids) {
            if (first) {
                first = false;
            } else {
                selection.append(" OR ");
            }
            selection.append(key);
            selection.append("=");
            selection.append(id);
        }
        return selection.toString();
    }

    /**
     * @param context application context
     * @param eventIds Event row IDs to query.
     * @return a map from event to calendar
     */
    private static Map<Long, Long> lookupEventToCalendarMap(final Context context,
            final Set<Long> eventIds) {
        Map<Long, Long> eventsToCalendars = new HashMap<Long, Long>();
        ContentResolver resolver = context.getContentResolver();
        String eventSelection = buildMultipleIdQuery(eventIds, Events._ID);
        Cursor eventCursor = resolver.query(Events.CONTENT_URI, EVENT_PROJECTION,
                eventSelection, null, null);
        try {
            eventCursor.moveToPosition(-1);
            int calendar_id_idx = eventCursor.getColumnIndex(Events.CALENDAR_ID);
            int event_id_idx = eventCursor.getColumnIndex(Events._ID);
            if (calendar_id_idx != -1 && event_id_idx != -1) {
                while (eventCursor.moveToNext()) {
                    eventsToCalendars.put(eventCursor.getLong(event_id_idx),
                            eventCursor.getLong(calendar_id_idx));
                }
            }
        } finally {
            eventCursor.close();
        }
        return eventsToCalendars;
    }

    /**
     * @param context application context
     * @param calendars Calendar row IDs to query.
     * @return a map from Calendar to a pair (account type, account name)
     */
    private static Map<Long, Pair<String, String>> lookupCalendarToAccountMap(final Context context,
            Set<Long> calendars) {
        Map<Long, Pair<String, String>> calendarsToAccounts =
                new HashMap<Long, Pair<String, String>>();
        ;
        ContentResolver resolver = context.getContentResolver();
        String calendarSelection = buildMultipleIdQuery(calendars, Calendars._ID);
        Cursor calendarCursor = resolver.query(Calendars.CONTENT_URI, CALENDARS_PROJECTION,
                calendarSelection, null, null);
        try {
            calendarCursor.moveToPosition(-1);
            int calendar_id_idx = calendarCursor.getColumnIndex(Calendars._ID);
            int account_name_idx = calendarCursor.getColumnIndex(Calendars.ACCOUNT_NAME);
            int account_type_idx = calendarCursor.getColumnIndex(Calendars.ACCOUNT_TYPE);
            if (calendar_id_idx != -1 && account_name_idx != -1 && account_type_idx != -1) {
                while (calendarCursor.moveToNext()) {
                    Long id = calendarCursor.getLong(calendar_id_idx);
                    String name = calendarCursor.getString(account_name_idx);
                    String type = calendarCursor.getString(account_type_idx);
                    calendarsToAccounts.put(id, new Pair<String, String>(type, name));
                }
            }
        } finally {
            calendarCursor.close();
        }
        return calendarsToAccounts;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        boolean updated = false;
        if (intent.hasExtra(SYNC_ID) && intent.hasExtra(ACCOUNT_NAME)) {
            String syncId = intent.getStringExtra(SYNC_ID);
            long startTime = Long.parseLong(intent.getStringExtra(START_TIME));
            ContentResolver resolver = context.getContentResolver();

            Uri uri = asSync(Events.CONTENT_URI, GOOGLE_ACCOUNT_TYPE,
                    intent.getStringExtra(ACCOUNT_NAME));
            Cursor cursor = resolver.query(uri, EVENT_SYNC_PROJECTION,
                    Events._SYNC_ID + " = '" + syncId + "'", null, null);
            try {
                int event_id_idx = cursor.getColumnIndex(Events._ID);
                cursor.moveToFirst();
                if (event_id_idx != -1 && !cursor.isAfterLast()) {
                    long eventId = cursor.getLong(event_id_idx);
                    ContentValues values = new ContentValues();
                    String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.STATE_FIRED +
                            " AND " + CalendarAlerts.EVENT_ID + "=" + eventId +
                            " AND " + CalendarAlerts.BEGIN + "=" + startTime;
                    values.put(CalendarAlerts.STATE, CalendarAlerts.STATE_DISMISSED);
                    if (resolver.update(CalendarAlerts.CONTENT_URI, values, selection, null) > 0) {
                        updated |= true;
                    }
                }
            } finally {
                cursor.close();
            }
        }

        if (updated) {
            Log.d(TAG, "updating alarm state");
            AlertService.updateAlertNotification(context);
        }
    }
}
