///////////////////////////////////////////////////////////////////////////////
//
//  PlayerControl
//
//  Extends Expression Media's player template classes by adding time-based
//  commenting to the video playing experience.
//
///////////////////////////////////////////////////////////////////////////////

function PlayerControl(parentId) {
    this._hostname = EePlayer.Player._getUniqueName("xamlHost");
    Silverlight.createObjectEx({
        source: 'Silverlight/Player/Player.xaml?v=1',
        parentElement: $get(parentId || "Player_SilverlightContainer"),
        id: this._hostname,
        properties: {
            width: '900',
            height: '412',
            framerate: '24',
            version: '1.0',
            background: 'transparent',
            isWindowless: 'true'
        },
        events: {
            onLoad: Function.createDelegate(this, this.onLoad)
            },
        initParams: videoUrl + ',' + videoId
    });
    //These are set in Player.ascx.cs
    this._currentMediainfo = 0;
}

PlayerControl.prototype = {

    _control: null,
    _content: null,
    _rootElement: null,
    _mediaOpened: false,

    _fontsDownloaded: false,
    _fonts: null,

    _dbComments: null,
    _commentsCreated: false,
    _numComments: 0,
    _moderatedCommentNumId: 0,
    _currentMarkerIndex: 0,
    
    _VideoTimeInSeconds: 0.0,
    _CommentText: null,
    _dbCommentId: null,
    _AddCommentMode: false,
    _ModerateCommentMode: false,
    _UserIsModerator: false,
    _UserAlreadyRated: true,
    _ShowPlayerSupplements: true,
    
    _favoriteStatus: false,

    _timelineMarkerTemplate: '<TimelineMarker xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="CommentMarker$id" Type="$id" Text="" Time="0:$minutes:$seconds"/>',
    //_commentBlockTemplate: '<Canvas xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Comment_$id" Canvas.Left="15" Width="313"><Image x:Name="CommentAvatar_$id" Height="16" Width="16" Opacity="0.5"/><TextBlock x:Name="CommentOwner_$id" Canvas.Left="26" Canvas.Top="5" Width="287" FontSize="11" Foreground="Gray" /><TextBlock x:Name="CommentText_$id" Canvas.Left="26" Canvas.Top="23" Width="287" FontSize="12" Foreground="Gray" TextWrapping="Wrap" FontStyle="Italic" /></Canvas>',
    _commentBlockTemplate: '<Canvas xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Comment_$id" Canvas.Left="15" Width="313"><Image x:Name="CommentAvatar_$id" Height="16" Width="16" Opacity="0.5"/><TextBlock x:Name="CommentOwner_$id" Canvas.Left="26" Canvas.Top="5" Width="287" FontSize="11" Foreground="Gray" /><TextBlock x:Name="CommentEditLink_$id" Canvas.Left="156" Canvas.Top="5" Width="30" FontSize="11" Foreground="#fc8800" Text="Edit" Cursor="Hand" Visibility="Collapsed" /><TextBlock x:Name="CommentSeperator_$id" Canvas.Left="176" Canvas.Top="5" Width="15" FontSize="11" Foreground="Gray" Text=" | " Visibility="Collapsed" /><TextBlock x:Name="CommentDeleteLink_$id" Canvas.Left="186" Canvas.Top="5" Width="40" FontSize="11" Foreground="#fc8800" Text="Delete" Cursor="Hand" Visibility="Collapsed" /><TextBlock x:Name="CommentId_$id" Canvas.Left="226" Canvas.Top="5" Width="10" FontSize="11" Text="$dbCommentId" Visibility="Collapsed" Opacity="0" /><TextBlock x:Name="CommentText_$id" Canvas.Left="26" Canvas.Top="23" Width="287" FontSize="12" Foreground="Gray" TextWrapping="Wrap" FontStyle="Italic" /></Canvas>',
    _commentBlockIntroTemplate: '<Canvas xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Comment_$id" Canvas.Left="15" Width="313"><Image x:Name="CommentAvatar_$id" Height="0" Width="0" Visibility="Collapsed" /><TextBlock x:Name="CommentOwner_$id" Height="0" Width="0" Visibility="Collapsed"/><TextBlock x:Name="CommentText_$id" Canvas.Left="26" Width="287" FontSize="12" Foreground="Gray" TextWrapping="Wrap" /></Canvas>',
    /*
    onLoad

    Handles the Silverlight onLoad event.
    Creates the ExtendedPlayer video player and calls back to services for video info.
    */
    onLoad: function(control, userContext, rootElement) {
        this._control = control;
        this._content = control.content;
        this._rootElement = rootElement;
        this._player = $create(ExtendedPlayer.Player, {
            // properties
            autoPlay: true,
            volume: 1.0,
            muted: false
        }, {
            // event handlers
            mediaEnded: Function.createDelegate(this, this.onMediaEnded),
            mediaFailed: Function.createDelegate(this, this.onMediaFailed),
            stateChanged: Function.createDelegate(this, this.onStateChanged),
            markerReached: Function.createDelegate(this, this.onMarkerReached),
            mediaOpened: Function.createDelegate(this, this.onMediaOpened)
            }, null, $get(this._hostname));

        var params = $get(this._hostname).InitParams.split(",");
        this._player.set_mediainfo({
            "mediaUrl": params[0],
            "placeholderImage": "",
            "chapters": []
            });
        var videoId = params[1];
        
        if (this._ShowPlayerSupplements)
        {
            var userLoggedIn = (typeof(userId) != 'undefined');
            if (userLoggedIn)
            {
                VideoShow.RatingWebservice.HasAlreadyRated(videoId, userId, this.createDelegate(this, this.onHasAlreadyRatedReceived));
            }
        
            VideoShow.VideoWebservice.GetVideoDetails(videoId, this.createDelegate(this, this.onVideoDetailsReceived));
            VideoShow.TagWebservice.GetTagsForVideo(videoId, this.createDelegate(this, this.onVideoTagsReceived));
            VideoShow.CommentWebservice.GetComments(videoId, this.createDelegate(this, this.onVideoCommentsReceived));
            VideoShow.RatingWebservice.GetRating(videoId, this.createDelegate(this, this.onVideoRatingReceived));
            
            if ($get("ToggleFavoriteLink")) {
                this.getFavoriteStatus();
            }
        }
        else
        {
            this._content.findname("CommentsView").Visibility = "Collapsed";
        }
        
        var fontDownloader = control.CreateObject('downloader');
        fontDownloader.addEventListener('completed', this.createDelegate(this, this.onFontsDownloaded));
        fontDownloader.open('GET', '/Silverlight/Fonts/Fonts.zip');
        fontDownloader.send();

        this._rootElement.findName('HidePagingControls').addEventListener('completed', this.createDelegate(this, this.OnHidePagingComplete));
        this._rootElement.findName('PagePrevious').addEventListener('mouseEnter', this.createDelegate(this, this.OnPagePreviousMouseEnter));
        this._rootElement.findName('PagePrevious').addEventListener('mouseLeave', this.createDelegate(this, this.OnPagePreviousMouseLeave));
        this._rootElement.findName('PagePrevious').addEventListener('mouseLeftButtonUp', this.createDelegate(this, this.OnPagePrevious));
        this._rootElement.findName('PageNext').addEventListener('mouseEnter', this.createDelegate(this, this.OnPageNextMouseEnter));
        this._rootElement.findName('PageNext').addEventListener('mouseLeave', this.createDelegate(this, this.OnPageNextMouseLeave));
        this._rootElement.findName('PageNext').addEventListener('mouseLeftButtonUp', this.createDelegate(this, this.OnPageNext));
        /*this._rootElement.findName('CommentAssistance').addEventListener('mouseEnter', this.createDelegate(this, this.OnMouseEnterAssistanceButton));
        this._rootElement.findName('CommentAssistance').addEventListener('mouseLeave', this.createDelegate(this, this.OnMouseLeaveAssistanceButton));
        this._rootElement.findName('CommentAssistance').addEventListener('mouseLeftButtonUp', this.createDelegate(this, this.OnCommentAssistanceButtonClick));
        this._rootElement.findName('RatingAssistance').addEventListener('mouseEnter', this.createDelegate(this, this.OnMouseEnterAssistanceButton));
        this._rootElement.findName('RatingAssistance').addEventListener('mouseLeave', this.createDelegate(this, this.OnMouseLeaveAssistanceButton));
        this._rootElement.findName('RatingAssistance').addEventListener('mouseLeftButtonUp', this.createDelegate(this, this.OnRatingAssistanceButtonClick));*/
        this._rootElement.findName('Share').addEventListener('mouseEnter', this.createDelegate(this, this.OnMouseEnterShareButton));
        this._rootElement.findName('Share').addEventListener('mouseLeave', this.createDelegate(this, this.OnMouseLeaveShareButton));
        this._rootElement.findName('Share').addEventListener('mouseLeftButtonUp', this.createDelegate(this, this.OnShareButtonClick));
    },

    /*
    onFontsDownloaded, onVideoDetailsReceived, onVideoTagsReceived, onVideoCommentsReceived

    These functions handle the receipt of downloaded elements.
    */
    onFontsDownloaded: function(sender, eventArgs) {
        this._fonts = sender;
        this._fontsDownloaded = true;
        this.SetFonts();
    },

    onVideoDetailsReceived: function(videoDetails) {
        $get("VideoDescription").innerText = videoDetails.description;
    },
    
    onVideoRatingReceived: function(videoRating) {
        var ratingImageHTML = "Film hasn't been rated yet!";
        
        if (this._UserAlreadyRated)
        {
            ratingImageHTML = "<ul class='star-rating2' id='rater'>" +
		                        "<li class='current-rating' style='width:" + videoRating * 20 + "%;' id='ulRating'></li>" +
		                        "<li><a onclick='return false;' href='#' title='1 star out of 5' class='one-star'>1</a></li>" +
		                        "<li><a onclick='return false;' href='#' title='2 stars out of 5' class='two-stars'>2</a></li>" +
		                        "<li><a onclick='return false;' href='#' title='3 stars out of 5' class='three-stars'>3</a></li>" +
		                        "<li><a onclick='return false;' href='#' title='4 stars out of 5' class='four-stars'>4</a></li>" +
		                        "<li><a onclick='return false;' href='#' title='5 stars out of 5' class='five-stars'>5</a></li>" +
	                            "</ul>";
        }
        else
        {
            ratingImageHTML = "<ul class='star-rating' id='rater'>" + 
		                        "<li class='current-rating' style='width: " + videoRating * 20 + "%;' id='ulRating'></li>" + 
		                        "<li><a onclick='player.rateVideo(" + videoId + ", 1); return false;' title='1 star out of 5' class='one-star' >1</a></li>" + 
		                        "<li><a onclick='player.rateVideo(" + videoId + ", 2); return false;' title='2 stars out of 5' class='two-stars'>2</a></li>" +
		                        "<li><a onclick='player.rateVideo(" + videoId + ", 3); return false;' title='3 stars out of 5' class='three-stars'>3</a></li>" + 
		                        "<li><a onclick='player.rateVideo(" + videoId + ", 4); return false;' title='4 stars out of 5' class='four-stars'>4</a></li>" +
		                        "<li><a onclick='player.rateVideo(" + videoId + ", 5); return false;' title='5 stars out of 5' class='five-stars'>5</a></li>" +
	                            "</ul>";
        }    
        //$get("VideoRating").innerHTML = "<span id=\"tag-title\">Rating: </span>" + ratingImageHTML;
        $get("VideoRating").innerHTML = ratingImageHTML;
     
    },
    
    onHasAlreadyRatedReceived: function(outcome) {
        this._UserAlreadyRated = outcome;
    },
    
    onVideoRatingAdded: function (ratingId) {
        this._UserAlreadyRated = true;
    },

    onVideoTagsReceived: function(videoTags) {
        
        /*var tagHtml = '';
        if ($get("VideoTags") == null)
        {
           for (var i = 0; i < videoTags.length; i++) {
                if (i > 0) 
                {
                    tagHtml += ", " + videoTags[i];
                }
                else    
                {
                    tagHtml += videoTags[i];
                }
           }
           $get("ctl00$contentPlaceHolderMain$txtTags").value = tagHtml; 
        }
        else
        {
            for (var i = 0; i < videoTags.length; i++) {
                tagHtml += "<a href='Tags.aspx?Tag=" + videoTags[i] + "'>" + videoTags[i] + "</a>";
            }
            $get("VideoTags").innerHTML = "<span id=\"tag-title\">Tags: </span>" + tagHtml;
        } */       
        var tagHtml = '';
        var tagTextBoxValue = '';
        
        for (var i = 0; i < videoTags.length; i++) 
        {
            if (i > 0) 
            {
                tagTextBoxValue += ", " + videoTags[i];
            }
            else    
            {
                tagTextBoxValue += videoTags[i];
            }
            tagHtml += "<a href='Tags.aspx?Tag=" + escape(videoTags[i]) + "'>" + videoTags[i] + "</a> ";
       }
       $get("txtTags").value = tagTextBoxValue; 
       $get("VideoTags").innerHTML = tagHtml;
    },

    onVideoCommentsReceived: function(dbComments) {
        this._dbComments = dbComments;
        this.addDbComments();
    },

    /*
    onMediaOpened and addDbComments

    Adds comment markers to the video after the media has been opened. 
    Markers added before the media is opened will not register.
    
    Since the addDbComments function cannot run until both comments have been
    received from a service call and the media is opened, both onMediaOpened
    and onVideoCommentsReceived call it.  It runs only on the second call 
    (whichever is last)
    */
    onMediaOpened: function(sender, eventArgs) {
        this._mediaOpened = true;
        this.addDbComments();
    },

    addDbComments: function() {
        
        if (this._dbComments !== null && this._mediaOpened) {
        
            var introText;
            if (this._dbComments.length === 0) {
                introText = 'No comments for this video yet...';
            } else {
                introText = 'Comments:';
            }
            this.insertComment(0,introText, '', '', 0, true);
            
            for (var i = 0; i < this._dbComments.length; i++) {
                var info = this._dbComments[i];
                this.insertComment(info.CommentId, info.CommentText, info.Username, info.AvatarUrl, info.VideoTimeInSeconds, false);
            }
            this._commentsCreated = true;

            this.resetCommentWindow();
            this.SetPagingVisibility();
            this.SetFonts();
        }
    },

    /*
    insertComment

    Inserts a comment into the comment window and adds a comment marker to the video.
    Note: this function does not attempt to place the comment spatially within the window.
    Spacing is done only after all comments are added.  This is done in order to easily reset 
    the layout after adding a comment dynamically.
    
    The isIntro parameter specifies whether the comment is the "intro" comment--a 
    static marker for the beginning of the comment list.
    */
    insertComment: function(commentId, text, ownerName, avatarUrl, timeInSeconds, isIntro) {
        var timelineMarkerXaml;
        var textBlockXaml;
        var marker;
        var commentBlock;

        var commentsCanvas = this._rootElement.findName('CommentsCanvas');
        var video = this._player._mediaElement;

        var commentNumId = this._numComments++;
        timelineMarkerXaml = this._timelineMarkerTemplate.replace(/\$id/g, commentNumId);
        //timelineMarkerXaml = timelineMarkerXaml.replace(/\$seconds/g, timeInSeconds);
        timelineMarkerXaml = timelineMarkerXaml.replace(/\$seconds/g, (timeInSeconds % 60).toFixed(1));
        timelineMarkerXaml = timelineMarkerXaml.replace(/\$minutes/g, parseInt(timeInSeconds / 60));
        commentBlockXaml = isIntro ? this._commentBlockIntroTemplate: this._commentBlockTemplate;
        
        commentBlockXaml = commentBlockXaml.replace(/\$id/g, commentNumId);
        commentBlockXaml = commentBlockXaml.replace(/\$dbCommentId/g, commentId);
             
        marker = this._content.createFromXaml(timelineMarkerXaml);
        commentBlock = this._content.createFromXaml(commentBlockXaml);
        
        var commentText = commentBlock.findName('CommentText_' + commentNumId);
        var commentAvatar = commentBlock.findName('CommentAvatar_' + commentNumId);
        var commentOwner = commentBlock.findName('CommentOwner_' + commentNumId);
        
        if (!isIntro && this._UserIsModerator)
        {
            var commentEditLink = commentBlock.findName('CommentEditLink_' + commentNumId);
            var commentDeleteLink = commentBlock.findName('CommentDeleteLink_' + commentNumId);
            var commentSeperator = commentBlock.findName('CommentSeperator_' + commentNumId);
            var commentIdBlock = commentBlock.findName('CommentId_' + commentNumId);
            commentEditLink.Visibility = "Visible";
            commentDeleteLink.Visibility = "Visible";
            commentSeperator.Visibility = "Visible";
            commentIdBlock.Visibility = "Visible";
            commentEditLink.addEventListener('mouseLeftButtonUp', this.createDelegate(this, this.onEditCommentClick));
            commentDeleteLink.addEventListener('mouseLeftButtonUp', this.createDelegate(this, this.onDeleteCommentClick));
        }
            
        commentText.Text = text;
        commentAvatar.Source = avatarUrl;
        commentOwner.Text = ownerName + " added:";
        commentBlock.Height = commentText.ActualHeight + commentText['Canvas.Top'];
        
        commentsCanvas.children.add(commentBlock);

        var markerIndex = video.markers.add(marker);
        if (markerIndex < this._currentMarkerIndex) {
            this._currentMarkerIndex++;
        }
          
        return commentNumId;
    },

    /*
    resetCommentWindow

    Resets vertical layout for all comments in the comment window.  
    This is done in order to easily reset the layout after adding a comment dynamically.
    */
    resetCommentWindow: function() {
        var marker;
        var comment;
        var totalHeight = 0;
        var commentBuffer = 30;
        var commentsCanvas = this._rootElement.findName('CommentsCanvas');
        
        for (var i = 0; i < this._numComments; i++) {
            //marker = this.GetMarker(i);
            marker = this.GetMarker(this.getMarkerIndexFromId(i));
            var commentId = parseInt(marker.Type,10);
            comment = this.GetCommentById(commentId);
            if (i === 0) {
                if (this._numComments > 1) {
                    comment.findName('CommentText_' + commentId).Text = 'Comments:';
                }
                commentsCanvas['Canvas.Top'] = (commentsCanvas.Height / 2) - comment.Height;
                comment['Canvas.Top'] = 0;
                totalHeight += comment.Height + commentBuffer;
            } else if (comment.Visibility != 'Collapsed'){
                comment['Canvas.Top'] = totalHeight;
                totalHeight += comment.Height + commentBuffer;
            }
        }

        var loadingMessage = this._rootElement.findName('LoadingMessage');
        loadingMessage.Visibility = 'Collapsed';

        this.SetFonts();
    },

    /*
    onMarkerReached and jumpToComment

    onMarkerReached Handles the markerReached video player event.
    jumpToComment moves the highlights the specified comment in the comment window.
    If syncPlayer is true, it will also move the video to the corresponding spot 
    (this behavior is desired for navigating from comment to comment in pause mode,
    but not in play mode.)
    */
    onMarkerReached: function(sender, markerEventArgs) {
        this.jumpToComment(this.getMarkerIndexFromId(markerEventArgs._marker.Type), false);
    },

    jumpToComment: function(markerIndex, syncPlayer) {
        var marker = this.GetMarker(markerIndex);
        var commentId = parseInt(marker.Type,10);
        if(isNaN(commentId)) {
            return;
        }
        var comment = this.GetCommentById(commentId);
        if(typeof comment == 'undefined') {
            return;
        }
        var translateTransform = this._rootElement.findName('CommentsTranslate');
        var commentAnimationStart = this._rootElement.findName('SlideCommentStart');
        var commentAnimationSpline = this._rootElement.findName('SlideCommentSpline');
        var storyboard = this._rootElement.findName('SlideCommentStoryboard');

        commentAnimationStart.Value = translateTransform.Y;
        
        var commentsCanvas = this._rootElement.findName('CommentsCanvas');
        if (comment.Height > (commentsCanvas.Height / 2))
            commentAnimationSpline.Value = -1 * (comment['Canvas.Top'] + (comment.Height - (commentsCanvas.Height / 2)));
        else
            commentAnimationSpline.Value = -1 * comment['Canvas.Top'];
        if (commentAnimationStart.Value != commentAnimationSpline.Value) {
            storyboard.begin();
        }
        var commentText = comment.findName('CommentText_' + commentId);
        var commentAvatar = comment.findName('CommentAvatar_' + commentId);
        var commentOwner = comment.findName('CommentOwner_' + commentId);

        commentText.foreground = 'White';
        commentOwner.foreground = 'White';
        commentAvatar.Opacity = 1;
        if (markerIndex != this._currentMarkerIndex) {
            marker = this.GetMarker(this._currentMarkerIndex);
            commentId = parseInt(marker.Type,10);
            comment = this.GetCommentById(commentId);
            commentText = comment.findName('CommentText_' + commentId);
            commentAvatar = comment.findName('CommentAvatar_' + commentId);
            commentOwner = comment.findName('CommentOwner_' + commentId);
            commentText.foreground = 'Gray';
            commentOwner.foreground = 'Gray';
            commentAvatar.Opacity = 0.5;
            this._currentMarkerIndex = markerIndex;
        }

        this.SetPagingVisibility();

        if (syncPlayer) {
            marker = this.GetMarker(markerIndex);
            this._player.set_timeIndex(marker.Time.Seconds);
            this._player._updatePosition();
        }
    },

    /*
    SetPagingVisibility

    Determines whether to show or hide each paging control depending on the position 
    of the currently highlighted comment.
    */
    SetPagingVisibility: function() {
        var pageNext = this._rootElement.findName('PageNext');
        var pagePrevious = this._rootElement.findName('PagePrevious');
        if (this._currentMarkerIndex === 0) {
            pagePrevious.Visibility = 'Collapsed';
            this.HighlightElement(this._rootElement.findName('PagePreviousArrow'), false);
        } else {
            pagePrevious.Visibility = 'Visible';
        }
        if (this._currentMarkerIndex == this._numComments - 1) {
            pageNext.Visibility = 'Collapsed';
            this.HighlightElement(this._rootElement.findName('PageNextArrow'), false);
        } else {
            pageNext.Visibility = 'Visible';
        }
    },

    /*
    ShowPagingControls and HidePagingControls
    */
    ShowPagingControls: function() {
        this._rootElement.findName('PagingControls').visibility = 'Visible';
        this._rootElement.findName('ShowPagingControls').begin();
    },

    HidePagingControls: function() {
        this._rootElement.findName('HidePagingControls').begin();
    },

    OnHidePagingComplete: function() {
        this._rootElement.findName('PagingControls').visibility = 'Collapsed';
    },

    /*
    OnPageNext, OnPagePrevious
    
    Handles page button clicks
    */

    OnPageNext: function(sender, mouseEventArgs) {
        this.jumpToComment(this._currentMarkerIndex + 1, true);
    },

    OnPagePrevious: function(sender, mouseEventArgs) {
        this.jumpToComment(this._currentMarkerIndex - 1, true);
    },
    
    /*
    OnPageNextMouseEnter, OnPageNextMouseLeave, OnPagePreviousMouseEnter, OnPagePreviousMouseLeave
    
    Handles hover behavior for paging buttons
    */

    OnPageNextMouseEnter: function(sender, mouseEventArgs) {
        this.HighlightElement(this._rootElement.findName('PageNextArrow'), true);
    },

    OnPageNextMouseLeave: function(sender, mouseEventArgs) {
        this.HighlightElement(this._rootElement.findName('PageNextArrow'), false);
    },

    OnPagePreviousMouseEnter: function(sender, mouseEventArgs) {
        this.HighlightElement(this._rootElement.findName('PagePreviousArrow'), true);
    },

    OnPagePreviousMouseLeave: function(sender, mouseEventArgs) {
        this.HighlightElement(this._rootElement.findName('PagePreviousArrow'), false);
    },
    
    /*
        onMouseEnterAssistanceButton and onMouseLeaveAssistanceButton
        Handles hover behavior for paging links
    */

    OnMouseEnterAssistanceButton: function(sender, eventArgs) {
        sender.textDecorations = 'Underline';
    },
    
    OnMouseLeaveAssistanceButton: function(sender, eventArgs) {
        sender.textDecorations = 'None';
    },
    
    /*
        onMouseEnterShareButton and onMouseLeaveShareButton
        Handles hover behavior for paging links
    */

    OnMouseEnterShareButton: function(sender, eventArgs) {
        sender.textDecorations = 'None';
        sender.Opacity = 1;
    },
    
    OnMouseLeaveShareButton: function(sender, eventArgs) {
        sender.textDecorations = 'None';
        sender.Opacity = 0.5;
    },
    
    OnShareButtonClick: function(sender, mouseEventArgs) {
        this.showShareForm();
    },
    
    /* Moderate Comments */
    onEditCommentClick: function(sender, mouseEventArgs) {
        var length = String(sender.Name).length;
        var commentNumId = String(sender.Name).substring(String(sender.Name).indexOf('_') + 1, length);
        this._ModerateCommentMode = true;
        this._moderatedCommentNumId = commentNumId;
        this.EditComment(commentNumId);
    },
    
    onDeleteCommentClick: function(sender, mouseEventArgs) {
        var length = String(sender.Name).length;
        var commentNumId = String(sender.Name).substring(String(sender.Name).indexOf('_') + 1, length);
        this._ModerateCommentMode = true;
        this._moderatedCommentNumId = commentNumId;
        this.DeleteComment(commentNumId);
    },
    
    DeleteComment: function(commentNumId) {
        var comment = this.GetCommentById(commentNumId);
        comment.Visibility = 'Collapsed';
        this.resetCommentWindow();
        var commentId = parseInt(comment.findName('CommentId_' + commentNumId).Text, 10);
        VideoShow.CommentWebservice.DeleteComment(commentId);
        
    },
    
    EditComment: function(commentNumId) {
        var comment = this.GetCommentById(commentNumId);
        var commentId = parseInt(comment.findName('CommentId_' + commentNumId).Text, 10);    
        var commentText = comment.findName('CommentText_' + commentNumId).Text; 
        $get("CommentText").value = commentText;
        var marker = this.GetMarker(this.getMarkerIndexFromId(commentNumId));
        this._player.set_timeIndex(marker.Time.Seconds);
        this._player._updatePosition();
        this.showCommentForm();   
    },
    
    /*
    HighlightElement
    
    Highlights or fades a comment
    */

    HighlightElement: function(element, isHighlighted) {
        element.Fill = isHighlighted ? 'White': 'Gray';
    },

    /*
    SetFonts
    
    Sets font resources for all comments.
    */

    SetFonts: function() {
        if (this._fontsDownloaded && this._commentsCreated) {
            for (var i = 0; i < this._numComments; i++) {
                var comment = this.GetCommentByMarkerIndex(i);
                var commentText = comment.findName('CommentText_' + i);
                var commentOwner = comment.findName('CommentOwner_' + i);
                commentText.setFontSource(this._fonts);
                commentText.fontFamily = 'Segoe UI';
                if (i > 0) {
                    commentText.fontStyle = 'Italic';
                }
                commentOwner.setFontSource(this._fonts);
                commentOwner.fontFamily = 'Segoe UI';
            }
        }

        var loadingMessage = this._rootElement.findName('LoadingMessage');
        loadingMessage.setFontSource(this._fonts);
        loadingMessage.fontFamily = 'Segoe UI';
    },

    /*
    Comment accessors
    
    These functions get comments and markers:
    GetCommentById: Finds a comment element by its canvas ID
    GetCommentByMarkerIndex: Finds a comment by its position relative to other markers.
    GetMarker: Finds a marker by its index relative to other markers.
    GetMarkerIndexFromId: Finds a marker index for a given ID.
    
    IDs vs. Indexes
    IDs are unique identifiers for a comment/marker pair.  They are assigned at load.
    As comments are added by the user, each one receives a new unique ID.\
    While indexes are also unique, the index of a comment may change if a new one is
    added before it. The ID will not. Since the ID is used to name the Silverlight
    canvas, it cannot change, so indexes provide a way to go to the next or previous
    comment without knowing its ID.
    */

    GetCommentById: function(id) {
        return this._rootElement.findName('Comment_' + id);
    },

    GetCommentByMarkerIndex: function(markerIndex) {
        var marker = this.GetMarker(markerIndex);
        return this.GetCommentById(parseInt(marker.Type,10));
    },

    GetMarker: function(markerIndex) {
        var sortedMarkers = this._player._mediaElement.Markers;
        return sortedMarkers.GetItem(markerIndex);
    },

    getMarkerIndexFromId: function(id) {
        var sortedMarkers = this._player._mediaElement.Markers;
        for (var i = 0; i < sortedMarkers.Count; i++) {
            var marker = sortedMarkers.GetItem(i);
            if (marker.Type == id) {
                return i;
            }
        }
    },

    /*
    Media event handlers

    onMediaEnded resets the video to the beginning and pauses it.
    onMediaFailed raises an error.
    onStateChanged toggles the playing vs. paused states of the comment view.
    */

    onMediaEnded: function(sender, eventArgs) {
        this._player.set_timeIndex(0);
        this._player._updatePosition();
        this._player.pause();
    },

    onMediaFailed: function(sender, eventArgs) {
        alert(String.format(Ee.UI.Xaml.Media.Res.mediaFailed, this._player.get_mediaUrl()));
    },

    onStateChanged: function(sender, eventArgs) {

        var playState = this._player.get_playState();
        //Comment mode pauses the video
        if (playState == "Paused" && !this._AddCommentMode && !this._ModerateCommentMode) {
            this.ShowPagingControls();

            if (AjaxControlToolkit.Animation) {
                $get("screen-cover").style.display = "block";
                $get("screen-cover").style.width = $get("main").offsetWidth;
                //Width must be a fixed value for fade-out
                AjaxControlToolkit.Animation.FadeOutAnimation.play($get("screen-cover"), 0.3, 30);
                AjaxControlToolkit.Animation.FadeOutAnimation.play($get("frame-bottom2"), 0.3, 30);
                $get("screen-cover").style.width = "100%";
                //Reset width to 100% to allow screen resize
                }

        } else if (playState == "Playing") {
            this.HidePagingControls();

            if (AjaxControlToolkit.Animation && $get("screen-cover")) {
                $get("screen-cover").style.display = "block";
                AjaxControlToolkit.Animation.FadeInAnimation.play($get("screen-cover"), 0.3, 30);
                AjaxControlToolkit.Animation.FadeInAnimation.play($get("frame-bottom2"), 0.3, 30);
            }
        }
    },
    
    /*
    showTags

    shows and hides the Tags textbox.
    */
    
    showTags: function()
    {
        if ($get("TagButton").innerHTML == "Edit Tags")
        {
            $get("VideoTags").style.display = "none";
            $get("VideoTagsModerate").style.display = "inline";
            $get("TagButton").innerHTML = "Update Tags";
        }
        else
        {
            VideoShow.TagWebservice.UpdateTagsForVideo(videoId, $get("txtTags").value, this.createDelegate(this, this.onVideoTagsReceived));
            $get("VideoTags").style.display = "inline";
            $get("VideoTagsModerate").style.display = "none";
            $get("TagButton").innerHTML = "Edit Tags";
        }
    },

    /*
    showCommentForm, hideCommentForm

    shows and hides the "add comment" dialog.
    */
        
    showCommentForm: function() {
        this._player.pause();
        this._content.findname("CommentsView").Opacity = 0;
        var timeline = this._content.findname("TimeLine");
        timeline["Canvas.Left"] = 560;
        timeline["Canvas.Top"] = 40;
        timeline.Width = 100;
        timeline["Canvas.ZIndex"] = 10;
        
        $get("assistance").style.display = 'none';
                
        if (this._ModerateCommentMode)
        {
            this._content.findname("ModerateCommentCanvas").Visibility = "Visible";  
            //Prevent user from changing the key frame the comment is attached to
            this._player._dragTime.set_sliderActive(false);  
        }
        else
        {
            this._AddCommentMode = true;
            this._content.findname("AddCommentCanvas").Visibility = "Visible";
        }
        this._content.findname("PlayerBase").Visibility = "Collapsed";
        this._content.findname("MuteButton").Visibility = "Collapsed";
        this._content.findname("PlayPauseButton").Visibility = "Collapsed";
        this._content.findname("TimeReadout").Visibility = "Collapsed";
        this._content.findname("FullScreenButton").Visibility = "Collapsed";
        this._content.findname("VolumeControl").Visibility = "Collapsed";
        this._content.findname("ShowVolumeControl").Visibility = "Collapsed";
        //$get("TabContainer").style.display="none";
        $get("commentForm").style.display = "inline";
    },

    hideCommentForm: function() {
        //$get("TabContainer").style.display="inline";
        $get("commentForm").style.display = "none";
        $get("assistance").style.display = 'inline';
                
        if (this._ModerateCommentMode)
        {
            this._ModerateCommentMode = false;
            this._content.findname("ModerateCommentCanvas").Visibility = "Collapsed";    
            this._player._dragTime.set_sliderActive(true); 
        }    
        else
        {
            this._AddCommentMode = false;
            this._content.findname("AddCommentCanvas").Visibility = "Collapsed";
        }
        this._content.findname("PlayerBase").Visibility = "Visible";
        this._content.findname("MuteButton").Visibility = "Visible";
        this._content.findname("PlayPauseButton").Visibility = "Visible";
        this._content.findname("TimeReadout").Visibility = "Visible";
        this._content.findname("FullScreenButton").Visibility = "Visible";
        this._content.findname("VolumeControl").Visibility = "Visible";
        this._content.findname("ShowVolumeControl").Visibility = "Visible";
        this._content.findname("CommentsView").Opacity = 1;
        var timeline = this._content.findname("TimeLine");
        timeline["Canvas.Left"] = 114;
        timeline["Canvas.Top"] = 392.556;
        timeline.Width = 390.162;
        timeline["Canvas.ZIndex"] = 10;
    },
    
    /*
    submitComment, onCommentAdded

    Adds a new comment to the comment window or edits an existing comment, sets the player to that marker.
    */

    SubmitComment: function() {
        var commentNumId;
        CommentText = $get("CommentText").value;
        timeInSeconds = this._player.get_timeIndex().toFixed(1);
        
        if (timeInSeconds === 0) {
            timeInSeconds += 0.1;
        }
        if (!this._ModerateCommentMode)
        {
            VideoShow.CommentWebservice.AddComment(userId, videoId, CommentText, timeInSeconds, this.createDelegate(this, this.onCommentAdded));
            commentNumId = this.insertComment(this._dbCommentId, CommentText, userName, userAvatarUrl, timeInSeconds, false);
        }
        else
        {
            commentNumId = this._moderatedCommentNumId;
            var comment = this.GetCommentById(commentNumId);
            comment.findName('CommentText_' + commentNumId).Text = CommentText; 
            var commentId = parseInt(comment.findName('CommentId_' + commentNumId).Text, 10)
            VideoShow.CommentWebservice.EditComment(commentId, CommentText, timeInSeconds, this.createDelegate(this, this.onCommentEdited));
        }    
        this.resetCommentWindow();
        this.jumpToComment(this.getMarkerIndexFromId(commentNumId), true);
    },

    onCommentAdded: function(commentId) {
        //Add the comment to the current display so we can see it.
        //var markerXaml = "<TimelineMarker Time=\"0:0:" + this._VideoTimeInSeconds + "\" Type=\"You just said...\" Text=\"" + CommentText + "\" />"
        //var marker = this._content.createFromXaml(markerXaml);
        //this._player._mediaElement.markers.add(marker);
        this._player.play();
        this.hideCommentForm();
        this._dbCommentId = commentId;
    },
    
    onCommentEdited: function() {
        this._player.play();
        this.hideCommentForm();
    },
    
    setUserModerator: function(value) {
        this._UserIsModerator = value;
    },
    
    setShowPlayerSupplements: function(value) {
        this._ShowPlayerSupplements = value;
    },

    /*
    favorites

    Methods to handle favorites button behavior
    */

    getFavoriteStatus: function() {
        this._favoriteStatus = VideoShow.FavoriteWebservice.GetFavoriteStatus(userId, videoId, PlayerControl.prototype.createDelegate(this, this.onFavoriteStatusReceived));
    },

    onFavoriteStatusReceived: function(status) {
        this._favoriteStatus = status;
        if (status) {
            $get("ToggleFavoriteLink").innerText = "Remove Favorite";
        } else {
            $get("ToggleFavoriteLink").innerText = "Favorite";
        }
    },

    toggleFavorite: function() {
        VideoShow.FavoriteWebservice.ToggleFavoriteStatus(userId, videoId, PlayerControl.prototype.createDelegate(this, this.getFavoriteStatus));
    },
    
    rateVideo: function(videoId, ratingValue) {
		
	    var loader = $get('VideoRatingLoading');
	    var uldiv = $get('ulRating');
	
	    /*if(res == 'already_voted')
	    {
			
			loader.style.display = 'block';
			loader.innerHTML = '<div class="voted_twice">You already voted!</div>';
			
		} 
		else 
		{*/
		    VideoShow.RatingWebservice.AddRating(videoId, ratingValue, userId, this.createDelegate(this, this.onVideoRatingAdded));
			loader.style.display = 'block';
			loader.innerHTML = '<div class="voted">Thanks for voting!</div>';
			VideoShow.RatingWebservice.GetRating(videoId, this.createDelegate(this, this.onVideoRatingReceived));

			//var newPerc = res;
							
			/*var ulRater = $get('rater');
			ulRater.className = 'star-rating2';
			
			var all_li = ulRater.getElementsByTagName('li');
			
			for(var i=1; i < all_li.length; i++)
			{
				
				all_li[i].getElementsByTagName('a')[0].onclick = 'return false;';
				all_li[i].getElementsByTagName('a')[0].setAttribute('href','#');
				
			}
			
			if(navigator.appName == 'Microsoft Internet Explorer')
			{
				uldiv.style.setAttribute('width',newPerc+'%'); // IE
			} 
			else 
			{
				uldiv.setAttribute('style','width:'+newPerc+'%'); // Everyone else
			}*/
			
		//}
	},
	
	showShareForm: function() {
        //this._content.findname("ShareCanvas").Opacity = 0;
        //this._content.findname("ShareCanvas").Visibility = "Visible";
        var shareCanvas = this._content.findname("ShareCanvas");
        //shareCanvas["Opacity"] = 70;
        shareCanvas["Visibility"] = "Visible";
        //shareCanvas["Canvas.ZIndex"] = 120;
        $get("shareForm").style.display = "inline";
    },

    hideShareForm: function() {
        this._content.findname("ShareCanvas").Visibility = "Collapsed";
        //this._content.findname("ShareCanvas").Opacity = 0;
        $get("shareForm").style.display = "none";
    },

    /*
    createDelegate

    Helper method for delegate creation.
    */

    createDelegate: function(instance, method) {
        return function() {
            return method.apply(instance, arguments);
        };
    }
};