package me.shouheng.omnilist.receiver;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.support.v4.app.NotificationCompat.Builder;

import java.util.Calendar;

import me.shouheng.omnilist.PalmApp;
import me.shouheng.omnilist.R;
import me.shouheng.omnilist.activity.ContentActivity;
import me.shouheng.omnilist.config.Constants;
import me.shouheng.omnilist.manager.AlarmNotFoundException;
import me.shouheng.omnilist.manager.AlarmsManager;
import me.shouheng.omnilist.manager.PresentationToModelIntents;
import me.shouheng.omnilist.model.Alarm;
import me.shouheng.omnilist.model.Assignment;
import me.shouheng.omnilist.provider.AssignmentsStore;
import me.shouheng.omnilist.utils.ColorUtils;
import me.shouheng.omnilist.utils.LogUtils;
import me.shouheng.omnilist.utils.ToastUtils;
import me.shouheng.omnilist.utils.preferences.NoticePreferences;

public class AlarmAlertReceiver extends BroadcastReceiver {

    private final static int NOTIFICATION_OFFSET = 1000;

    private Context context;

    private AlarmsManager alarmsManager;

    private NotificationManager notificationManager;

    @Override
    public void onReceive(final Context ctx, final Intent intent) {
        context = ctx;
        alarmsManager = AlarmsManager.getsInstance();
        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        
        handleIntent(intent);
    }

    private void handleIntent(final Intent intent) {
        String action = intent.getAction();
        if (action == null) {
            throw new IllegalArgumentException("Illegal action received");
        }

        /*Notice the extra code is long value.*/
        long code = intent.getLongExtra(Constants.EXTRA_CODE, -1);
        try {
            switch (action) {
                case Constants.ACTION_ALARM_ALERT: {
                    /*Alert and set next time.*/
                    Alarm alarm = alarmsManager.getAlarm((int) code);
                    onAlert(alarm);
                    alarmsManager.registerAlarm(alarm);
                    break;
                }
                case Constants.ACTION_ALARM_DISMISS: {
                    /*Dismiss current notification.*/
                    notificationManager.cancel((int) code);
                    notificationManager.cancel((int) (code + NOTIFICATION_OFFSET));
                    break;
                }
                case Constants.ACTION_CANCEL_SNOOZE: {
                    /*Cancel snooze notification.*/
                    notificationManager.cancel((int) code);
                    notificationManager.cancel((int) (code + NOTIFICATION_OFFSET));
                    break;
                }
                case Constants.ACTION_ALARM_SNOOZE: {
                    /*Cancel current notification and snooze the alarm.*/
                    notificationManager.cancel((int) code);
                    Alarm alarm = alarmsManager.getAlarm((int) code);
                    onSnoozed(alarm);
                    break;
                }
                case Constants.ACTION_CANCEL_NOTIFICATION: {
                    /*Cancel current notification.*/
                    int notificationId = intent.getIntExtra(Constants.EXTRA_NOTIFICATION_ID, -1);
                    notificationManager.cancel(notificationId);
                    break;
                }
                case Constants.ACTION_MARK_ASSIGNMENT_AS_DONE: {
                    /*Done assignment and cancel current notification.*/
                    AssignmentsStore.getInstance().updateAssignment(code, true);
                    int notificationId = intent.getIntExtra(Constants.EXTRA_NOTIFICATION_ID, -1);
                    notificationManager.cancel(notificationId);
                    ToastUtils.makeToast(R.string.one_assignment_marked_as_done);
                    break;
                }
                case Constants.ACTION_POSTPONE_ALARM: {
                    /*Postpone alarm for given minutes.*/
                    Alarm alarm = alarmsManager.getAlarm((int) code);
                    int snoozeMinutes = NoticePreferences.getInstance().getSnoozeDuration();
                    Calendar nextTime = Calendar.getInstance();
                    nextTime.add(Calendar.MINUTE, snoozeMinutes);
                    alarm.setNextTime(nextTime);
                    alarmsManager.setUpRTCAlarm(alarm);
                    int notificationId = intent.getIntExtra(Constants.EXTRA_NOTIFICATION_ID, -1);
                    notificationManager.cancel(notificationId);
                    ToastUtils.makeToast(String.format(PalmApp.getStringCompact(R.string.will_be_reminded_in_minutes), snoozeMinutes));
                    break;
                }
            }
        } catch (AlarmNotFoundException e) {
            notificationManager.cancel((int) code);
        }
    }

    private void onAlert(Alarm alarm) {
        int alarmCode = (int) alarm.getCode();
        Assignment assignment = AssignmentsStore.getInstance().get(alarm.getModelCode());
        /*If the assignment is null, we don't show notification for it*/
        if (assignment == null) {
            alarmsManager.removeAlarm(alarm);
            return;
        }

        Builder mBuilder = new Builder(context)
                .setContentTitle(assignment.getName())
                .setContentText(assignment.getComment())
                .setAutoCancel(true)
                .setSmallIcon(R.drawable.ic_assignment_turned_in_black_24dp)
                .setColor(ColorUtils.accentColor());

        /*Add action: mark as done.*/
        Intent mdIntent = new Intent(context, AlarmAlertReceiver.class);
        mdIntent.setAction(Constants.ACTION_MARK_ASSIGNMENT_AS_DONE);
        mdIntent.putExtra(Constants.EXTRA_CODE, assignment.getCode());
        mdIntent.putExtra(Constants.EXTRA_NOTIFICATION_ID, (int) alarm.getCode());
        PendingIntent piMD = PendingIntent.getBroadcast(
                context, (int) alarm.getCode(), mdIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        mBuilder.addAction(R.drawable.ic_check_circle_black_24dp, context.getString(R.string.mark_as_done), piMD);

        /*Add action: postpone.*/
        Intent pIntent = new Intent(context, AlarmAlertReceiver.class);
        pIntent.setAction(Constants.ACTION_POSTPONE_ALARM);
        pIntent.putExtra(Constants.EXTRA_CODE, alarm.getCode());
        pIntent.putExtra(Constants.EXTRA_NOTIFICATION_ID, (int) alarm.getCode());
        PendingIntent piP = PendingIntent.getBroadcast(
                context, (int) alarm.getCode(), pIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        int snoozeMinutes = NoticePreferences.getInstance().getSnoozeDuration();
        mBuilder.addAction(R.drawable.ic_snooze_black_24dp, String.format(context.getString(R.string.remind_in_minutes), snoozeMinutes), piP);

        /*Add action: click.*/
        Intent clickIntent = new Intent(context, ContentActivity.class);
        clickIntent.setAction(Constants.ACTION_NOTIFICATION);
        clickIntent.putExtra(Constants.EXTRA_CODE, assignment.getCode());
        clickIntent.putExtra(Constants.EXTRA_FRAGMENT, Constants.VALUE_FRAGMENT_ASSIGNMENT);
        clickIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent contentIntent = PendingIntent.getActivity(
                context, (int) assignment.getCode(), clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(contentIntent);

        /*Vibrate.*/
        if (NoticePreferences.getInstance().isVibrateAllowed()) {
            mBuilder.setVibrate(getVibrate());
        }

        /*Ringtone.*/
        String ringtone = NoticePreferences.getInstance().getNotificationRingtone(); // 铃声
        if (ringtone != null){
            mBuilder.setSound(Uri.parse(ringtone));
        }

        Notification notification = mBuilder.build();

        /*Light.*/
        setNotificationLight(notification);

        notificationManager.notify(alarmCode, notification);
    }

    private void onSnoozed(Alarm alarm) {
        LogUtils.d("onSnoozed: " + alarm);
        int alarmCode = (int) alarm.getCode();
        Assignment assignment = AssignmentsStore.getInstance().get(alarm.getModelCode());

        /*Add action cancel.*/
        Intent cancelIntent = new Intent(context, AlarmAlertReceiver.class);
        cancelIntent.setAction(Constants.ACTION_CANCEL_NOTIFICATION);
        cancelIntent.putExtra(Constants.EXTRA_CODE, alarmCode);
        PendingIntent piCancel = PendingIntent.getBroadcast(context, alarmCode, cancelIntent, 0);

        /*Action dismiss.*/
        PendingIntent piDismiss = PresentationToModelIntents.createPendingIntent(
                context, PresentationToModelIntents.ACTION_REQUEST_DISMISS, alarmCode);

        Notification status = new Builder(context)
                .setContentTitle(assignment.getName())
                .setContentText(assignment.getComment())
                .setSmallIcon(R.drawable.ic_assignment_turned_in_black_24dp)
                .setContentIntent(piCancel)
                .setOngoing(true)
                .addAction(R.drawable.ic_highlight_off_black_24dp, PalmApp.getStringCompact(R.string.text_dismiss), piDismiss)
                .setDefaults(Notification.DEFAULT_LIGHTS)
                .build();

        notificationManager.notify(alarmCode, status);
    }

    private long[] getVibrate() {
        return new long[]{500, 500};
    }

    private void setNotificationLight(Notification notification) {
        notification.flags |= Notification.FLAG_SHOW_LIGHTS;
        switch (NoticePreferences.getInstance().getLightColor()) {
            case 0:
                notification.ledARGB = Color.GREEN;
                break;
            case 1:
                notification.ledARGB = Color.RED;
                break;
            case 2:
                notification.ledARGB = Color.YELLOW;
                break;
            case 3:
                notification.ledARGB = Color.BLUE;
                break;
            case 4:
                break;
        }
        notification.ledOnMS = 1000;
        notification.ledOffMS = 1000;
    }
}