/*
 * Copyright (C) 2014 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.example.android.wearable.agendadata;

import static com.example.android.wearable.agendadata.Constants.TAG;
import static com.example.android.wearable.agendadata.Constants.EXTRA_SILENT;

import static com.example.android.wearable.agendadata.Constants.ALL_DAY;
import static com.example.android.wearable.agendadata.Constants.BEGIN;
import static com.example.android.wearable.agendadata.Constants.DESCRIPTION;
import static com.example.android.wearable.agendadata.Constants.END;
import static com.example.android.wearable.agendadata.Constants.PROFILE_PIC;
import static com.example.android.wearable.agendadata.Constants.TITLE;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.Log;

import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataItem;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Listens to DataItem events on the home device.
 */
public class HomeListenerService extends WearableListenerService {

    private static final Map<Uri, Integer> sNotificationIdByDataItemUri =
            new HashMap<Uri, Integer>();
    private static int sNotificationId = 1;
    private GoogleApiClient mGoogleApiClient;

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDataChanged: " + dataEvents + " for " + getPackageName());
        }
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_DELETED) {
                deleteDataItem(event.getDataItem());
            } else if (event.getType() == DataEvent.TYPE_CHANGED) {
                UpdateNotificationForDataItem(event.getDataItem());
            }
        }
        dataEvents.close();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mGoogleApiClient = new GoogleApiClient.Builder(this.getApplicationContext())
                .addApi(Wearable.API)
                .build();
        mGoogleApiClient.connect();
    }

    /**
     * Posts a local notification to show calendar card.
     */
    private void UpdateNotificationForDataItem(DataItem dataItem) {
        DataMapItem mapDataItem = DataMapItem.fromDataItem(dataItem);
        DataMap data = mapDataItem.getDataMap();

        String description = data.getString(DESCRIPTION);
        if (TextUtils.isEmpty(description)) {
            description = "";
        } else {
            // Add a space between the description and the time of the event.
            description += " ";
        }
        String contentText;
        if (data.getBoolean(ALL_DAY)) {
            contentText = getString(R.string.desc_all_day, description);
        } else {
            String startTime = DateFormat.getTimeFormat(this).format(new Date(data.getLong(BEGIN)));
            String endTime = DateFormat.getTimeFormat(this).format(new Date(data.getLong(END)));
            contentText = getString(R.string.desc_time_period, description, startTime, endTime);
        }

        Intent deleteOperation = new Intent(this, DeleteService.class);
        // Use a unique identifier for the delete action.
        String deleteAction = "action_delete" + dataItem.getUri().toString() + sNotificationId;
        deleteOperation.setAction(deleteAction);
        deleteOperation.setData(dataItem.getUri());
        PendingIntent deleteIntent = PendingIntent.getService(this, 0, deleteOperation,
                PendingIntent.FLAG_ONE_SHOT);
        PendingIntent silentDeleteIntent = PendingIntent.getService(this, 1,
                deleteOperation.putExtra(EXTRA_SILENT, true), PendingIntent.FLAG_ONE_SHOT);

        Notification.Builder notificationBuilder = new Notification.Builder(this)
                .setContentTitle(data.getString(TITLE))
                .setContentText(contentText)
                .setSmallIcon(R.drawable.ic_launcher)
                .addAction(R.drawable.ic_menu_delete, getText(R.string.delete), deleteIntent)
                .setDeleteIntent(silentDeleteIntent)  // Delete DataItem if notification dismissed.
                .setLocalOnly(true)
                .setPriority(Notification.PRIORITY_MIN);

        // Set the event owner's profile picture as the notification background.
        Asset asset = data.getAsset(PROFILE_PIC);
        if (null != asset) {
            if (mGoogleApiClient.isConnected()) {
                DataApi.GetFdForAssetResult assetFdResult =
                        Wearable.DataApi.getFdForAsset(mGoogleApiClient, asset).await();
                if (assetFdResult.getStatus().isSuccess()) {
                    Bitmap profilePic = BitmapFactory.decodeStream(assetFdResult.getInputStream());
                    notificationBuilder.extend(new Notification.WearableExtender()
                            .setBackground(profilePic));
                } else if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "asset fetch failed with statusCode: "
                            + assetFdResult.getStatus().getStatusCode());
                }
            } else {
                Log.e(TAG, "Failed to set notification background"
                         + " - Client disconnected from Google Play Services");
            }
        }
        Notification card = notificationBuilder.build();

        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                .notify(sNotificationId, card);

        sNotificationIdByDataItemUri.put(dataItem.getUri(), sNotificationId++);
    }

    /**
     * Deletes the calendar card associated with the data item.
     */
    private void deleteDataItem(DataItem dataItem) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "onDataItemDeleted:DataItem=" + dataItem.getUri());
        }
        Integer notificationId = sNotificationIdByDataItemUri.remove(dataItem.getUri());
        if (notificationId != null) {
            ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancel(notificationId);
        }
    }

    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onMessageReceived: " + messageEvent.getPath()
                     + " " + messageEvent.getData() + " for " + getPackageName());
        }
    }

}
