package com.p3.bewoplaner.data.firebase;

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

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
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 com.p3.bewoplaner.utils.Constants.GROUP_ID;

/**
 * Created by laszloffiferenc on 3/20/17.
 */
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) {
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                .setSmallIcon(HandleMessagesService.getNotificationIcon())
                .setColor(ContextCompat.getColor(context, R.color.colorDefaultBright))
                .setContentTitle(context.getResources().getString(R.string.chat_you_name))
                .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);

                        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();
    }
}
