/* Minification failed. Returning unminified contents.
(39,55-56): run-time warning JS1195: Expected expression: >
(50,18-19): run-time warning JS1195: Expected expression: )
(51,13-14): run-time warning JS1002: Syntax error: }
(57,51-52): run-time warning JS1195: Expected expression: >
(77,13-14): run-time warning JS1002: Syntax error: }
(91,1-2): run-time warning JS1002: Syntax error: }
(94,74-75): run-time warning JS1004: Expected ';': {
(137,71-72): run-time warning JS1195: Expected expression: >
(142,22-23): run-time warning JS1195: Expected expression: )
(145,58-59): run-time warning JS1195: Expected expression: )
(145,61-62): run-time warning JS1195: Expected expression: >
(147,18-19): run-time warning JS1195: Expected expression: )
(148,14-15): run-time warning JS1195: Expected expression: )
(149,10-11): run-time warning JS1195: Expected expression: )
(152,43-44): run-time warning JS1004: Expected ';': {
(310,1-2): run-time warning JS1002: Syntax error: }
(57,13-49): run-time warning JS1018: 'return' statement outside of function: return new Promise((resolve, reject)
(61,21-28): run-time warning JS1018: 'return' statement outside of function: return;
(90,5-30): run-time warning JS1018: 'return' statement outside of function: return _factoryInterface;
(309,5-23): run-time warning JS1018: 'return' statement outside of function: return _interface;
 */
var TwilioMultimediaProviderWidgetFactory = (function() {
    var _factoryInterface = {
        createInstance: function(options) { return null; },
        getFactoryData: function() { if (!_factoryData.isInitialized) { init(); } return _factoryData; },
        scriptSource: document.currentScript.src
    }; 
    
    // initialize factory/one-time data.  done only when first instance is created
    function init() {
        _factoryData.defaultInstanceOptions = {    
            roomName: null,
            token: null,
            userMediaState: null,
            primaryContainer: null,
            secondaryContainer: null,            
            callbacks:  {
                setTitle: function(title) {},
                syncSecondaryVideoDimensions: function() {}
            }
        };

        _factoryData.templateDefinitions = {
            control:
                ''
        };
        
        $.each(_factoryData.templateDefinitions, function (key, templateDefinition) {
            _factoryData.templateInstances[key] = doT.template(templateDefinition);
        });

        _factoryData.isInitialized = true;


        var loadDependencies = function() {
            console.log(TwilioMultimediaProviderWidgetFactory.scriptSource);
            var scriptUrl = new URL(TwilioMultimediaProviderWidgetFactory.scriptSource);
       
            var includeJs = function(url) {
                return new Promise((resolve, reject) => {
                    var jsElement = document.createElement("script");
                    var body = document.getElementsByTagName('BODY')[0];  
                    jsElement.type = "text/javascript";        
                    jsElement.src = url;
                    jsElement.async = true;
                    jsElement.onload = function() {
                        console.log('loaded ' + url);
                        resolve();
                    }        
                    body.appendChild(jsElement);         
                });
            };
                   
            var scripts = [
                '/ext/twilio/video/2.7/twilio-video.min.js'
            ];
               
            return new Promise((resolve, reject) => {
                var twilioAlreadyLoaded = (typeof window.Twilio != 'undefined' && typeof window.Twilio.Video != 'undefined');
                if (twilioAlreadyLoaded) {
                    resolve();
                    return;
                }

                var i = 0;

                var loadNext = function() {
                    if (i >= scripts.length) {
                        resolve();
                    } else {
                        includeJs(scriptUrl.origin  + scripts[i]).then(function() {
                            i++;
                            loadNext();
                        });
                    }
                }
                loadNext();
            });
        };

        _factoryData.loadDependenciesPromise = loadDependencies();
    }

    var _factoryData = {
        isInitialized: false,
        templateDefinitions: {},
        templateInstances: {},
        loadDependenciesPromise: null
    };

    return _factoryInterface;
}());


TwilioMultimediaProviderWidgetFactory.createInstance = function(options) {
    var _interface = {
        setAVEnabled: function (enabledState) { },
        destroy: function() {}  
    };
    
    var _factoryData = this.getFactoryData();
    var _options = $.extend(true, {}, _factoryData.defaultInstanceOptions, options);

    var _video = null;
    var _room = null;

   
    function init() {     
        // load twitter js sdk if it has not already been loaded
        _factoryData.loadDependenciesPromise.then(function() {
            //console.log(window.Twilio.Video);
            
            _video = window.Twilio.Video;            

            _video.connect(_options.token, {
                name: _options.roomName,
                audio: _options.userMediaState.audioEnabled,
                video: _options.userMediaState.videoEnabled,
            }).then(function (room) {
                _room = room;

                syncUserMediaState();

                _room.participants.forEach(function (participant) {
                    syncParticipant(participant);
                });

                _room.on('participantConnected', function (participant) {
                    syncParticipant(participant);
                });

                _room.on('participantDisconnected', function (participant) {
                    // clear out the remote stuff
                    $(_options.primaryContainer).empty();
                });

                _room.on('disconnected', function(room) {
                    room.localParticipant.tracks.forEach(publication => {
                        publication.track.detach();
                        // clear out the local and remote stuff                        
                        $(_options.primaryContainer).empty();
                        $(_options.secondaryContainer).empty();
                    });
                });           

                window.addEventListener('beforeunload', () => {
                   if (_room != null) _room.disconnect()
                });
            });
        });       
    }

    function syncParticipant(participant) {
        participant.tracks.forEach(function (publication) {
            syncPublication(publication);
        });

        participant.on('trackSubscribed', function (track) {
            syncTrack(track);
        });
    }

    function syncPublication(publication) {
        if (publication.isSubscribed) {
            syncTrack(publication.track);
        }

        publication.on('subscribed', function () {
            syncTrack(publication.track);
        });

        publication.on('unsubscribed', function () {
            disableRemoteTrack(publication);
        });
    }

    function syncTrack(track) {
        if (track.isEnabled) {
            enableRemoteTrack(track);
        }

        track.on('enabled', function () {
            enableRemoteTrack(track);
        });

        track.on('disabled', function () {
            disableRemoteTrack(track);
        });
    }

    function enableLocalTrack(track) {
        disableLocalTrack(track);

        $(_options.secondaryContainer)[0].appendChild(track.attach());

        if (track.kind == 'video') {
            $(_options.secondaryContainer).find('video').unbind().on('loadeddata', function (e) {
                //var width = e.target.videoWidth;
                //var height = e.target.videoHeight;
                //console.log('local loaded = width: ' + width + ', height: ' + height);
                //_options.callbacks.setTitle('l2 local = ' + width + ' x ' + height);
                _options.callbacks.syncSecondaryVideoDimensions();
            });

            var onResize = function (e) {
                //var width = e.target.videoWidth;
                //var height = e.target.videoHeight;
                //console.log('local resized = width: ' + width + ', height: ' + height);
                //_options.callbacks.setTitle('r2 local = ' + width + ' x ' + height);
                _options.callbacks.syncSecondaryVideoDimensions();
            };
            if ((_options.secondaryContainer).find('video').length > 0) {
                $(_options.secondaryContainer).find('video')[0].removeEventListener('resize', onResize);
                $(_options.secondaryContainer).find('video')[0].addEventListener('resize', onResize);
            }
        }
    }

    function enableRemoteTrack(track) {
        disableRemoteTrack(track);

        $(_options.primaryContainer)[0].appendChild(track.attach());

        if (track.kind == 'video') {
            $(_options.primaryContainer).find('video').unbind().on('loadeddata', function (e) {
                var width = e.target.clientWidth;
                var height = e.target.clientHeight;
                //console.log('remote loaded = width: ' + width + ', height: ' + height);                
            });

            var onResize = function (e) {
                var width = e.target.videoWidth;
                var height = e.target.videoHeight;
                //console.log('remote resized = width: ' + width + ', height: ' + height);
            };
            if ((_options.primaryContainer).find('video').length > 0) {
                $(_options.primaryContainer).find('video')[0].removeEventListener('resize', onResize);
                $(_options.primaryContainer).find('video')[0].addEventListener('resize', onResize);
            }
        }
    }

    function disableLocalTrack(track) {
        $.each($(_options.secondaryContainer).find(track.kind), function (index, value) {
            $(value).remove();
        });
    }

    function disableRemoteTrack(track) {
        $.each($(_options.primaryContainer).find(track.kind), function (index, value) {
            $(value).remove();
        });
    }

    _interface.setAVEnabled = function (enabledState) {
        _options.userMediaState.audioEnabled = enabledState.audioEnabled;
        _options.userMediaState.videoEnabled = enabledState.videoEnabled;
        syncUserMediaState();
    };

    _interface.destroy = function() {
        if (_room != null) {
            _interface.setAVEnabled({ audioEnabled: false, videoEnabled: false });

            _room.disconnect();
            _room = null;           
        }
    };

    function syncUserMediaState() {
        if (_options.userMediaState.audioEnabled) {
            if (_room.localParticipant.audioTracks.length > 0) {
                return;
            }

            _video.createLocalAudioTrack().then(function (localTrack) {
                _room.localParticipant.publishTrack(localTrack);
            });
        } else {
            _room.localParticipant.audioTracks.forEach(function (publication) {                
                disableLocalTrack(publication.track);

                // do this so your mic turns off properly
                publication.track.stop();
                publication.unpublish();
            });
        }

        if (_options.userMediaState.videoEnabled) {
            if (_room.localParticipant.videoTracks.length > 0) {
                return;
            }

            _video.createLocalVideoTrack().then(function (localTrack) {
                _room.localParticipant.publishTrack(localTrack);
                enableLocalTrack(localTrack);
            });
        } else {
            _room.localParticipant.videoTracks.forEach(function (publication) {
                disableLocalTrack(publication.track);

                // do this so your camera turns off properly
                publication.track.stop();
                publication.unpublish();
            });
        }
    }
   
    init();
    return _interface;
}
;
