var model = null;

// Protocol helper functions
function getHttpProtocol() {
  return window.location.protocol === 'https:' ? 'https://' : 'http://';
}

function getWsProtocol() {
  return window.location.protocol === 'https:' ? 'wss://' : 'ws://';
}

$('#toggleLeft').on('click', function() {
	if($(this).hasClass('on')) {
            $(this).removeClass('on');
            $('#main').css('margin-left', '0px');
            $('#main').css('width', '100%');
            $('#left').hide();
	}else{
            $(this).addClass('on');
            $('#main').css('margin-left', '201px');
            $('#main').css('width', 'calc(100% - 201px)');
            $('#left').show();
	}
});

function setAspectRatio(){
    var outer = $('.viewerwrap');
	var box = $('.box');
	var previewHeader = $('.previewheader')

	outer.css('height', 'calc(100vh - 81px)');
	
    if (outer.height() > outer.width() * 0.5625) {
		previewHeader.css({'width': outer.width()});
        box.css({'width': '100%'});
        box.css({'height': box.width() * 0.5625});

    } else {
		previewHeader.css({'width': outer.width()});
        box.css({'height': '100%'});
        box.css({'width': box.height() / 0.5625});
    }
}

$(function() {

    setAspectRatio();

    $(window).resize(function() {
        setAspectRatio();
    })
	
	/*setTimeout(
	function() {
    	if($('.sourceselect option').size() > 1) {
			$('.sourceselect option:eq(1)').attr('selected', 'selected');
    	}
	}, 1500);*/
    
});


function MRRemoteModel() {
	var self = this;
	
	self.sources = ko.observableArray();
	self.destinations = ko.observableArray();
	self.viewers = ko.observableArray();
	self.numberOfViewersSelected = ko.observable(0);
	
	self.canGangStop = ko.computed(function() {
		for (var i = 0; i < self.viewers().length; i++) {
			if (self.viewers()[i].selectedSource() && self.viewers()[i].selectedSource().isRecording()) {
				return true;
			}
		}
		return false;
	}, self);
	self.canGangPause = ko.computed(function() {
		for (var i = 0; i < self.viewers().length; i++) {
			if (self.viewers()[i].selectedSource() &&
				self.viewers()[i].selectedSource().isRecording() &&
				self.viewers()[i].selectedSource().isPaused() === false) {
				return true;
			}
		}
		return false;
	}, self);
	self.canGangRecord = ko.computed(function() {
		for (var i = 0; i < self.viewers().length; i++) {
			if (self.viewers()[i].selectedSource() &&
				(self.viewers()[i].selectedSource().isRecording() === false ||
				 self.viewers()[i].selectedSource().isPaused() === true)) {
				return true;
			}
		}
		return false;
	}, self);
}

function Viewer() {
	var self = this;
	
	self.selectedSource = ko.observable(null);
	self.isSelected = ko.observable(false);
	self.previewImage = null;
	self.shouldDraw = false;
	self.shouldFetch = false;
	self.animationRequestID = null;
	self.context = null;
	
	self.isRecording = ko.computed(function() {
		return (self.selectedSource() && self.selectedSource().isRecording);
	});
	self.selectViewer = function() {
		if (self.selectedSource()) {
			self.isSelected(!self.isSelected());
			if (self.isSelected()) {
				model.numberOfViewersSelected(model.numberOfViewersSelected() + 1);
			} else {
				model.numberOfViewersSelected(model.numberOfViewersSelected() - 1);
			}
		}
	}
	self.drawPreview = function() {
		if (self.shouldDraw) {
			var leftOffset = (214 - self.previewImage.width / 2) / 2;
			self.context.clearRect(0, 0, 852, 480);
			self.context.drawImage(self.previewImage, leftOffset, 0, self.previewImage.width * 2.0, self.previewImage.height * 2.0);
			self.shouldDraw = false;
			self.shouldFetch = true;
		}
		
		self.animationRequestID = window.requestAnimationFrame(self.drawPreview);
	}
	self.startPreview = function() {
		var canvas = $('canvas')[model.viewers.indexOf(self)];
		self.context = canvas.getContext('2d');
		var devicePixelRatio = window.devicePixelRatio || 1,
			backingStoreRatio = self.context.webkitBackingStorePixelRatio ||
			self.context.mozBackingStorePixelRatio ||
			self.context.msBackingStorePixelRatio ||
			self.context.oBackingStorePixelRatio ||
			self.context.backingStorePixelRatio || 1,
			ratio = devicePixelRatio / backingStoreRatio,
			oldWidth = 852,
			oldHeight = 480;
		canvas.width = oldWidth * ratio;
		canvas.height = oldHeight * ratio;
		canvas.style.width = "100%";
		self.context.scale(ratio, ratio);
		self.animationRequestID = requestAnimationFrame(self.drawPreview);
		self.shouldFetch = true;
	}
	self.stopPreview = function() {
		cancelAnimationFrame(self.animationRequestID);
		self.animationRequestID = null;
		self.previewImage = null;
		self.shouldFetch = false;
		self.context.clearRect(0, 0, 852, 480);
	}
	self.selectedSource.subscribe(function(oldValue) {
		if (oldValue) {
			self.stopPreview();
		}
	}, null, "beforeChange");
	self.selectedSource.subscribe(function(newValue) {
		if (newValue) {
			for (var i = 0; i < model.viewers().length; i++) {
				if (model.viewers()[i] != self && model.viewers()[i].selectedSource() == newValue) {
					model.viewers()[i].selectedSource(null);
				}
			}
			self.startPreview();
		}
	});
}

function Source(inData) {
	var self = this;
	self.uniqueID = inData.unique_id;
	self.displayName = ko.observable(inData.display_name);
	self.deviceName = inData.device_name;
	self.videoFormat = ko.observable(inData.video_format);
	self.isRecording = ko.observable(inData.is_recording);
	self.isPaused = ko.observable(inData.is_paused);
	self.lastWarning = ko.observable(null);
	self.selectedDestinations = ko.observableArray(inData.selected_destinations);
	
	self.description = ko.computed(function() {
		return self.deviceName + " (" + self.videoFormat() + ")";
	});
	self.selectedDestinationsLabel = ko.computed(function() {
		if (self.selectedDestinations().length) {
			for(var i = 0; i < model.destinations().length; i++) {
				var destination = model.destinations()[i];
				for(var j = 0; j < self.selectedDestinations().length; j++) {
					if (destination.uniqueID === self.selectedDestinations()[j]) {
						return destination.name;
					}
				}
			}
		}
		return "Destinations...";
	});
	self.hasWarning = ko.computed(function() {
		return (self.lastWarning() != null) ? true : false;
	});
}

function Destination(inData) {
	var self = this;
	self.uniqueID = inData.unique_id;
	self.name = inData.name;
	self.path = inData.path;
}

model = new MRRemoteModel();

function fetchPreview() {
	for (var i = 0; i < model.viewers().length; i++) {
		var viewer = model.viewers()[i];
		if (viewer.shouldFetch) {
			viewer.shouldFetch = false;
			viewer.previewImage = new Image();
			viewer.previewImage.onload = function(loadedViewer) {
				return function() {
					if (loadedViewer.selectedSource()) {
						if (loadedViewer.previewImage.width) {
							loadedViewer.shouldDraw = true;
						} else {
							loadedViewer.shouldFetch = true;
						}
					}
				}
			}(viewer);
			viewer.previewImage.src = '/sources/'+encodeURIComponent(viewer.selectedSource().uniqueID)+'/thumbnail?time='+Date.now();
		}
	}
	
	window.setTimeout(fetchPreview, 1000/30);
}

function updateViewerInfo(index) {
	if (index == model.viewers().length) {
		window.setTimeout(updateViewersInfo, 1000/60);
	} else {
		var source = model.viewers()[index].selectedSource();
		if (source) {
			$.getJSON('/sources/'+encodeURIComponent(source.uniqueID)+'/info', function(data) {
				var canvaswrap = $('.canvaswrap').eq(index);
				var vuMeters = canvaswrap.find('.vuMeterOverlay');
				for (var i = 0; i < 8; i++) {
					var height = 100;
					if (i < data.vu_meter_levels.length) {
						height = (1 - data.vu_meter_levels[i]) * 100;
					}
					vuMeters.eq(i).animate({height: height+"%"}, {duration: 1});
				}
				canvaswrap.find('.timecode').eq(0).text(data.timecode);
				source.isRecording(data.is_recording);
				source.isPaused(data.is_paused);
				source.lastWarning((data.last_warning) ? data.last_warning : null);
			}).always(function() {
				updateViewerInfo(index + 1);
			});
		} else {
			updateViewerInfo(index + 1);
		}
	}
}

function updateViewersInfo() {
	updateViewerInfo(0);
}

updateViewersInfo();

$('#destinationlist').hide();

$('#topmenu').on("click", "div", function() {
	if ($(this).hasClass('selected') === false) {
		$('#topmenu div').toggleClass('selected');
		$('#sourcelist, #destinationlist').toggle();
	}
});

$('#bottom').on("click", ".stopButton", function() {
	for (var i = 0; i < model.viewers().length; i++) {
		var source = model.viewers()[i].selectedSource();
		if (source && source.isRecording()) {
			$.ajax('/sources/' + encodeURIComponent(source.uniqueID) + '/stop');
		}
	}
}).on("click", ".recordButton", function() {
	for (var i = 0; i < model.viewers().length; i++) {
	 var source = model.viewers()[i].selectedSource();
	 if (source && (source.isRecording() === false || source.isPaused())) {
		 var action = source.isPaused() ? 'resume' : 'record';
		 $.ajax('/sources/' + encodeURIComponent(source.uniqueID) + '/' + action);
	 }
 }
}).on("click", ".pauseButton", function() {
	for (var i = 0; i < model.viewers().length; i++) {
	 var source = model.viewers()[i].selectedSource();
	 if (source && source.isRecording() && source.isPaused() === false) {
		 $.ajax('/sources/' + encodeURIComponent(source.uniqueID) + '/pause');
	 }
 }
}).on("click", ".timerButton", function() {
	var offset = $(this).offset();
	var timerPopOver = $("#timerPopOver");
	timerPopOver.css('left', 'calc('+offset.left+'px + 12px - '+(timerPopOver.outerWidth() / 2)+'px)').css('top', 'calc('+offset.top+'px - '+timerPopOver.outerHeight()+'px - 14px)').show();
});

$('#timerPopOver').on("click", ".apply", function() {
	if ($('#timerDuration:checked').val()) {
		var duration = $('#duration').val().split(':');
		// Calculate the total duration (in seconds)
		var totalDuration = parseInt(duration[0], 10) * 3600 + parseInt(duration[1], 10) * 60;
		for (var i = 0; i < model.viewers().length; i++) {
			var source = model.viewers()[i].selectedSource();
			if (source) {
				$.ajax('/sources/' + encodeURIComponent(source.uniqueID) + '/record?duration=' + totalDuration);
			}
		}
		$('#timerPopOver').hide();
	} else if ($('#timerDate:checked').val()) {
		var endDateAsString = $('#endDate').val();
		if (endDateAsString.length) {
			var endDate = new Date(endDateAsString);
			for (var i = 0; i < model.viewers().length; i++) {
				var source = model.viewers()[i].selectedSource();
				if (source) {
					$.ajax('/sources/' + encodeURIComponent(source.uniqueID) + '/record?end_date=' + endDate.toJSON());
				}
			}
			$('#timerPopOver').hide();
		}
	}
}).on("click", ".cancel", function() {
	$('#timerPopOver').hide();
});

$('#viewers').on("click", ".destinationsLabel", function() {
	$(this).next().css('visibility', 'visible');
}).on("click", "button", function() {
	$(this).parent().css('visibility', 'hidden');
});

$('#gangRecording').on("click", "button", function() {
	for (var i = 0; i < model.viewers().length; i++) {
		var source = model.viewers()[i].selectedSource();
		if (source) {
			$.ajax({
				url: '/sources/' + encodeURIComponent(source.uniqueID) + '/recording_name',
				type: 'PUT',
				data: JSON.stringify({ recording_name: $('#gangRecording input').val() }),
				contentType: 'application/json'
			});
		}
	}
});

for(var i = 0; i < 1; i++) {
	model.viewers.push(new Viewer());
}

ko.applyBindings(model);
fetchPreview();
var socket = new WebSocket(getWsProtocol()+window.location.hostname+":"+window.location.port+"/remote", "v1.1.main_update.movierecorder.softronmedia.com");
socket.onmessage = function (event) {
	var message = JSON.parse(event.data);
	switch (message.dataType) {
		case "source":
			switch (message.change) {
				case "insertion":
					$.each(message.data, function(index, inSource) {
						if (inSource.is_enabled) {
							var source = new Source(inSource);
							model.sources.push(source);
							$.ajax('/sources/'+encodeURIComponent(source.uniqueID)+'/destinations').done(function(inSelectedDestinations) {
								source.selectedDestinations(inSelectedDestinations);
							});
						}
					});
					break;
				case "removal":
					for (var i = 0; i < message.data.length; i++) {
						model.sources.remove(function(source) {
							return (source.uniqueID === message.data[i]);
						});
					}
					break;
				case "replacement":
					var source = new Source(message.data);
					for (var i = 0; i < model.sources().length; i++) {
						if (model.sources()[i].uniqueID == source.uniqueID) {
							// Replace any property that changed
							if (typeof source.displayName() !== 'undefined') {
								model.sources()[i].displayName(source.displayName());
							}
							if (typeof source.videoFormat() !== 'undefined') {
								model.sources()[i].videoFormat(source.videoFormat());
							}
							if (typeof source.isRecording() !== 'undefined') {
								model.sources()[i].isRecording(source.isRecording());
							}
							if (typeof source.isPaused() !== 'undefined') {
								model.sources()[i].isPaused(source.isPaused());
							}
							if (message.data.selected_destinations && getDifferencesBetweenTwoArrays(source.selectedDestinations(), model.sources()[i].selectedDestinations()).length > 0) {
								model.sources()[i].selectedDestinations(source.selectedDestinations());
							}
							break;
						}
					}
					break;
			}
			break;
		case "destination":
			switch (message.change) {
				case "insertion":
					$.each(message.data, function(index, inDestination) {
						model.destinations.push(new Destination(inDestination));
					});
					break;
				case "removal":
					for (var i = 0; i < message.data.length; i++) {
						model.destinations.remove(function(destination) {
							return (destination.uniqueID === message.data[i]);
						});
					}
					break;
				case "replacement":
					var destination = new Destination(message.data);
					for (var i = 0; i < model.destinations().length; i++) {
						if (model.destinations()[i].uniqueID == destination.uniqueID) {
							model.destinations.replace(model.destinations()[i], destination);
							break;
						}
					}
					break;
			}
			break;
	}
};

// Send New selected destinations to Movie Recorder
function onSelectedDestinationsChanged(source)
{
    $.ajax({url: '/sources/'+encodeURIComponent(source.uniqueID)+'/destinations', type: 'PUT', data: JSON.stringify(source.selectedDestinations()), contentType: 'application/json'});
}


// Retrieve all differences between two arrays
function getDifferencesBetweenTwoArrays(array1, array2)
{
    var existingArray = [], differenceList = [];
    
    for (var i = 0; i < array1.length; i++) {
        existingArray[array1[i]] = true;
    }
    
    for (var i = 0; i < array2.length; i++) {
        if (existingArray[array2[i]]) {
            delete existingArray[array2[i]];
        } else {
            existingArray[array2[i]] = true;
        }
    }
    
    for (var difference in existingArray) {
        differenceList.push(difference);
    }
    
    return differenceList;
};

