(function (window) {
    'use strict';

    function CallController(call, client, meetingId, hasVideo, callsView) {
        this._call = call;
        this._conference = undefined;
        this._client = client;
        this._user = this._client.user;
        this._meetingId = meetingId;
        this._hasVideo = hasVideo;

        this._callsView = callsView;

        this._time = 0;
        this._timerInterval = undefined;

        this._template = this._callsView.createCallTemplate();

        this._callView = new window.CallView(this._template, {
            handleEndCall: function () {
                this.endCall();
            }.bind(this),
            handleMuteUnmute: function () {
                this.muteUnmute();
            }.bind(this),
            handleBlockUnblockVideo: function (isBlockVideo) {
                this.blockUnblockVideo(isBlockVideo);
            }.bind(this),
        });

        this._init();
    }

    CallController.prototype = {
        /**
         * Init function for Call.
         * Registration callbacks releated with Call.
         */
        _init: function () {
            this._callsView.addCallTemplate(this._template);

            this._callView.showLocalCall(this._call.getRemoteAddress());
            this._callView.setCallTitle();

            this._call.addOnCallConferenceStatusChangedCallback(function (call, isConference, uccpUrl) {
                if (isConference) {
                    this._callView.setConferenceTitle();

                    var uccpConfig = {
                        enabled: true,
                    };

                    if (uccpUrl) {
                        var options = AvayaClientServices.Base.Utils.parseUrl(uccpUrl);

                        var webSocketConfig = new AvayaClientServices.Config.ServerInfo(options.hostname,
                                                                                        options.port,
                                                                                        options.isSecure,
                                                                                        options.path,
                                                                                        options.credentials,
                                                                                        options.query);
                        uccpConfig.networkProviderConfiguration = {
                            webSocketConfig: webSocketConfig
                        }; 
                    }

                    this._conference = new ConferenceController(this._user, call, uccpConfig, this._template, this._hasVideo);
                }
            }.bind(this));

            this._call._addOnCallStateChangedCallback(function () {
				if (this._call.isHeldRemotely()) {
					this._callView.changeCallState('Held Remotely');
				} else {
					this._callView.changeCallState(this._call._callState);
				}
            }.bind(this));

            this._call.addOnCallEstablishedCallback(function (call) {
                this._callView.setCallId(call.getCallId());
                this._callView.showCallControlPanel(call, this._hasVideo);
                this._startTimer();
            }.bind(this));

            this._call.addOnCallFailedCallback(function (call, error) {
                if (error && error.getError()) {
                    this._callView.showCallFailedInformation(error.getError());
                } else {
                    this._callView.showCallFailedInformation();
                }
                this._callsView.removeTemplate(this._template);
            }.bind(this));

            this._call.addOnCallRemoteAlertingCallback(function () {
                this._callView.showRemoteAlerting();
            }.bind(this));

            this._call.addOnCallEndedCallback(function () {
                this._callView.hideCallPanel();
                this._callsView.unlock();
                this._stopTimer();
                this._callsView.removeTemplate(this._template);
            }.bind(this));

            this._call.addOnCallVideoChannelsUpdatedCallback(function (call) {
                console.log("Client: addOnCallVideoChannelsUpdatedCallback called ");
                this._updateVideoStreams(call);
            }.bind(this));

            var recvOnlyVideoModeCapability = this._call.getUpdateVideoModeReceiveOnlyCapability();
            var sendRecvVideoModeCapability = this._call.getUpdateVideoModeSendReceiveCapability();

            // Block capability
            recvOnlyVideoModeCapability.addOnChangedCallback(function(capabilities) {
                var enableBlockVideo = capabilities.isAllowed && !sendRecvVideoModeCapability.isAllowed;
                this._callView.changeBlockBtn(enableBlockVideo);
                this._callView.changeUnblockBtn(!enableBlockVideo);
            }.bind(this));

            this._callView.changeBlockBtn(recvOnlyVideoModeCapability.isAllowed);

            // Unblock/escalate capability
            sendRecvVideoModeCapability.addOnChangedCallback(function(capabilities) {
                var enableUnblockVideo = capabilities.isAllowed && !recvOnlyVideoModeCapability.isAllowed;
                this._callView.changeUnblockBtn(enableUnblockVideo);
                this._callView.changeBlockBtn(!enableUnblockVideo);
            }.bind(this));

            this._callView.changeUnblockBtn(sendRecvVideoModeCapability.isAllowed);
        },

        /**
         * Function used to end a call.
         */
        endCall: function () {
            this._call.end();
        },

        /**
         * Function used to mute/unmute call.
         */
        muteUnmute: function () {
            this._call.addOnCallAudioMuteStatusChangedCallback(function (c, isMuted) {
                this._callView.changeMuteUnmuteBtn(isMuted);
            }.bind(this));

            this._call.getMuteCapability().addOnChangedCallback(function () {
                console.trace("call.getMuteCapability().addOnChangedCallback executed " + this._call.getMuteCapability().isAllowed);
            }.bind(this));

            if (this._call.isAudioMuted() === false) {
                this._call.muteAudio();
            } else {
                this._call.unmuteAudio();
            }
        },

        /**
         * Function used to block/unblock video in call.
         */
        blockUnblockVideo: function (isBlockVideo) {
            if (isBlockVideo) {
                this._call.setVideoMode(AvayaClientServices.Services.Call.VideoMode.RECEIVE_ONLY);
            } else {
                this._call.setVideoMode(AvayaClientServices.Services.Call.VideoMode.SEND_RECEIVE);
            }
        },

        /**
         * Function used to update video stream.
         *
         * @param {Object} call
         * @private
         */
        _updateVideoStreams: function (call) {
            var mediaEngine = this._client.getMediaServices();
            var videoChannels = call.getVideoChannels();
            if (videoChannels[0]) {
                var localStream;
                var remoteStream;
                switch (videoChannels[0].getNegotiatedDirection()) {
                    case AvayaClientServices.Services.Call.MediaDirection.RECV_ONLY:
                        this._callView.setLocalStream(null);
                        remoteStream = mediaEngine.getVideoInterface().getRemoteMediaStream(videoChannels[0].getChannelId());
                        if (AvayaClientServices.Base.Utils.isDefined(remoteStream)) {
                            this._callView.setRemoteStream(remoteStream); 
                        }
                        break;
                    case AvayaClientServices.Services.Call.MediaDirection.SEND_ONLY:
                        localStream = mediaEngine.getVideoInterface().getLocalMediaStream(videoChannels[0].getChannelId());
                        if (AvayaClientServices.Base.Utils.isDefined(localStream)) {
                            this._callView.setLocalStream(localStream); 
                        }
                        this._callView.setRemoteStream(null);
                        break;
                    case AvayaClientServices.Services.Call.MediaDirection.SEND_RECV:
                        localStream = mediaEngine.getVideoInterface().getLocalMediaStream(videoChannels[0].getChannelId());
                        if (AvayaClientServices.Base.Utils.isDefined(localStream)) {
                            this._callView.setLocalStream(localStream); 
                        }
                        remoteStream = mediaEngine.getVideoInterface().getRemoteMediaStream(videoChannels[0].getChannelId());
                        if (AvayaClientServices.Base.Utils.isDefined(remoteStream)) {
                            this._callView.setRemoteStream(remoteStream); 
                        }
                        break;
                    case AvayaClientServices.Services.Call.MediaDirection.INACTIVE:
                    case AvayaClientServices.Services.Call.MediaDirection.DISABLE:
                    default:
                        this._callView.setLocalStream(null);
                        this._callView.setRemoteStream(null);
                        break;
                }
            }
            else {
                this._callView.setLocalStream(null);
                this._callView.setRemoteStream(null);
            }
        },

        _startTimer: function () {
            this._timerInterval = setInterval(function () {
                this._time = this._time + 1;
                this._callView.refreshCallTimer(this._time);
            }.bind(this), 1000);
        },

        _pauseTimer: function () {
            clearInterval(this._timerInterval);
        },

        _stopTimer: function () {
            clearInterval(this._timerInterval);
            this._callView.clearCallTimer();
            this._time = 0;
        }
    };

    window.CallController = CallController;

})(window);
