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

import static com.example.android.wearable.quiz.Constants.ANSWERS;
import static com.example.android.wearable.quiz.Constants.CONNECT_TIMEOUT_MS;
import static com.example.android.wearable.quiz.Constants.CORRECT_ANSWER_INDEX;
import static com.example.android.wearable.quiz.Constants.NUM_CORRECT;
import static com.example.android.wearable.quiz.Constants.NUM_INCORRECT;
import static com.example.android.wearable.quiz.Constants.NUM_SKIPPED;
import static com.example.android.wearable.quiz.Constants.QUESTION;
import static com.example.android.wearable.quiz.Constants.QUESTION_INDEX;
import static com.example.android.wearable.quiz.Constants.QUESTION_WAS_ANSWERED;
import static com.example.android.wearable.quiz.Constants.QUESTION_WAS_DELETED;
import static com.example.android.wearable.quiz.Constants.QUIZ_ENDED_PATH;
import static com.example.android.wearable.quiz.Constants.QUIZ_EXITED_PATH;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.net.Uri;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.data.FreezableUtils;
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.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Listens to changes in DataItems, which represent quiz questions.
 * If a new question is created, this builds a new notification for it.
 * Otherwise, if a question is deleted, this cancels the corresponding notification.
 *
 * When the quiz ends, this listener receives a message telling it to create an end-of-quiz report.
 */
public class QuizListenerService extends WearableListenerService {

    private static final String TAG = "QuizSample";
    private static final int QUIZ_REPORT_NOTIF_ID = -1; // Never used by question notifications.
    private static final Map<Integer, Integer> questionNumToDrawableId;

    static {
        Map<Integer, Integer> temp = new HashMap<Integer, Integer>(4);
        temp.put(0, R.drawable.ic_choice_a);
        temp.put(1, R.drawable.ic_choice_b);
        temp.put(2, R.drawable.ic_choice_c);
        temp.put(3, R.drawable.ic_choice_d);
        questionNumToDrawableId = Collections.unmodifiableMap(temp);
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents);

        GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .build();

        ConnectionResult connectionResult = googleApiClient.blockingConnect(CONNECT_TIMEOUT_MS,
                TimeUnit.MILLISECONDS);
        if (!connectionResult.isSuccess()) {
            Log.e(TAG, "QuizListenerService failed to connect to GoogleApiClient.");
            return;
        }

        for (DataEvent event : events) {
            if (event.getType() == DataEvent.TYPE_CHANGED) {
                DataItem dataItem = event.getDataItem();
                DataMap dataMap = DataMapItem.fromDataItem(dataItem).getDataMap();
                if (dataMap.getBoolean(QUESTION_WAS_ANSWERED)
                        || dataMap.getBoolean(QUESTION_WAS_DELETED)) {
                    // Ignore the change in data; it is used in MainActivity to update
                    // the question's status (i.e. was the answer right or wrong or left blank).
                    continue;
                }
                String question = dataMap.getString(QUESTION);
                int questionIndex = dataMap.getInt(QUESTION_INDEX);
                int questionNum = questionIndex + 1;
                String[] answers = dataMap.getStringArray(ANSWERS);
                int correctAnswerIndex = dataMap.getInt(CORRECT_ANSWER_INDEX);
                Intent deleteOperation = new Intent(this, DeleteQuestionService.class);
                deleteOperation.setData(dataItem.getUri());
                PendingIntent deleteIntent = PendingIntent.getService(this, 0,
                        deleteOperation, PendingIntent.FLAG_UPDATE_CURRENT);
                // First page of notification contains question as Big Text.
                Notification.BigTextStyle bigTextStyle = new Notification.BigTextStyle()
                        .setBigContentTitle(getString(R.string.question, questionNum))
                        .bigText(question);
                Notification.Builder builder = new Notification.Builder(this)
                        .setStyle(bigTextStyle)
                        .setSmallIcon(R.drawable.ic_launcher)
                        .setLocalOnly(true)
                        .setDeleteIntent(deleteIntent);

                // Add answers as actions.
                Notification.WearableExtender wearableOptions = new Notification.WearableExtender();
                for (int i = 0; i < answers.length; i++) {
                    Notification answerPage = new Notification.Builder(this)
                            .setContentTitle(question)
                            .setContentText(answers[i])
                            .extend(new Notification.WearableExtender()
                                    .setContentAction(i))
                            .build();

                    boolean correct = (i == correctAnswerIndex);
                    Intent updateOperation = new Intent(this, UpdateQuestionService.class);
                    // Give each intent a unique action.
                    updateOperation.setAction("question_" + questionIndex + "_answer_" + i);
                    updateOperation.setData(dataItem.getUri());
                    updateOperation.putExtra(UpdateQuestionService.EXTRA_QUESTION_INDEX,
                            questionIndex);
                    updateOperation.putExtra(UpdateQuestionService.EXTRA_QUESTION_CORRECT, correct);
                    PendingIntent updateIntent = PendingIntent.getService(this, 0, updateOperation,
                            PendingIntent.FLAG_UPDATE_CURRENT);
                    Notification.Action action = new Notification.Action.Builder(
                            questionNumToDrawableId.get(i), null, updateIntent)
                            .build();
                    wearableOptions.addAction(action).addPage(answerPage);
                }
                builder.extend(wearableOptions);
                Notification notification = builder.build();
                ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                        .notify(questionIndex, notification);
            } else if (event.getType() == DataEvent.TYPE_DELETED) {
                Uri uri = event.getDataItem().getUri();
                // URI's are of the form "/question/0", "/question/1" etc.
                // We use the question index as the notification id.
                int notificationId = Integer.parseInt(uri.getLastPathSegment());
                ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                        .cancel(notificationId);
            }
            // Delete the quiz report, if it exists.
            ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                    .cancel(QUIZ_REPORT_NOTIF_ID);
        }
        googleApiClient.disconnect();
    }

    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
        String path = messageEvent.getPath();
        if (path.equals(QUIZ_EXITED_PATH)) {
            // Remove any lingering question notifications.
            ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancelAll();
        }
        if (path.equals(QUIZ_ENDED_PATH) || path.equals(QUIZ_EXITED_PATH)) {
            // Quiz ended - display overall results.
            DataMap dataMap = DataMap.fromByteArray(messageEvent.getData());
            int numCorrect = dataMap.getInt(NUM_CORRECT);
            int numIncorrect = dataMap.getInt(NUM_INCORRECT);
            int numSkipped = dataMap.getInt(NUM_SKIPPED);

            Notification.Builder builder = new Notification.Builder(this)
                    .setContentTitle(getString(R.string.quiz_report))
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setLocalOnly(true);
            SpannableStringBuilder quizReportText = new SpannableStringBuilder();
            appendColored(quizReportText, String.valueOf(numCorrect), R.color.dark_green);
            quizReportText.append(" " + getString(R.string.correct) + "\n");
            appendColored(quizReportText, String.valueOf(numIncorrect), R.color.dark_red);
            quizReportText.append(" " + getString(R.string.incorrect) + "\n");
            appendColored(quizReportText, String.valueOf(numSkipped), R.color.dark_yellow);
            quizReportText.append(" " + getString(R.string.skipped) + "\n");

            builder.setContentText(quizReportText);
            if (!path.equals(QUIZ_EXITED_PATH)) {
                // Don't add reset option if user exited quiz (there might not be a quiz to reset!).
                builder.addAction(R.drawable.ic_launcher,
                        getString(R.string.reset_quiz), getResetQuizPendingIntent());
            }
            ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                    .notify(QUIZ_REPORT_NOTIF_ID, builder.build());
        }
    }

    private void appendColored(SpannableStringBuilder builder, String text, int colorResId) {
        builder.append(text).setSpan(new ForegroundColorSpan(getResources().getColor(colorResId)),
                builder.length() - text.length(), builder.length(), 0);
    }

    /**
     * Returns a PendingIntent that will send a message to the phone to reset the quiz when fired.
     */
    private PendingIntent getResetQuizPendingIntent() {
        Intent intent = new Intent(QuizReportActionService.ACTION_RESET_QUIZ)
                .setClass(this, QuizReportActionService.class);
        return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }
}
