/*
 *  Copyright (C) 2004-2020 Savoir-faire Linux Inc.
 *
 *  Author: Hadrien De Sousa <hadrien.desousa@savoirfairelinux.com>
 *  Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package cx.ring.call;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

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

import cx.ring.facades.ConversationFacade;
import cx.ring.model.Conference;
import cx.ring.model.Conversation;
import cx.ring.model.SipCall;
import cx.ring.model.Uri;
import cx.ring.mvp.RootPresenter;
import cx.ring.services.AccountService;
import cx.ring.services.CallService;
import cx.ring.services.ContactService;
import cx.ring.services.DeviceRuntimeService;
import cx.ring.services.HardwareService;
import cx.ring.services.PreferencesService;
import cx.ring.utils.Log;
import cx.ring.utils.StringUtils;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.Scheduler;
import io.reactivex.disposables.Disposable;
import io.reactivex.subjects.BehaviorSubject;
import io.reactivex.subjects.Subject;

import static cx.ring.daemon.Ringservice.listCallMediaHandlers;

public class CallPresenter extends RootPresenter<CallView> {

    public final static String TAG = CallPresenter.class.getSimpleName();

    private AccountService mAccountService;
    private ContactService mContactService;
    private HardwareService mHardwareService;
    private CallService mCallService;
    private DeviceRuntimeService mDeviceRuntimeService;
    private ConversationFacade mConversationFacade;

    private Conference mConference;
    private final List<SipCall> mPendingCalls = new ArrayList<>();
    private final Subject<List<SipCall>> mPendingSubject = BehaviorSubject.createDefault(mPendingCalls);
    private final PreferencesService mPreferencesService;

    private boolean mOnGoingCall = false;
    private boolean mAudioOnly = true;
    private boolean permissionChanged = false;
    private boolean pipIsActive = false;
    private boolean incomingIsFullIntent = true;
    private boolean callInitialized = false;

    private int videoWidth = -1;
    private int videoHeight = -1;
    private int previewWidth = -1;
    private int previewHeight = -1;
    private String currentSurfaceId = null;
    private String currentPluginSurfaceId = null;

    private Disposable timeUpdateTask = null;

    @Inject
    @Named("UiScheduler")
    protected Scheduler mUiScheduler;

    @Inject
    public CallPresenter(AccountService accountService,
                         ContactService contactService,
                         HardwareService hardwareService,
                         CallService callService,
                         DeviceRuntimeService deviceRuntimeService,
                         ConversationFacade conversationFacade,
                         PreferencesService preferencesService) {
        mAccountService = accountService;
        mContactService = contactService;
        mHardwareService = hardwareService;
        mCallService = callService;
        mDeviceRuntimeService = deviceRuntimeService;
        mConversationFacade = conversationFacade;
        mPreferencesService = preferencesService;
    }

    public void cameraPermissionChanged(boolean isGranted) {
        if (isGranted && mHardwareService.isVideoAvailable()) {
            mHardwareService.initVideo()
                    .onErrorComplete()
                    .blockingAwait();
            permissionChanged = true;
        }
    }

    public void audioPermissionChanged(boolean isGranted) {
        if (isGranted && mHardwareService.hasMicrophone()) {
            mCallService.restartAudioLayer();
        }
    }


    @Override
    public void unbindView() {
        if (!mAudioOnly) {
            mHardwareService.endCapture();
        }
        super.unbindView();
    }

    @Override
    public void bindView(CallView view) {
        super.bindView(view);
        /*mCompositeDisposable.add(mAccountService.getRegisteredNames()
                .observeOn(mUiScheduler)
                .subscribe(r -> {
                    if (mSipCall != null && mSipCall.getContact() != null) {
                        getView().updateContactBubble(mSipCall.getContact());
                    }
                }));*/
        mCompositeDisposable.add(mHardwareService.getVideoEvents()
                .observeOn(mUiScheduler)
                .subscribe(this::onVideoEvent));
        mCompositeDisposable.add(mHardwareService.getAudioState()
                .observeOn(mUiScheduler)
                .subscribe(state -> getView().updateAudioState(state)));

        /*mCompositeDisposable.add(mHardwareService
                .getBluetoothEvents()
                .subscribe(event -> {
                    if (!event.connected && mSipCall == null) {
                        hangupCall();
                    }
                }));*/
    }

    public void initOutGoing(String accountId, String contactRingId, boolean audioOnly) {
        if (accountId == null || contactRingId == null) {
            Log.e(TAG, "initOutGoing: null account or contact");
            hangupCall();
            return;
        }
        if (!mHardwareService.hasCamera()) {
            audioOnly = true;
        }
        //getView().blockScreenRotation();

        Observable<Conference> callObservable = mCallService
                .placeCall(accountId, StringUtils.toNumber(contactRingId), audioOnly)
                //.map(mCallService::getConference)
                .flatMapObservable(call -> mCallService.getConfUpdates(call))
                .share();

        mCompositeDisposable.add(callObservable
                .observeOn(mUiScheduler)
                .subscribe(conference -> {
                    contactUpdate(conference);
                    confUpdate(conference);
                }, e -> {
                    hangupCall();
                    Log.e(TAG, "Error with initOutgoing: " + e.getMessage());
                }));

        showConference(callObservable);
    }

    /**
     * Returns to or starts an incoming call
     *
     * @param confId         the call id
     * @param actionViewOnly true if only returning to call or if using full screen intent
     */
    public void initIncomingCall(String confId, boolean actionViewOnly) {
        //getView().blockScreenRotation();

        // if the call is incoming through a full intent, this allows the incoming call to display
        incomingIsFullIntent = actionViewOnly;

        Observable<Conference> callObservable = mCallService.getConfUpdates(confId)
                .observeOn(mUiScheduler)
                .share();

        // Handles the case where the call has been accepted, emits a single so as to only check for permissions and start the call once
        mCompositeDisposable.add(callObservable
                .firstOrError()
                .subscribe(call -> {
                    if (!actionViewOnly) {
                        contactUpdate(call);
                        confUpdate(call);
                        callInitialized = true;
                        getView().prepareCall(true);
                    }
                }, e -> {
                    hangupCall();
                    Log.e(TAG, "Error with initIncoming, preparing call flow :" , e);
                }));

        // Handles retrieving call updates. Items emitted are only used if call is already in process or if user is returning to a call.
        mCompositeDisposable.add(callObservable
                .subscribe(call -> {
                    if (callInitialized || actionViewOnly) {
                        contactUpdate(call);
                        confUpdate(call);
                    }
                }, e -> {
                    hangupCall();
                    Log.e(TAG, "Error with initIncoming, action view flow: ", e);
                }));

        showConference(callObservable);
    }

    private void showConference(Observable<Conference> conference) {
        mCompositeDisposable.add(conference
                .distinctUntilChanged()
                .switchMap(Conference::getParticipantInfo)
                .observeOn(mUiScheduler)
                .subscribe(info -> getView().updateConfInfo(info),
                        e -> Log.e(TAG, "Error with initIncoming, action view flow: ", e)));
    }

    public void prepareOptionMenu() {
        boolean isSpeakerOn = mHardwareService.isSpeakerPhoneOn();
        //boolean hasContact = mSipCall != null && null != mSipCall.getContact() && mSipCall.getContact().isUnknown();
        boolean canDial = mOnGoingCall && mConference != null;
        // get the preferences
        boolean displayPluginsButton = getView().displayPluginsButton();
        boolean showPluginBtn = displayPluginsButton && mOnGoingCall && mConference != null;
        boolean hasMultipleCamera = mHardwareService.getCameraCount() > 1 && mOnGoingCall && !mAudioOnly;
        getView().initMenu(isSpeakerOn, hasMultipleCamera, canDial, showPluginBtn, mOnGoingCall);
    }

    public void chatClick() {
        if (mConference == null || mConference.getParticipants().isEmpty()) {
            return;
        }
        SipCall firstCall = mConference.getParticipants().get(0);
        if (firstCall == null
                || firstCall.getContact() == null
                || firstCall.getContact().getIds() == null
                || firstCall.getContact().getIds().isEmpty()) {
            return;
        }
        getView().goToConversation(firstCall.getAccount(), firstCall.getContact().getIds().get(0));
    }

    public void speakerClick(boolean checked) {
        mHardwareService.toggleSpeakerphone(checked);
    }

    public void muteMicrophoneToggled(boolean checked) {
        mCallService.setMuted(checked);
    }


    public boolean isMicrophoneMuted() {
        return mCallService.isCaptureMuted();
    }

    public void switchVideoInputClick() {
        if(mConference == null)
            return;
        mHardwareService.switchInput(mConference.getId(), false);
        getView().switchCameraIcon(mHardwareService.isPreviewFromFrontCamera());
    }

    public void configurationChanged(int rotation) {
        mHardwareService.setDeviceOrientation(rotation);
    }

    public void dialpadClick() {
        getView().displayDialPadKeyboard();
    }

    public void acceptCall() {
        if (mConference == null) {
            return;
        }
        mCallService.accept(mConference.getId());
    }

    public void hangupCall() {
        List<String> callMediaHandlers = listCallMediaHandlers();

        for (String callMediaHandler : callMediaHandlers)
        {
            toggleCallMediaHandler(callMediaHandler, false);
        }

        if (mConference != null) {
            if (mConference.isConference())
                mCallService.hangUpConference(mConference.getId());
            else
                mCallService.hangUp(mConference.getId());
        }
        for (SipCall call : mPendingCalls) {
            mCallService.hangUp(call.getDaemonIdString());
        }
        finish();
    }

    public void refuseCall() {
        final Conference call = mConference;
        if (call != null) {
            mCallService.refuse(call.getId());
        }
        finish();
    }

    public void videoSurfaceCreated(Object holder) {
        if (mConference == null) {
            return;
        }
        String newId = mConference.getId();
        if (!newId.equals(currentSurfaceId)) {
            mHardwareService.removeVideoSurface(currentSurfaceId);
            currentSurfaceId = newId;
        }
        mHardwareService.addVideoSurface(mConference.getId(), holder);
        getView().displayContactBubble(false);
    }

    public void videoSurfaceUpdateId(String newId) {
        if (!Objects.equals(newId, currentSurfaceId)) {
            mHardwareService.updateVideoSurfaceId(currentSurfaceId, newId);
            currentSurfaceId = newId;
        }
    }

    public void pluginSurfaceCreated(Object holder) {
        if (mConference == null) {
            return;
        }
        String newId = mConference.getPluginId();
        if (!newId.equals(currentPluginSurfaceId)) {
            mHardwareService.removeVideoSurface(currentPluginSurfaceId);
            currentPluginSurfaceId = newId;
        }
        mHardwareService.addVideoSurface(mConference.getPluginId(), holder);
        getView().displayContactBubble(false);
    }

    public void pluginSurfaceUpdateId(String newId) {
        if (!Objects.equals(newId, currentPluginSurfaceId)) {
            mHardwareService.updateVideoSurfaceId(currentPluginSurfaceId, newId);
            currentPluginSurfaceId = newId;
        }
    }

    public void previewVideoSurfaceCreated(Object holder) {
        mHardwareService.addPreviewVideoSurface(holder, mConference);
        //mHardwareService.startCapture(null);
    }

    public void videoSurfaceDestroyed() {
        if (currentSurfaceId != null) {
            mHardwareService.removeVideoSurface(currentSurfaceId);
            currentSurfaceId = null;
        }
    }
    public void pluginSurfaceDestroyed() {
        if (currentPluginSurfaceId != null) {
            mHardwareService.removeVideoSurface(currentPluginSurfaceId);
            currentPluginSurfaceId = null;
        }
    }
    public void previewVideoSurfaceDestroyed() {
        mHardwareService.removePreviewVideoSurface();
        mHardwareService.endCapture();
    }

    public void displayChanged() {
        mHardwareService.switchInput(mConference.getId(), false);
    }

    public void layoutChanged() {
        //getView().resetVideoSize(videoWidth, videoHeight, previewWidth, previewHeight);
    }


    public void uiVisibilityChanged(boolean displayed) {
        CallView view = getView();
        if (view != null)
            view.displayHangupButton(mOnGoingCall && displayed);
    }

    private void finish() {
        if (timeUpdateTask != null && !timeUpdateTask.isDisposed()) {
            timeUpdateTask.dispose();
            timeUpdateTask = null;
        }
        mConference = null;
        CallView view = getView();
        if (view != null)
            view.finish();
    }

    private Disposable contactDisposable = null;

    private void contactUpdate(final Conference conference) {
        if (mConference != conference) {
            mConference = conference;
            if (contactDisposable != null && !contactDisposable.isDisposed()) {
                contactDisposable.dispose();
            }
            if (conference.getParticipants().isEmpty())
                return;

            // Updates of participant (and  pending participant) list
            Observable<List<SipCall>> callsObservable = mPendingSubject
                    .map(pendingList -> {
                        Log.w(TAG, "mPendingSubject onNext " + pendingList.size() + " " + conference.getParticipants().size());
                        if (pendingList.isEmpty())
                            return conference.getParticipants();
                        List<SipCall> newList = new ArrayList<>(conference.getParticipants().size() + pendingList.size());
                        newList.addAll(conference.getParticipants());
                        newList.addAll(pendingList);
                        return newList;
                    });

            // Updates of individual contacts
            Observable<List<Observable<SipCall>>> contactsObservable = callsObservable
                    .flatMapSingle(calls -> Observable
                            .fromIterable(calls)
                            .map(call -> mContactService.observeContact(call.getAccount(), call.getContact(), false)
                                    .map(contact -> call))
                            .toList(calls.size()));

            // Combined updates of contacts as participant list updates
            Observable<List<SipCall>> contactUpdates = contactsObservable
                    .switchMap(list -> Observable
                            .combineLatest(list, objects -> {
                                Log.w(TAG, "flatMapObservable " + objects.length);
                                ArrayList<SipCall> calls = new ArrayList<>(objects.length);
                                for (Object call : objects)
                                    calls.add((SipCall)call);
                                return (List<SipCall>)calls;
                            }))
                    .filter(list -> !list.isEmpty());

            contactDisposable = contactUpdates
                    .observeOn(mUiScheduler)
                    .subscribe(cs -> getView().updateContactBubble(cs), e -> Log.e(TAG, "Error updating contact data", e));
            mCompositeDisposable.add(contactDisposable);
        }
        mPendingSubject.onNext(mPendingCalls);
    }

    private void confUpdate(Conference call) {
        Log.w(TAG, "confUpdate " + call.getId());

        mConference = call;
        SipCall.CallStatus status = mConference.getState();
        if (status == SipCall.CallStatus.HOLD && mCallService.getConferenceList().size() == 1) {
            mCallService.unhold(mConference.getId());
        }
        mAudioOnly = !call.hasVideo();
        CallView view = getView();
        if (view == null)
            return;
        view.updateMenu();
        if (call.isOnGoing()) {
            mOnGoingCall = true;
            view.initNormalStateDisplay(mAudioOnly, isMicrophoneMuted());
            view.updateMenu();
            if (!mAudioOnly) {
                mHardwareService.setPreviewSettings();
                mHardwareService.updatePreviewVideoSurface(mConference);
                videoSurfaceUpdateId(call.getId());
                pluginSurfaceUpdateId(call.getPluginId());
                view.displayVideoSurface(true, mDeviceRuntimeService.hasVideoPermission());
                if (permissionChanged) {
                    mHardwareService.switchInput(mConference.getId(), permissionChanged);
                    permissionChanged = false;
                }
            }
            if (timeUpdateTask != null)
                timeUpdateTask.dispose();
            timeUpdateTask = mUiScheduler.schedulePeriodicallyDirect(this::updateTime, 0, 1, TimeUnit.SECONDS);
        } else if (call.isRinging()) {
            SipCall scall = call.getCall();

            view.handleCallWakelock(mAudioOnly);
            if (scall.isIncoming()) {
                if (mAccountService.getAccount(scall.getAccount()).isAutoanswerEnabled()) {
                    mCallService.accept(scall.getDaemonIdString());
                    // only display the incoming call screen if the notification is a full screen intent
                } else if (incomingIsFullIntent) {
                    view.initIncomingCallDisplay();
                }
            } else {
                mOnGoingCall = false;
                view.updateCallStatus(scall.getCallStatus());
                view.initOutGoingCallDisplay();
            }
        } else {
            finish();
        }
    }

    public void maximizeParticipant(SipCall call) {
        if (mConference.getMaximizedCall() == call)
            call = null;
        mConference.setMaximizedCall(call);
        if (call != null) {
            mCallService.setConfMaximizedParticipant(mConference.getConfId(), call.getDaemonIdString());
        } else {
            mCallService.setConfGridLayout(mConference.getConfId());
        }
    }

    private void updateTime() {
        CallView view = getView();
        if (view != null && mConference != null) {
            if (mConference.isOnGoing()) {
                long start = mConference.getTimestampStart();
                if (start != Long.MAX_VALUE) {
                    view.updateTime((System.currentTimeMillis() - start) / 1000);
                } else {
                    view.updateTime(-1);
                }
            }
        }
    }

    private void onVideoEvent(HardwareService.VideoEvent event) {
        Log.d(TAG, "VIDEO_EVENT: " + event.start + " " + event.callId + " " + event.w + "x" + event.h);

        if (event.start) {
            getView().displayVideoSurface(true, !isPipMode() && mDeviceRuntimeService.hasVideoPermission());
        } else if (mConference != null && mConference.getId().equals(event.callId)) {
            getView().displayVideoSurface(event.started, event.started && !isPipMode() && mDeviceRuntimeService.hasVideoPermission());
            if (event.started) {
                videoWidth = event.w;
                videoHeight = event.h;
                getView().resetVideoSize(videoWidth, videoHeight);
            }
        } else if (event.callId == null) {
            if (event.started) {
                previewWidth = event.w;
                previewHeight = event.h;
                getView().resetPreviewVideoSize(previewWidth, previewHeight, event.rot);
            }
        }
        if (mConference != null && mConference.getPluginId().equals(event.callId)) {
            if (event.started) {
                previewWidth = event.w;
                previewHeight = event.h;
                getView().resetPluginPreviewVideoSize(previewWidth, previewHeight, event.rot);
            }
        }
        /*if (event.started || event.start) {
            getView().resetVideoSize(videoWidth, videoHeight, previewWidth, previewHeight);
        }*/
    }

    public void positiveButtonClicked() {
        if (mConference.isRinging() && mConference.isIncoming()) {
            acceptCall();
        } else {
            hangupCall();
        }
    }

    public void negativeButtonClicked() {
        if (mConference.isRinging() && mConference.isIncoming()) {
            refuseCall();
        } else {
            hangupCall();
        }
    }

    public void toggleButtonClicked() {
        if (mConference != null && !(mConference.isRinging() && mConference.isIncoming())) {
            hangupCall();
        }
    }

    public boolean isAudioOnly() {
        return mAudioOnly;
    }

    public void requestPipMode() {
        if (mConference != null && mConference.isOnGoing() && mConference.hasVideo()) {
            getView().enterPipMode(mConference.getId());
        }
    }

    public boolean isPipMode() {
        return pipIsActive;
    }

    public void pipModeChanged(boolean pip) {
        pipIsActive = pip;
        if (pip) {
            getView().displayHangupButton(false);
            getView().displayPreviewSurface(false);
            getView().displayVideoSurface(true, false);
        } else {
            getView().displayPreviewSurface(true);
            getView().displayVideoSurface(true, mDeviceRuntimeService.hasVideoPermission());
        }
    }

    public void toggleCallMediaHandler(String id, boolean toggle)
    {
        if (mConference != null && mConference.isOnGoing() && mConference.hasVideo()) {
            getView().toggleCallMediaHandler(id, mConference.getId(), toggle);
        }
    }

    public boolean isSpeakerphoneOn() {
        return mHardwareService.isSpeakerPhoneOn();
    }

    public void sendDtmf(CharSequence s) {
        mCallService.playDtmf(s.toString());
    }

    public void addConferenceParticipant(String accountId, String contactId) {
        mCompositeDisposable.add(mConversationFacade.startConversation(accountId, new Uri(contactId))
                .map(Conversation::getCurrentCalls)
                .subscribe(confs -> {
                    if (confs.isEmpty()) {
                        final Observer<SipCall> pendingObserver = new Observer<SipCall>() {
                            private SipCall call = null;
                            @Override
                            public void onSubscribe(Disposable d) {}

                            @Override
                            public void onNext(SipCall sipCall) {
                                if (call == null) {
                                    call = sipCall;
                                    mPendingCalls.add(sipCall);
                                }
                                mPendingSubject.onNext(mPendingCalls);
                            }

                            @Override
                            public void onError(Throwable e) {}

                            @Override
                            public void onComplete() {
                                if (call != null) {
                                    mPendingCalls.remove(call);
                                    mPendingSubject.onNext(mPendingCalls);
                                    call = null;
                                }
                            }
                        };

                        // Place new call, join to conference when answered
                        Maybe<SipCall> newCall = mCallService.placeCallObservable(accountId, contactId, mAudioOnly)
                                .doOnEach(pendingObserver)
                                .filter(SipCall::isOnGoing)
                                .firstElement()
                                .delay(1, TimeUnit.SECONDS)
                                .doOnEvent((v, e) -> pendingObserver.onComplete());
                        mCompositeDisposable.add(newCall.subscribe(call ->  {
                            String id = mConference.getId();
                            if (mConference.isConference()) {
                                mCallService.addParticipant(call.getDaemonIdString(), id);
                            } else {
                                mCallService.joinParticipant(id, call.getDaemonIdString()).subscribe();
                            }
                        }));
                    } else {
                        // Selected contact already in call or conference, join it to current conference
                        Conference selectedConf = confs.get(0);
                        if (selectedConf != mConference) {
                            if (mConference.isConference()) {
                                if (selectedConf.isConference())
                                    mCallService.joinConference(mConference.getId(), selectedConf.getId());
                                else
                                    mCallService.addParticipant(selectedConf.getId(), mConference.getId());
                            } else {
                                if (selectedConf.isConference())
                                    mCallService.addParticipant(mConference.getId(), selectedConf.getId());
                                else
                                    mCallService.joinParticipant(mConference.getId(), selectedConf.getId()).subscribe();
                            }
                        }
                    }
                }));
    }

    public void startAddParticipant() {
        getView().startAddParticipant(mConference.getId());
    }

    public void hangupParticipant(SipCall call) {
        mCallService.hangUp(call.getDaemonIdString());
    }

    public void openParticipantContact(SipCall call) {
        getView().goToContact(call.getAccount(), call.getContact());
    }

    public void stopCapture() {
        mHardwareService.stopCapture();
    }

    public boolean startScreenShare(Object mediaProjection) {
        return mHardwareService.startScreenShare(mediaProjection);
    }

    public void stopScreenShare() {
        mHardwareService.stopScreenShare();
    }

    public boolean isMaximized(SipCall call) {
        return mConference.getMaximizedCall() == call;
    }

    public void startPlugin(String mediaHandlerId) {
        mHardwareService.startMediaHandler(mediaHandlerId);
        if(mConference == null)
            return;
        mHardwareService.switchInput(mConference.getId(), mHardwareService.isPreviewFromFrontCamera());
    }

    public void stopPlugin() {
        mHardwareService.stopMediaHandler();
        if(mConference == null)
            return;
        mHardwareService.switchInput(mConference.getId(), mHardwareService.isPreviewFromFrontCamera());
    }

    public boolean setBlockRecordStatus(){
        return mPreferencesService.getSettings().isRecordingBlocked();
    }

}
