package de.beyondsoft.ownchat.data.firebase;

import de.beyondsoft.ownchat.BewoplanerApplication;
import de.beyondsoft.ownchat.R;
import de.beyondsoft.ownchat.data.AppPrefsConstants;
import de.beyondsoft.ownchat.data.api.common.ErrorHandlingResponseConverter;
import de.beyondsoft.ownchat.data.api.responses.MessageResponse;
import de.beyondsoft.ownchat.data.api.services.ChatService;
import de.beyondsoft.ownchat.data.prefs.LongPreference;
import de.beyondsoft.ownchat.data.prefs.StringPreference;
import de.beyondsoft.ownchat.data.repository.GroupRealmRepository;
import de.beyondsoft.ownchat.data.repository.MessageRealmRepository;
import de.beyondsoft.ownchat.data.repository.RealmProvider;
import de.beyondsoft.ownchat.data.repository.specifications.GroupByIdSpecification;
import de.beyondsoft.ownchat.data.repository.specifications.MessageByIdSpecification;
import de.beyondsoft.ownchat.di.InjectionHelper;
import de.beyondsoft.ownchat.model.Group;
import de.beyondsoft.ownchat.model.Message;
import de.beyondsoft.ownchat.page.chat.ChatPresenter;
import de.beyondsoft.ownchat.utils.Constants;
import de.beyondsoft.ownchat.utils.rx.RxUtils;

import android.app.Notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;
import javax.inject.Named;

import rx.Observable;
import rx.Subscriber;

import static android.support.v4.app.NotificationCompat.DEFAULT_ALL;
import static android.support.v4.app.NotificationCompat.PRIORITY_MAX;
import static de.beyondsoft.ownchat.utils.Constants.GROUP_ID;

public class ReplyNotificationReceiver extends BroadcastReceiver {
    private static final String BUNDLE = "bundle";

    @Inject
    ChatService mChatService;

    @Inject
    @Named(AppPrefsConstants.USER_ID)
    LongPreference mUserIdPreference;

    @Inject
    @Named(AppPrefsConstants.AVATAR)
    StringPreference mAvatarPreference;

    @Inject
    @Named(AppPrefsConstants.NAME)
    StringPreference mProfileNamePreference;

    @Inject
    RealmProvider mRealmProvider;

    @Inject
    MessageRealmRepository mMessageRealmRepository;

    @Inject
    GroupRealmRepository mGroupRealmRepository;

    @Inject
    @Named(AppPrefsConstants.USER_ID)
    LongPreference mUserIdReference;

    public ReplyNotificationReceiver() {
    }

    public static Intent createReplyIntent(Context context, Bundle bundle, int numberOfUsers, int groupId) {
        Intent intent = new Intent(context, ReplyNotificationReceiver.class);
        intent.putExtra(GROUP_ID, groupId);
        intent.putExtra(BUNDLE, bundle);
        intent.putExtra(Constants.GROUP_NR_USERS, numberOfUsers);

        return intent;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        InjectionHelper.getMessagingComponent(context).inject(this);
        CharSequence replyMessage = HandleMessagesService.getReplyMessage(intent);

        Bundle bundle = intent.getBundleExtra(BUNDLE);
        long groupId = bundle.getLong(Constants.GROUP_ID);

        if(replyMessage != null && replyMessage instanceof String) {
            sendMessage(context, (String) replyMessage, (int) groupId);
        }
    }

    private void updateNotificationOnReply(Context context, String replyMessage, int groupId) {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationUtils notificationUtils = BewoplanerApplication.getNotificationUtils();

            Notification.Builder nb = new Notification.Builder(context, context.getString(R.string.default_notification_channel_id))
                    .setSmallIcon(HandleMessagesService.getNotificationIcon())
                    .setColor(ContextCompat.getColor(context, R.color.colorDefaultBright))
                    .setContentTitle(context.getResources().getString(R.string.chat_you_name))
                    .setContentText(replyMessage);

            if(notificationUtils.getManager() != null) {
                notificationUtils.getManager().notify(groupId, nb.build());

                Observable.timer(2, TimeUnit.SECONDS).subscribe(aLong -> notificationUtils.getManager().cancel(groupId));
            }
        } else {
            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);

            NotificationCompat.Builder builder = new NotificationCompat.Builder(context, context.getString(R.string.default_notification_channel_id))
                    .setSmallIcon(HandleMessagesService.getNotificationIcon())
                    .setColor(ContextCompat.getColor(context, R.color.colorDefaultBright))
                    .setContentTitle(context.getResources().getString(R.string.chat_you_name))
                    .setPriority(PRIORITY_MAX)
                    .setDefaults(DEFAULT_ALL)
                    .setContentText(replyMessage);

            notificationManager.notify(groupId, builder.build());
            Observable.timer(2, TimeUnit.SECONDS).subscribe(aLong -> notificationManager.cancel(groupId));
        }
    }

    public void sendMessage(Context context, String replyMessage, int groupId) {
        mChatService.sendMessage(groupId, replyMessage)
                .compose(RxUtils.provideDefaultTransformer())
                .flatMap(new ErrorHandlingResponseConverter<>())
                .subscribe(new Subscriber<MessageResponse>() {
                    @Override
                    public void onCompleted() {
                        updateNotificationOnReply(context, replyMessage, groupId);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Message message = new Message(ChatPresenter.findUniqueRandomId(mRealmProvider, mUserIdPreference.get()),
                                groupId,
                                System.currentTimeMillis() / 1000,
                                replyMessage,
                                null,
                                null,
                                null,
                                null,
                                mUserIdPreference.get(),
                                mProfileNamePreference.get(),
                                mAvatarPreference.get(),
                                Message.Status.FAILED,
                                true,
                                mUserIdPreference.get(),
                                false);
                        storeMessageLocally(message);
                        storeGroupLocally(groupId, message);

                        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                            NotificationUtils notificationUtils = BewoplanerApplication.getNotificationUtils();
                            notificationUtils.getManager().cancel(groupId);
                        } else {
                            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
                            notificationManager.cancel(groupId);
                        }

                        Toast.makeText(context, R.string.error_message_not_sent, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onNext(MessageResponse baseResponse) {
                        Message message = baseResponse.response.message;
                        message.status = Message.Status.DELIVERED;
                        storeMessageLocally(message);
                        storeGroupLocally(groupId, message);
                        Bundle bundle = new Bundle();
                        bundle.putString(Constants.MESSAGE_ID, message.id);
                        bundle.putLong(Constants.GROUP_ID, message.groupId);
                        bundle.putLong(Constants.CREATED_AT, message.createdAt);
                        bundle.putString(Constants.MESSAGE_TEXT, message.message);
                        bundle.putString(Constants.FILE, message.filePath);
                        bundle.putLong(Constants.USER_ID, message.senderId);
                        bundle.putString(Constants.USERNAME, message.senderName);
                        bundle.putString(Constants.USER_AVATAR, message.senderAvatar);
                        Intent intent = new Intent();
                        intent.putExtra(Constants.MESSAGE, bundle);
                        intent.setAction(Constants.NOTIFICATION_BROADCAST);
                        context.sendBroadcast(intent);
                    }
                });
    }

    private void storeGroupLocally(long groupId, Message message) {
        Group group = new Group();
        group.id = groupId;
        group.lastMessage = message;
        mGroupRealmRepository.updateGroupMessage(group, new GroupByIdSpecification(mUserIdPreference.get())).subscribe();
    }

    private void storeMessageLocally(Message message) {
        MessageByIdSpecification messageByIdSpecification = new MessageByIdSpecification(mUserIdPreference.get());
        messageByIdSpecification.setMessageId(message.id);
        mMessageRealmRepository.update(Collections.singletonList(message), messageByIdSpecification)
                .subscribe();
    }
}
