dojo.provide('xn.widget.video');

xn.widget.video = dojo.lang.mixin(xn.widget.video, {

    configureValidation: function(form, validate) {
        dojo.event.connect(form, 'onsubmit', function(event) {
            dojo.lang.forEach(dojo.html.getElementsByClass('validation', form), function(validationElement) { dojo.dom.removeNode(validationElement); });
            xn.widget.video.trimTextInputsAndTextAreas(form);
            var errors = validate();
            if (dojo.lang.isEmpty(errors)) { return; }
            dojo.event.browser.stopEvent(event);
            for (name in errors) {
                dojo.dom.insertBefore(dojo.html.createNodesFromText('<p class="validation">' + dojo.string.escape('html', errors[name]) + '</p>')[0], form[name]);
            }
            xn.widget.video.scrollIntoView(dojo.html.getElementsByClass('validation', form)[0]);
        });
    },

    trimTextInputsAndTextAreas: function(root) {
        dojo.lang.forEach(root.getElementsByTagName('textarea'), function(textarea) { textarea.value = dojo.string.trim(textarea.value); });
        dojo.lang.forEach(xn.widget.video.select(root.getElementsByTagName('input'), function(input) { return input.type == 'text'; }), function(textInput) { textInput.value = dojo.string.trim(textInput.value); });
    },

    // From ningbar/js/LangHelper.js  [Jon Aquino 2006-07-03]
    select: function(array, f) {
        var result = [];
        dojo.lang.forEach(array, function(item) {
            if (f(item)) { result.push(item); }
        });
        return result;
    },

    collect: function(array, f) {
        var result = [];
        dojo.lang.forEach(array, function(item) {
            result.push(f(item));
        });
        return result;
    },

    /**
     * Scrolls if necessary to bring the node into view.
     */
    scrollIntoView: function(node) {
        var nodeTop = dojo.style.getAbsoluteY(node, true);
        var nodeHeight = dojo.style.getInnerHeight(node);
        var nodeBottom = nodeTop + nodeHeight;
        var viewportTop = dojo.html.getScrollTop();
        var viewportHeight = dojo.html.getViewportHeight();
        var viewportBottom = viewportTop + viewportHeight;
        var padding = 10;
        if (nodeTop < viewportTop || padding+nodeHeight+padding > viewportHeight) {
            dj_global.scrollTo(0, Math.max(nodeTop - padding));
        } else if (nodeBottom > viewportBottom) {
            dj_global.scrollTo(0, nodeTop - Math.max(0, viewportHeight - nodeHeight) + padding);
        }
    },

    /**
     * Returns the ancestor with a position other than the default ("static").
     * Useful for absolute positioning, which is relative to this ancestor
     *
     * @see Douglas Bowman, "Making the Absolute, Relative", http://www.stopdesign.com/articles/absolute/.
     */
    positionedAncestor: function(node) {
        if (node.parentNode.tagName == 'BODY') { return node.parentNode; }
        if (dojo.style.getStyle(node.parentNode, 'position') != 'static') { return node.parentNode; }
        return xn.widget.video.positionedAncestor(node.parentNode);
    },

    /**
     * Toggles the open/closed state of a section (usuall a DIV) by making it visible/invisible
     * and changing the class of the toggling object to 'open'/'closed', respectively.
     *
     * @param toggleObj      The object that acts as the toggle, e.g. a H4 or P with an onclick
     *                       handler
     * @param idOfSectionObj The id of the section object
     * @param openText       Optional: the text of the toggle object when open
     * @param closedText     Optional: the text of the toggle object when closed
     */
    toggleSection: function(toggleObj, idOfSectionObj, openText, closedText) {
      var sectionObj = dojo.byId(idOfSectionObj);

      if (dojo.html.getClass(toggleObj) == 'open') {
        dojo.html.setClass(toggleObj, 'closed');
        if (closedText) {
            toggleObj.innerHTML = closedText;
        }
        sectionObj.style.display = 'none';
      } else {
        dojo.html.setClass(toggleObj, 'open');
        if (openText) {
            toggleObj.innerHTML = openText;
        }
        sectionObj.style.display = 'block';
      }
    },

    parseUrlParameters: function(url) {
        var urlParts   = url.split('?');
        var urlContent = new Object;

        if (urlParts.length > 1) {
            var urlPairs   = urlParts[1].split('&');

            for (var idx = 0; idx < urlPairs.length; idx++) {
                var kv = urlPairs[idx].split('=');

                urlContent[kv[0]] = kv[1];
            }
        }
        return urlContent;
    }
});

(function() {
    dojo.require("ning.hooks.tags")
    ning.hooks.viewTag = function(tag, event) {
        if (event) dojo.event.browser.stopEvent(event);
        document.location.href = '/index.php/main/video/listTagged?tag=' + encodeURIComponent(tag);
    }
}());


dojo.provide('xn.widget.video.InPlaceEditor');
dojo.widget.defineWidget('xn.widget.video.InPlaceEditor', dojo.widget.HtmlWidget, {
    // Use '<required>' as there is a Dojo bug preventing the attributes from being recognized if the defaults are instead null  [Jon Aquino 2006-07-15]
    _entity: '<required>',
    _maxLength: '<required>',
    _setValueUrl: '<required>',
    _getValueUrl: '',
    _control: 'textArea',
    _endRegexToIgnore: '',
    _html: false,
    disabled: false,
    initialized: false,
    // To do when needed: startRegexToIgnore  [Jon Aquino 2006-07-16]
    showForm: function() {
        dojo.html.hide(this.displayNode);
        dojo.html.removeClass(this.displayNode, 'in-place-editor-hover');
        // Show the form early; otherwise it will be empty in Safari (VID-323) [Jon Aquino 2006-08-14]
        dojo.html.show(this.form);
        this.textControl.value = this.displayNode.innerHTML.replace(this.end, '');
        // Use stripTags to normalize the comparison in IE  [Jon Aquino 2006-08-12]
        if (this.stripTags(this.textControl.value) == this.stripTags(this.instruction())) { this.textControl.value = ''; }
        if (! this._html) { this.textControl.value = this.stripTags(this.textControl.value); }
        else { this.textControl.value = this.textControl.value.replace(/<br ?.?>\n/gi, "\n") }
        this.textControl.focus();
    },
    hideForm: function() {
        dojo.html.hide(this.form);
        dojo.html.show(this.displayNode);
    },
    stripTags: function(x) {
        return dojo.html.renderedTextContent(dojo.html.createNodesFromText('<div>' + x + '</div>')[0])
    },
    fillInTemplate: function(args, frag) {
        this.displayNode = this.getFragNodeRef(frag);
        this.displayNode.title = 'Click to edit';
        // Ignore case, as IE uppercases tags  [Jon Aquino 2006-07-15]
        var endMatch = new RegExp(this._endRegexToIgnore, 'i').exec(this.displayNode.innerHTML);
        this.end = endMatch ? endMatch[0] : '';
        this.setDisplayHtml(this.displayNode.innerHTML);
        dojo.html.addClass(this.displayNode, 'in-place-editor');
        dojo.event.connect(this.displayNode, 'onmouseover', dojo.lang.hitch(this, function() {
            dojo.html.addClass(this.displayNode, 'in-place-editor-hover');
        }));
        dojo.event.connect(this.displayNode, 'onmouseout', dojo.lang.hitch(this, function() {
            dojo.html.removeClass(this.displayNode, 'in-place-editor-hover');
        }));
        dojo.event.connect(this.displayNode, 'onclick', dojo.lang.hitch(this, function() {
            this.initializeIfNecessary();
            if (this.disabled) { return; }
            this.originalDisplayHtml = this.displayNode.innerHTML;
            if (this._getValueUrl == '') {
                this.showForm();
            } else {
                this.disabled = true;
                this.displayNode.innerHTML = '<span class="instruction">Loading...</span>';
                dojo.io.bind({
                    encoding: 'utf-8',
                    url: this._getValueUrl,
                    preventCache: true,
                    mimetype: 'text/javascript',
                    load: dojo.lang.hitch(this, function(type, data, event){
                        this.setDisplayHtml(data.html);
                        this.showForm();
                        this.disabled = false;
                    })
                });
            }
        }));
    },
    initializeIfNecessary: function() {
        if (this.initialized) { return; }
        this.initialized = true;
        var div = dojo.html.createNodesFromText(dojo.string.trim(' \
            <div class="in-place-editor"> \
                <form style="display:none"> \
                    <textarea rows="5"></textarea> \
                    <input type="image" class="inputImage" src="/images/save_button.gif" alt="Save" /> \
                    <input type="image" class="inputImage" src="/images/cancel_button.gif" alt="Cancel" />' +
                    (this._html ? '&nbsp;<span class="smallgridtext">Some HTML is allowed</span>' : '') +
                '</form> \
            </div>'))[0];
        dojo.dom.insertAfter(div, this.displayNode);
        this.form = div.getElementsByTagName('form')[0];
        this.textControl = div.getElementsByTagName('textarea')[0];
        this.saveButton = div.getElementsByTagName('input')[0];
        this.cancelButton = div.getElementsByTagName('input')[1];
        if (this._control == 'textInput') {
            var oldTextControl = this.textControl;
            this.textControl = dojo.html.createNodesFromText('<input type="text" class="inputText" maxLength="' + this._maxLength + '" />')[0];
            oldTextControl.parentNode.replaceChild(this.textControl, oldTextControl);
        }
        dojo.event.connect(this.cancelButton, 'onclick', dojo.lang.hitch(this, function(event) {
            dojo.event.browser.stopEvent(event);
            this.setDisplayHtml(this.originalDisplayHtml);
            this.hideForm();
        }));
        dojo.event.connect(this.saveButton, 'onclick', dojo.lang.hitch(this, function(event) {
            dojo.event.browser.stopEvent(event);
            if (this.disabled) { return; }
            this.disabled = true;
            this.displayNode.innerHTML = '<span class="instruction">Saving...</a>';
            this.hideForm();
            this.textControl.value = dojo.string.trim(this.textControl.value).substr(0, this._maxLength);
            var params = xn.widget.video.parseUrlParameters(this._setValueUrl);
            params['value'] = this.textControl.value;
            dojo.io.bind({
                url: this._setValueUrl,
                content: params,
                method: "post",
                encoding: 'utf-8',
                preventCache: true,
                mimetype: 'text/javascript',
                load: dojo.lang.hitch(this, function(type, data, event){
                    this.setDisplayHtml(data.html);
                    this.disabled = false;
                    this._getValueUrl = '';
                })
            });
        }));
        dojo.event.connect(this.form, 'onsubmit', dojo.lang.hitch(this, function(event) {
            dojo.event.browser.stopEvent(event);
            this.saveButton.click();
        }));
    },
    setDisplayHtml: function(displayHtml) {
        displayHtml = dojo.string.trim(displayHtml.replace(this.end, ''));
        if (displayHtml.length == 0) {
            displayHtml = this.instruction();
        }
        this.displayNode.innerHTML = displayHtml + this.end;
        // If the person clicks a link, don't show the in-place editor  [Jon Aquino 2006-08-05]
        dojo.lang.forEach(this.displayNode.getElementsByTagName('a'), dojo.lang.hitch(this, function(a) {
            // Use a.onclick instead of dojo.event.connect; otherwise IE throws
            // "TypeError: '__clobberAttrs__' is null or not an object" for some reason  [Jon Aquino 2006-08-05]
            a.onclick = dojo.lang.hitch(this, function() {
                this.disabled = true;
                dojo.lang.setTimeout(dojo.lang.hitch(this, function() {
                    this.disabled = false;
                }), 1000);
            });
        }));
    },
    instruction: function() {
        return '<span class="instruction">[click to add ' + this._entity + ']</span>';
    }
});


dojo.provide('xn.widget.video.AutoUpdatingText');
// A "behavior widget"--doesn't replace the source element. Made so by omitting the template.  [Jon Aquino 2006-07-18]
dojo.widget.defineWidget('xn.widget.video.AutoUpdatingText', dojo.widget.HtmlWidget, {
    _url: '<required>',
    _urls: '',
    _highlightColor: '',
    fillInTemplate: function(args, frag) {
        
        var node = this.getFragNodeRef(frag);
        var urls = new Array();

        if (this._urls && this._urls.length > 0) {
            urls = this._urls.split(' ');
        } else {
            urls.push(this._url);
        }
        dojo.event.connect('before', dojo.io, 'bind', dojo.lang.hitch(this, function(kwArgs) {
            var url_match = false;
            for (var i=0; i < urls.length; i++){
                if (urls[i].indexOf(kwArgs.url) >= 0){
                    url_match = true;
                    break;
                }
            }
            if ('url' in kwArgs && url_match) {
                dojo.event.connect(kwArgs, 'load', dojo.lang.hitch(this, function(type, data, event) {
                    if ('html' in data) {
                        dojo.require("dojo.fx.*");
                        node.innerHTML = data.html;
                        xn.widget.video.fixImagesInIE(node.getElementsByTagName('img'));
                        if (this._highlightColor.length > 0) { dojo.fx.html.highlight(node, 2000, this._highlightColor); }
                    }
                }));
            }
        }));
    }
});


dojo.provide('xn.widget.video.ActionButton');
dojo.widget.defineWidget('xn.widget.video.ActionButton', dojo.widget.HtmlWidget, {
    showDialog: function(dialog) {
        if (dojo.html.hasClass(this.actionbar(), 'xn_actionbutton')) {
            var positionedAncestor = xn.widget.video.positionedAncestor(this.actionButton);
            var positionedAncestorTop = dojo.style.getAbsoluteY(positionedAncestor, true);
            var positionedAncestorLeft = dojo.style.getAbsoluteX(positionedAncestor, true);
            var buttonTop = dojo.style.getAbsoluteY(this.actionButton, true);
            var buttonLeft = dojo.style.getAbsoluteX(this.actionButton, true);
            var buttonHeight = dojo.style.getInnerHeight(this.actionButton);
            dialog.style.top = (buttonTop - positionedAncestorTop + buttonHeight) + 'px';
            dialog.style.left = (buttonLeft - positionedAncestorLeft) + 'px';
        }
        this.hideDialog();
        dojo.html.insertAtPosition(dialog, this.actionbar(), 'last');
        dojo.html.addClass(this.actionButton, 'active');
        xn.widget.video.scrollIntoView(dialog);
    },
    hideDialog: function() {
        dojo.lang.forEach(dojo.html.getElementsByClass('dialog', this.actionbar()), function(dialog) { dojo.dom.removeNode(dialog); });
        dojo.lang.forEach(dojo.html.getElementsByClass('active', this.actionbar()), function(actionButton) { dojo.html.removeClass(actionButton, 'active'); });
    },
    showAndFadeDialog: function(dialog, after) {
        dojo.require("dojo.lfx.*");
        this.showDialog(dialog);
        dojo.lfx.fadeOut(dialog, 500, dojo.lfx.easeIn, dojo.lang.hitch(this, function() {
            // VID-211  [Jon Aquino 2006-08-09]
            this.hideDialog();
            if (after) { after(); }
        })).play();
    },
    actionbar: function() {
        return this.actionbarProper(this.actionButton);
    },
    actionbarProper: function(node) {
        if (dojo.html.hasClass(node, 'xn_actionbar')) { return node; }
        if (dojo.html.hasClass(node, 'xn_actionbutton')) { return node; }
        return this.actionbarProper(node.parentNode);
    },
    init: function(frag) {
        this.actionButton = this.getFragNodeRef(frag);
    }
});


dojo.provide('xn.widget.video.AddRemoveButton');
dojo.widget.defineWidget('xn.widget.video.AddRemoveButton', xn.widget.video.ActionButton, {
    _addUrl: '<required>',
    _removeUrl: '<required>',
    _collection: '<required>',
    _dialogClass: 'dialog',
    _signedIn: true,
    _signInUrl: '<required>',
    _collectionUrl: '<required>',
    _hideAfterAdd: false,

    fillInTemplate: function(args, frag) {
        this.init(frag);
        dojo.event.connect(this.actionButton.getElementsByTagName('a')[0], 'onclick', dojo.lang.hitch(this, function(event) {
            dojo.event.browser.stopEvent(event);
            if (dojo.html.hasClass(this.actionButton, 'disabled')) { return; }
            if (!this._signedIn) {document.location.href=this._signInUrl;return;}
            if (! dojo.html.hasClass(this.actionButton, 'added')) {
                this.add();
                if (this._hideAfterAdd) { dojo.html.hide(this.actionButton); }
            } else {
                this.remove();
            }
        }));
    },
    add: function() {
        dojo.html.addClass(this.actionButton, 'added');
        this.setShowingAddedImage(true);
        this.setShowingAddedSpan(true);
        var dialog = dojo.html.createNodesFromText(dojo.string.trim(' \
            <div class="' + this._dialogClass + '"> \
                <h4>Added!</h4> \
            </div>'))[0];
        this.showAndFadeDialog(dialog);
        dojo.io.bind({
            encoding:'utf-8',
            url: this._addUrl,
            preventCache: true,
            mimetype: 'text/javascript',
            method: 'post'
        });
    },
    remove: function() {
        dojo.html.removeClass(this.actionButton, 'added');
        this.setShowingAddedImage(false);
        this.setShowingAddedSpan(false);
        var dialog = dojo.html.createNodesFromText(dojo.string.trim(' \
            <div class="' + this._dialogClass + '"> \
                <h4>Removed!</h4> \
            </div>'))[0];
        this.showAndFadeDialog(dialog);
        dojo.io.bind({
            encoding:'utf-8',
            url: this._removeUrl,
            preventCache: true,
            mimetype: 'text/javascript',
            method: 'post'
        });
    },
    /**
     * @param showingAddedImage Whether to show the added-image or the original image
     */
    setShowingAddedImage: function(showingAddedImage) {
        dojo.lang.forEach(this.actionButton.getElementsByTagName('img'), function(img) {
            dojo.html.setShowing(img, !showingAddedImage);
        });
        dojo.html.setShowing(dojo.html.getElementsByClass('added-image', this.actionButton)[0], showingAddedImage);
    },
    /**
     * @param showingAddedSpan Whether to show the added-span or the original span
     */
    setShowingAddedSpan: function(showingAddedSpan) {
        dojo.lang.forEach(this.actionButton.getElementsByTagName('span'), function(span) {
            dojo.html.setShowing(span, !showingAddedSpan);
        });
        dojo.html.setShowing(dojo.html.getElementsByClass('added-span', this.actionButton)[0], showingAddedSpan);
    }
});


dojo.provide('xn.widget.video.ShowEmailLink');
dojo.widget.defineWidget('xn.widget.video.ShowEmailLink', xn.widget.video.ActionButton, {
    fillInTemplate: function(args, frag) {
        this.init(frag);
        dojo.event.connect(this.actionButton, 'onclick', dojo.lang.hitch(this, function(event) {
            dojo.event.browser.stopEvent(event);
            if (dojo.html.hasClass(this.actionButton, 'active')) {
                this.hideDialog();
                return;
            }
            var dialog = dojo.html.createNodesFromText(dojo.string.trim(' \
                <div class="neutral dialog"> \
                    <p><a href="' + dojo.string.escape('html', this.actionButton.href) + '">' + dojo.string.escape('html', this.actionButton.href).replace(/mailto./, '') + '</a></p> \
                    <p class="close"><a href="javascript:void(0)">Close</a></p> \
                </div>'))[0];
            this.showDialog(dialog);
            var cancelLink = dialog.getElementsByTagName('a')[1];
            dojo.event.connect(cancelLink, 'onclick', dojo.lang.hitch(this, function() {
                this.hideDialog();
            }));
        }));
    }
});

xn.widget.video.openNingbarPanel = function(name) {
    ning.Bar.open(name);
    top.window.scrollTo(0, 0);
}

xn.widget.video.openProfile = function(screenName) {
    ning.hooks.viewProfile(screenName);
    top.window.scrollTo(0, 0);
}

xn.widget.video.openSendMessageBox = function(screenName) {
    if (ning.CurrentProfile) {
        ning.social.openSendMessageBox(ning.Bar.open('user').getAlerter(), screenName);
        top.window.scrollTo(0, 0);
    } else {
        window.location.replace('/index.php/main/index/sign?target=' + encodeURIComponent(window.location.href));
    }
}

xn.widget.video.sendFriendRequest = function(screenName) {
    // TODO: implement callbacks to show fading pop ups
    ning.social.sendFriendRequest(screenName, {
        success : function(relationshipStatus) {},
        error: function(errors) {}
    });
}

/**
 * Makes an <a> do a post submission. Useful for delete links, which if implemented
 * as a get would be at risk of inadvertent execution by search robots.
 */
dojo.provide('xn.widget.video.PostLink');
dojo.widget.defineWidget('xn.widget.video.PostLink', dojo.widget.HtmlWidget, {
    _url: '<required>',
    fillInTemplate: function(args, frag) {
        var a = this.getFragNodeRef(frag);
        dojo.event.connect(a, 'onclick', dojo.lang.hitch(this, function(event) {
            dojo.event.browser.stopEvent(event);
              dojo.io.bind({
                encoding:'utf-8',
                url: this._url,
                method: 'post',
                load: function(type, data, evt) {
                  window.location.reload(true);
                }
              });
        }));
    }
});

dojo.provide('xn.widget.video.MessageSender');
dojo.widget.defineWidget('xn.widget.video.MessageSender', dojo.widget.HtmlWidget, {
    _screenName: '<required>',
    fillInTemplate: function(args, frag) {
        var a = this.getFragNodeRef(frag);
        dojo.event.connect(a, 'onclick', dojo.lang.hitch(this, function(event) {
            dojo.event.browser.stopEvent(event);
            xn.widget.video.openSendMessageBox(this._screenName);
        }));
    }
});

dojo.provide('xn.widget.video.FriendRequestButton');
dojo.widget.defineWidget('xn.widget.video.FriendRequestButton', xn.widget.video.ActionButton, {
    _screenName: '<required>',
    _successNodeId: '<required>',
    fillInTemplate: function(args, frag) {
        this.init(frag);
        var a = this.getFragNodeRef(frag);
        dojo.event.connect(a, 'onclick', dojo.lang.hitch(this, function(event) {
            dojo.event.browser.stopEvent(event);
            xn.widget.video.sendFriendRequest(this._screenName);
            var dialog = dojo.html.createNodesFromText(dojo.string.trim(' \
                <div class="dialog"> \
                    <p>Friend request sent to ' + this._screenName + '</p> \
                </div>'))[0];
            this.showAndFadeDialog(dialog, dojo.lang.hitch(this, function() {
                dojo.html.hide(this.actionbar());
                dojo.html.show(dojo.dom.nextElement(this.actionbar()));
            }));
        }));
    }
});


// Does an AJAX POST to the given delete url and upon success
// redirects to the given target url
xn.widget.video.deleteObject = function(id, deleteUrl, targetUrl, message) {
  if (!confirm(message ? message : 'Delete this video?')) {
    return;
  }

  dojo.io.bind({
    encoding:'utf-8',
    url     : deleteUrl,
    method  : "post",
    content : { id : id },
    load    : function(type, data, evt) {
      location.href = targetUrl;
    }
  });
};

xn.widget.video.playerFullscreenButtonClicked = function() {
    newwindow = dojo.render.html.ie ? window.open('','ningvideo','fullscreen,resizable=1') : window.open('','ningvideo','resizable=1,height='+screen.height+',width='+screen.width);
    if (newwindow == null) {
        // Popup blocked.  [Jon Aquino 2006-08-21]
        return;
    }
    var player_url = '/flvplayer/flvplayer.swf?video_url='+encodeURIComponent(dojo.byId('video-url').value)+'&frame_url='+encodeURIComponent(dojo.byId('frame-url').value)+'&autoplay=on&controller_inside=on&footer=off&';
    if (window.focus) {newwindow.focus()}
    // Don't set original window to detail page, as that will cause the full-screen video to stutter (VID-445)  [Jon Aquino 2006-09-08]
    var html = '<html><body style=\"background:#000000;margin:0px;padding:0px\">';
    html += "<div id=\"video\" style=\"width:100%;height:100%;\">"
    html += "<object type=\"application/x-shockwave-flash\"width=\"100%\" height=\"100%\"data=\""+player_url+"\"><param name=\"movie\" value=\""+player_url+"\" /><param name=\"scale\" value=\"noscale\" /><param name=\"bgcolor\" value=\"#000000\" /></object></div>";
    html += '</div></body></html>';
    newwindow.document.write(html);
    newwindow.document.close();
    return;
}

xn.widget.video.parseWidgets = function(root) {
    root = root != null ? root : dojo.byId('container');
    djConfig.parseWidgets = false;
    var parser = new dojo.xml.Parse();
    var frag = parser.parseElement(root, null, true);
    dojo.widget.getParser().createComponents(frag);
}
