///////////////////////////////////////////////////////////////////////////////
//
//  main.js
//
// 
// © 2007 Microsoft Corporation. All Rights Reserved.
//
// This file is licensed as part of the Silverlight 1.0 SDK, for details look 
// here: http://go.microsoft.com/fwlink/?LinkID=89144&clcid=0x409
//
///////////////////////////////////////////////////////////////////////////////

VideoLibrary = function() 
{
}

VideoLibrary.prototype.handleLoad = function(control, userContext, rootElement) {
    this.plugIn = control;      // Store the host plug-in
    this.media = rootElement.findName("mediaElement");
    this.isMediaOpened = false;
    this.thumbSize = rootElement.findName("scrollThumbBackground").height;
    
    // Hook the unload event
    document.body.onbeforeunload = Silverlight.createDelegate(this, this.onUnload);
    
    // Hook the plug-in's resize event
    this.resize(rootElement, null);
    this.setCallback(this.plugIn.content, "onResize", this.resize);
    
    // Bind XAML buttons to javascript code
    var playButton = rootElement.findName("playButton");
    var playButtonBackground = rootElement.findName("playButtonBackground");
    new button(playButton, playButtonBackground, "#FF6D6D6D", "#FF595959", Silverlight.createDelegate(this, this.onPlayButtonClicked));
    
    var muteButton = rootElement.findName("muteButton");
    var muteButtonBackground = rootElement.findName("muteButtonBackground");
    new button(muteButton, muteButtonBackground, "#FF6D6D6D", "#FF595959", Silverlight.createDelegate(this, this.onMuteButtonClicked));
    
    var volumeUpButton = rootElement.findName("volumeUpButton");
    var volumeUpButtonBackground = rootElement.findName("volumeUpButtonBackground");
    new button(volumeUpButton, volumeUpButtonBackground, "#FF6D6D6D", "#FF595959", Silverlight.createDelegate(this, this.onVolumeUpButtonClicked));
    
    var volumeDownButton = rootElement.findName("volumeDownButton");
    var volumeDownButtonBackground = rootElement.findName("volumeDownButtonBackground");
    new button(volumeDownButton, volumeDownButtonBackground, "#FF6D6D6D", "#FF595959", Silverlight.createDelegate(this, this.onVolumeDownButtonClicked));
    
    // Hook up Scrollbar
    var scrollThumb = rootElement.findName("scrollThumb");
    var scrollThumbBackground = rootElement.findName("scrollThumbBackground");
    new scrollbar(scrollThumb, scrollThumbBackground, "#FF6D6D6D", "#FF595959", Silverlight.createDelegate(this, this.onScrollDrag));   
    
    // Hook-up seek UI
    rootElement.findName("seekRect").addEventListener("mouseLeftButtonUp", Silverlight.createDelegate(this, this.onSeekClicked));
    
    // Timer callback
    this.timer = rootElement.findName("timer");
    this.timer.addEventListener("completed", Silverlight.createDelegate(this, this.timerTick));
    
    // Hook up media events
    this.media.addEventListener("currentStateChanged", Silverlight.createDelegate(this, this.mediaStateChanged));
    this.media.addEventListener("mediaOpened", Silverlight.createDelegate(this, this.mediaOpened));
    
    this.downloader = this.plugIn.createObject("downloader");
    this.downloader.addEventListener("completed", Silverlight.createDelegate(this, this.downloadCompleted));
    this.downloader.open("GET", "XAML/itemTemplate.xaml");
    this.downloader.send();
}

VideoLibrary.prototype.onScrollDrag = function(sender, eventArgs) {
    if (eventArgs <= 145) { 
        sender.findName("scrollThumb")["Canvas.Top"] = 145
    }
    else if (eventArgs >= 353.1 - this.thumbSize) {
        sender.findName("scrollThumb")["Canvas.Top"] = 353.1 - this.thumbSize;
    }
    else {
        sender.findName("scrollThumb")["Canvas.Top"] = eventArgs;
    }
    sender.findName("itemsContainer")["canvas.top"] = 145 - sender.findName("scrollThumb")["Canvas.Top"];   
}

VideoLibrary.prototype.onListBoxItemClicked = function(sender, eventArgs) {
    // Get the video URL from the TextBlock in the item template
    var sourceUrlTextBlock = sender.findName("sourceUrlTextBlock" + eventArgs);
    
    // Set the source to the URL
    this.media.source = sourceUrlTextBlock.text;
    this.isMediaOpened = false;
    
    // Move the selection rectangle
    sender.findName("selectionRect")["Canvas.Top"] = (eventArgs - 1) * 47;
}

VideoLibrary.prototype.downloadCompleted = function(sender, eventArgs) {
    this.xamlTemplate = sender.responseText;
    var templateInstance;

    // Canned array for data, this could be replaced by a JSON or XML HTTP request
    var videoEntries = new Array();
    videoEntries[0] = new videoEntry("Mike Harsh", "\"WPF\\E\"", "http://download.microsoft.com/download/3/b/0/3b0b0ab5-eb51-4896-bf3a-2f08a4007144/mike_harsh_wpf_e_2006.wmv", "assets/MikeHarsh.jpg");
    videoEntries[1] = new videoEntry("Mike Swanson", "Adobe Illustrator to XAML converter", "http://download.microsoft.com/download/3/1/c/31c7c851-d455-476d-8a11-6306f0383d20/illustrator_to_xaml_2005.wmv", "assets/MikeSwanson.jpg");
    videoEntries[2] = new videoEntry("Bill Gates", "17 Minutes with Bill", "http://download.microsoft.com/download/d/8/7/d8751d87-3c99-4470-8e3e-bf352932601a/ctorrec9billg.wmv", "assets/BillGates.jpg");
    videoEntries[3] = new videoEntry("Katy Hunter", "Steve Ballmer's Speechwriter", "http://download.microsoft.com/download/8/1/c/81cdb151-0aae-4f50-ab44-654b5f7ae0db/WM_IN_2005_KatyHunter.wmv", "assets/KatyHunter.jpg");
    videoEntries[4] = new videoEntry("London Niners", "Tour, Drinks and Debate", "http://download.microsoft.com/download/3/0/9/30948eab-b25d-462b-8e88-91160e92ff22/LondonNiners.wmv", "assets/London.jpg");
    videoEntries[5] = new videoEntry("Channel 9 Team", "Rory Meets Da Team", "http://download.microsoft.com/download/5/4/a/54aa352e-2587-40cc-8a9f-dcd1932973de/Rory_Team_Meet.wmv", "assets/RoryTeam.jpg");
    videoEntries[6] = new videoEntry("Jacqueline Russell", "Microsoft at Maker Faire", "http://download.microsoft.com/download/3/b/0/3b0b0ab5-eb51-4896-bf3a-2f08a4007144/Maker_Faire_Russel.wmv", "assets/JacquelineRussell.jpg");
    videoEntries[7] = new videoEntry("Jenny Lam", "Designing Experiences at Microsoft", "http://download.microsoft.com/download/7/d/b/7dbc5bf1-884c-476a-8915-b2e883de8642/jenny_lam_windows_vista_designer_2005.wmv", "assets/JennyLam.jpg");
    videoEntries[8] = new videoEntry("MS Research Cambridge", "Tour of the Cambridge Campus", "http://download.microsoft.com/download/2/a/d/2adef79f-192f-4fba-ac2c-44975b750ccf/Tour_Final.wmv", "assets/Cambridge.jpg");

    // Iterate over the data items 
    for (var i = 0; i < videoEntries.length; i++)
    {
        // Fill out the template and create a Silverlight element
        templateInstance = this.instanceTemplate(i, videoEntries[i]);
        
        // Position the item in items canvas
        templateInstance["Canvas.Top"] = i * templateInstance.Height;
        sender.findName("itemsContainer").children.insert(0, templateInstance);
        
        // Hook up the new item to eventhandler code
        new listBoxItem(templateInstance, i + 1, Silverlight.createDelegate(this, this.onListBoxItemClicked));
    }
    
    // Set the listbox's item count;
    this.itemCount = videoEntries.length;
    
    // Set the listbox's item height
    this.itemHeight = templateInstance.Height;
    
    // Set the scrollbar's height
    this.calculateScrollThumbSize(sender);
    
    this.onListBoxItemClicked(sender, 1);
}

VideoLibrary.prototype.calculateScrollThumbSize = function(sender) {
    var thumbBackground = sender.findName("scrollThumbBackground");
    thumbScale = sender.findName("itemsContainer").height / (this.itemHeight * this.itemCount);
    
    if (thumbScale > 1.0) {
        thumbBackground.height = sender.findName("scrollThumbBackground").height;
    }
    else {
        thumbBackground.height = thumbScale * sender.findName("scrollThumbBackground").height;
    }
    this.thumbSize = thumbBackground.height;
}

VideoLibrary.prototype.instanceTemplate = function(index, templateData) {
    // Databind the template by replacing the placeholders with real data
    var templateInstanceString = this.xamlTemplate.replaceAll("$0", index + 1);
 
    // Iterate over the proeprties in the data item and fill out the template   
    var i = 0;
    for (var propName in templateData) {
        templateInstanceString = templateInstanceString.replaceAll("$" + (i + 1), templateData[propName]);
        i++;
    }

    // Use createFromXaml to create an element from the string
    var templateInstance = this.plugIn.content.createFromXaml(templateInstanceString);
    return templateInstance;
}

VideoLibrary.prototype.mediaOpened = function(sender, eventArgs) {
    this.isMediaOpened = true;
    this.timer.begin();
    
    // Set duration textblock
    // Process the duration of the media into an hours:minutes:seconds string to be presented.
    var datetime = new Date(0, 0, 0, 0, 0, this.media.naturalDuration.Seconds)
    var hours = datetime.getHours();
    var minutes = datetime.getMinutes();
    var seconds = datetime.getSeconds();
    if (seconds < 10) {
        seconds = "0" + seconds;
    }
    
    if (minutes < 10) {
        minutes = "0" + minutes;
    }
    
    var durationString;
    if (hours > 0) {
        durationString = hours.toString() + ":" + minutes + ":" + seconds;
        sender.findName("duration").text = durationString.toString();
        sender.findName("duration")["canvas.left"] = 493;
    }
    else {
        durationString = minutes + ":" + seconds;
        sender.findName("duration").text = durationString.toString();
        sender.findName("duration")["canvas.left"] = 504;
    } 
}

VideoLibrary.prototype.timerTick = function(sender, eventArgs) {
    if (this.isMediaOpened) { 
        if (this.media.downloadProgress < 1) {
            sender.findName("downloadProgressRect").width = this.media.downloadProgress * 320;
        }
        
        sender.findName("playbackProgressRect").width = (this.media.position.seconds / this.media.naturalDuration.seconds) * 320;
        sender.findName("progressThumb")["Canvas.Left"] = 211 + ((this.media.position.seconds / this.media.naturalDuration.seconds) * 320);
        
        if (this.media.downloadProgress < 1 || this.media.currentState != "Paused") {
            this.timer.begin();
        }
    }
}

VideoLibrary.prototype.mediaStateChanged = function(sender, eventArgs) { 
    if (this.media.currentState != "Paused") {
        sender.findName("pauseIcon").visibility = "Visible";
        sender.findName("playIcon").visibility = "Collapsed";
    }
    else {
        sender.findName("pauseIcon").visibility = "Collapsed";
        sender.findName("playIcon").visibility = "Visible";
    }
}

VideoLibrary.prototype.onSeekClicked = function(sender, eventArgs) { 
    if (this.isMediaOpened) {
        var scaleTransform = sender.findName("scaleTransform");
        var offset = (eventArgs.getPosition(null).x - (73 * scaleTransform.scaleX)) / (321 * scaleTransform.scaleX);
    
        offset = this.media.naturalDuration.seconds * offset;
        var timeSpan = this.media.position;
        timeSpan.seconds = offset;
        this.media.position = timeSpan;
    }
}

VideoLibrary.prototype.onPlayButtonClicked = function(sender, eventArgs) { 
    if(this.media.currentState != "Paused") {
        this.media.pause();
    }
    else {
        this.media.play();
    }
}

VideoLibrary.prototype.onMuteButtonClicked = function(sender, eventArgs) { 
    if(this.media.isMuted) {
        this.media.isMuted = false;
        sender.findName("muteIcon").visibility = "hidden";
    }
    else {
        this.media.isMuted = true;
        sender.findName("muteIcon").visibility = "visible";
    }
}

VideoLibrary.prototype.onVolumeUpButtonClicked = function(sender, eventArgs) { 
    this.media.volume += .05;
}

VideoLibrary.prototype.onVolumeDownButtonClicked = function(sender, eventArgs) { 
    this.media.volume -= .05;
}

// Resizes the XAML scene to fill the browser
VideoLibrary.prototype.resize = function(sender, eventArgs) {
   var sourceWidth = sender.findName("root").width;
   var targetWidth = this.plugIn.content.actualWidth;
   var sourceHeight = sender.findName("root").height;
   var targetHeight = this.plugIn.content.actualWidth;
   
   var scale = 0;
   if (sourceHeight > 0 && sourceWidth > 0) {
       var aspectRatio = sourceWidth/sourceHeight;
       scale = Math.min(targetHeight / sourceHeight, targetWidth / sourceWidth);
   }
   
   var scaleTransform = sender.findName("scaleTransform");
   scaleTransform.scaleX = scale;
   scaleTransform.scaleY = scale;
}

VideoLibrary.prototype.onUnload = function() {
    this.isMediaOpened = false;
    this.media.stop();
    this.media.source = null;
}

VideoLibrary.prototype.setCallback = function(target, eventName, callback) {
	if (!window.methodIndex)
		window.methodIndex = 0;
	
	var callbackName = "uniqueCallback" + (window.methodIndex++);
	var controller = this;
	var func = function() {
		callback.apply(controller, arguments);
	}
	
	eval(callbackName + " = func;");
	target[eventName] = func;
}

function videoEntry(author, videoTitle, videoUrl, videoThumbnailUrl, siteLogoUrl) {
    this.videoUrl = videoUrl;
    this.videoThumbnailUrl = videoThumbnailUrl;
    this.author = author;
    this.videoTitle = videoTitle;
}

// Replaces all instances of the given substring.
String.prototype.replaceAll = function(strTarget, strSubString) {
    var strText = this;
    var intIndexOfMatch = strText.indexOf( strTarget );
 
    // Keep looping while an instance of the target string
    // still exists in the string.
    while (intIndexOfMatch != -1) {
        // Relace out the current instance.
        strText = strText.replace( strTarget, strSubString )

        // Get the index of any next matching substring.
        intIndexOfMatch = strText.indexOf( strTarget );
    }
 
    // Return the updated string with ALL the target strings
    // replaced out with the new substring.
    return( strText );
}