// Basic HTML builder for search results
// @author Daniel Lichtenberger, UCS


// ////////////////////////////////////////////////
// ----------------- ResultHtmlBuilder ------------
// ////////////////////////////////////////////////
//
// Base implementation of the HTML generator for search results.
// Layout changes are primarily done by modifying the styles/class in ResultHtmlBuilder#styles
// or changing the associated CSS classes, but more intrusive changes may
// be done by overriding single methods, i.e. pushPropertyTable.
//

function ResultHtmlBuilder() {
    this.searchResult = null;
    this.resultRow = null;
    this.tableCtr = 0;  // property table counter
}

ResultHtmlBuilder.prototype.init = function() {
    this.styles = {
            propertyTableRow:       {styleClass: "row propertyCell"},       // instance property row (list/screenview)
            listRow:                {styleClass: "listRow"},                // list row (containing an instance in list view)
            listThumbnail:          {styleClass: "listThumbnail"},              // thumbnail table cell container
            thumbnailContainer:     {styleClass: "thumbnailContainer"},     // thumbnail container (containing thumbnail + labels + buttons)
            thumbnailHeader:        {styleClass: "thumbLabelHeader"},       // thumbnail header (label above thumbnail)
            thumbnailFooter:        {styleClass: "thumbLabelFooter"},       // thumbnail footer (label below thumbnail)
            thumbnail:              {styleClass: "thumbnail"},              // the thumbnail image itself including buttons (style without borders)
            thumbnailWithBorders:   {styleClass: "thumbnailBorder"},        // the thumbnail image itself including buttons (style with borders)
            screenviewTable:        {styleClass: "instancedetail"},         // table style for screenview image + displayed properties

            propertyLabel:          {styleClass: "resultLabel"},            // label of an instance property (list/screenview)
            propertyValueWithLabel: {styleClass: "resultValue resultLabelOffset"},  // value of an instance property (label displayed)
            propertyValueWithoutLabel: {styleClass: "resultValue"},         // value of an instance propert (without label)

            propertyTableButtons:   {style: "float:right"},                 // buttons for the property table (list/screenview)
            listButtons:            {style: "float:right"},                 // buttons in list view (without property table - i.e. topics view or a single property without label)
            thumbnailButtons:       {styleClass: "thumbFooter"},            // buttons for thumbnails

            textLink:               {styleClass: "main"}                    // "instance" link (to open the instance (KO) or the screenview (MO)
    };
    // miscellaneous dimensions (in pixels)
    this.dimensions = {
            containerPadding: 5,            // padding of the thumbnail container
            imagePadding: 3,                // padding of the thumbnail image itself
            thumbLabelHeight: 20,           // height of a single thumbnail label row
            thumbButtonRowHeight: 20        // height of thumbnail buttons row
    }
}

/**
 * Render HTML class and style attributes for the given style
 * (see ResultHtmlBuilder.styles).
 */
ResultHtmlBuilder.prototype.getStyleHtml = function(style, additionalStyleAttributes) {
    var out = ""
    var styleAttributes = style.style ? style.style : "";
    if (additionalStyleAttributes) {
        styleAttributes += additionalStyleAttributes;
    }
    if (style.styleClass) {
        out += "class=\"" + style.styleClass + "\" ";
    }
    if (styleAttributes != "") {
        out += "style=\"" + styleAttributes + "\" ";
    }
    return out;
}

/**
 * Open a div container with the given style.
 */
ResultHtmlBuilder.prototype.startStyledDiv = function(out, style, additionalStyleAttributes) {
    out.push("<div " + this.getStyleHtml(style, additionalStyleAttributes) + ">");
}

/**
 * Render a div container with the given style and content.
 */
ResultHtmlBuilder.prototype.pushStyledDiv = function(out, style, additionalStyleAttributes, content) {
    this.startStyledDiv(out, style, additionalStyleAttributes);
    out.push(content);
    out.push("</div>");
}

ResultHtmlBuilder.prototype.pushKeywords = function(out,keywords,keywordsPos,topics,topicsPos,pos) {
    if (this.searchResult.viewType == "screenview") {
        // write out links to keywords
        if (keywords != null && keywordsPos == pos) {
            this.startStyledDiv(out, this.styles.propertyTableRow);
            this.pushStyledDiv(out, this.styles.propertyLabel, null,searchResult.msg.keywords);
            this.startStyledDiv(out, this.styles.propertyValueWithLabel);
            var inputId = "keywords_" + this.tableCtr + "_";
            out.push("<div id=\"instancekeywords\"><ul>");
            for (var j in keywords) {
                out.push("<li><input type=\"checkbox\" class=\"noborder\" id=\"" + inputId + j + "\"/ value=\"" + keywords[j] + "\">"
                        + "<label class=\"keywords\" for=\"" + inputId + j + "\">" + keywords[j] + "</label></li>")
            }
            out.push("</ul></div>");
            out.push("<div id=\"instancetopics\"><ul><li><a href=\"javascript:getTop().keywordQuery(document, '" + inputId + "')\">" + searchResult.msg.keywordQuery + "</a></li></ul></div>");
            out.push("</div></div>");
        }
    }
}
ResultHtmlBuilder.prototype.pushTopics = function(out,keywords,keywordsPos,topics,topicsPos,pos) {
    if (this.searchResult.viewType == "screenview") {
        // write out links to topics, if there are any topics related to this MO
        if (topics != null && topicsPos == pos){
            this.startStyledDiv(out, this.styles.propertyTableRow);
            this.pushStyledDiv(out, this.styles.propertyLabel, null,searchResult.msg.topics);
            this.startStyledDiv(out, this.styles.propertyValueWithLabel);
            out.push("<div id=\"instancetopics\"><ul>");
            for(var j in topics){
                if(topics[j].oid != null && topics[j].oid != "" && topics[j].name != null && topics[j].name != ""){
                    out.push("<li><a href=\"" + getBase() + "instance.do?action=instance.load&id=" +topics[j].oid + "\">" + topics[j].name + "</a></li>");
                }
            }
            out.push("</ul></div></div></div>");
        }
    }
}

/**
 * Render the property table (containing the instance properties in list and screenview mode).
 */
ResultHtmlBuilder.prototype.pushPropertyTable = function(out, data, labels, topics, showEmpty, href, tooltip, target, tableAlign, tableWidth, keywords, keywordsPos, topicsPos,keywordsBeforeTopics) {
    if (data == null)
        return;
    this.tableCtr++;
    var hasContainer = false;
    if (tableAlign != null || tableWidth != null) {
        // start container div
        out.push("<div style=\"");
        if (tableAlign != null) out.push("float:" + tableAlign + ";");
        if (tableWidth != null) out.push("width:" + tableWidth + "px;");
        out.push("\">");
        hasContainer = true;
    }
    var pos = 0;
    for (var i in data) {
        if (keywordsBeforeTopics) {
            if (keywordsPos >= 0)
                this.pushKeywords(out,keywords,keywordsPos,topics,topicsPos,pos);
            if (topicsPos >= 0)
                this.pushTopics(out,keywords,keywordsPos,topics,topicsPos,pos);
        } else {
            if (topicsPos >= 0)
                this.pushTopics(out,keywords,keywordsPos,topics,topicsPos,pos);
            if (keywordsPos >= 0)
                this.pushKeywords(out,keywords,keywordsPos,topics,topicsPos,pos);
        }
        if (data[i] == this.searchResult.emptyFieldMessage && !showEmpty[i]) {
            // property should not be displayed if empty, continue
        } else {
            this.startStyledDiv(out, this.styles.propertyTableRow);
            if (this.searchResult.showListLabels) {
                // print label
                this.pushStyledDiv(out, this.styles.propertyLabel, null, labels[i]);
            }
            this.startStyledDiv(out, this.resultRow.showListLabels ? this.styles.propertyValueWithLabel : this.styles.propertyValueWithoutLabel);
            if (i == 0 && href != null && !this.searchResult.printMode) {
                // add download/order buttons
                this.pushStyledDiv(out, this.styles.propertyTableButtons, null, this.getButtons());
                // add data with link
                out.push("<a href=\"" + href + "\"" + target + " title=\"" + tooltip + "\" "
                        + this.getStyleHtml(this.styles.textLink) + ">" + data[i] + "</a>");
            } else {
                out.push(data[i]);
            }
            out.push("&nbsp;</div></div>");
        }
        pos++;
    }

    if (keywordsBeforeTopics) {
        if (keywordsPos == pos)
            this.pushKeywords(out,keywords,keywordsPos,topics,topicsPos,pos);
        if (topicsPos == pos)
            this.pushTopics(out,keywords,keywordsPos,topics,topicsPos,pos);
    } else {
        if (topicsPos == pos)
            this.pushTopics(out,keywords,keywordsPos,topics,topicsPos,pos);
        if (keywordsPos == pos)
            this.pushKeywords(out,keywords,keywordsPos,topics,topicsPos,pos);
    }

    //only write buttons if not overwritten (demoDB)
    if (this.searchResult.viewType == "screenview" && this.getButtons().length == 0 && !this.searchResult.printMode)
        out.push("<div style=\"padding-top:10px;padding-left:5px\" align=\"left\">"+this.getButtons(true)+"</div>");
    out.push("<div style=\"clear:both\"></div>");
    if (hasContainer) {
        out.push("</div>");
    }
}

/**
 * Get the active buttons for the current instance (this.resultRow).
 */
ResultHtmlBuilder.prototype.getButtons = function() {
    if (this.searchResult.viewType == "screenview") {
        return this._getCartTextLink() + this._getDownloadTextLink() + this._getLightBoxTextLink();
    } else {
        return this._getCartButton() + this._getDownloadButton() + this._getLightBoxButton();
    }
}

/**
 * Update the shopping cart icon for the current result row
 */
ResultHtmlBuilder.prototype.updateCartIcon = function() {
    var doc = this.searchResult.getResultDocument();
    var cartLink = doc.getElementById("cart" + this.resultRow.oid);
    var cartImage = doc.getElementById("cart" + this.resultRow.oid + ".image");
    if (cartLink == null || cartImage == null) {
        return;
    }
    // update img
    cartImage.src = this._getCartImage();
    cartImage.setAttribute("alt", this._getCartTooltip());
    // update link
    cartLink.setAttribute("title", this._getCartTooltip());
    cartLink.setAttribute("href", this._getCartLink());
}

/**
 * Update the lightbox icon for the current result row
 */
ResultHtmlBuilder.prototype.updateLightBoxIcon = function() {
    var doc = this.searchResult.getResultDocument();
    var lbLink = doc.getElementById("lightbox" + this.resultRow.oid);
    var lbImage = doc.getElementById("lightbox" + this.resultRow.oid + ".lbimage");
    if (lbLink == null || lbImage == null) {
        return;
    }
    // update img
    lbImage.src = this._getLightBoxImage();
}

/**
 * Get the shopping cart button for the current instance (this.resultRow).
 */
ResultHtmlBuilder.prototype._getCartButton = function() {
    return this.searchResult.enableCart ?
           "<a id=\"cart" + this.resultRow.oid + "\" href=\"" + this._getCartLink() + "\" title=\""
                   + this._getCartTooltip() + "\"><img id=\"cart" + this.resultRow.oid + ".image\" src=\""
                   + this._getCartImage() + "\" border=\"0\" alt=\"" + this._getCartTooltip() + "\"></a>"
            : "";
}

/**
 * Get the download button for the current instance (this.resultRow).
 */
ResultHtmlBuilder.prototype._getDownloadButton = function() {
    var inlineDownload = this.resultRow.inlineDownloadAllowed
            ? "<a href=\"" + this._getInlineDownloadLink() + "\" target=\"_blank\" title=\"" + this.searchResult.msg.downloadInlineButton + "\"><img src=\"images/download.inline.gif\" border=\"0\" alt=\"" + this.searchResult.msg.downloadInlineButton + "\"></a>"
            : "";
    return this.resultRow.showDownloadButton ?
           inlineDownload+"<a href=\"" + this._getDownloadLink() + "\" title=\"" + this.searchResult.msg.downloadButton + "\"><img src=\"images/download.gif\" border=\"0\" alt=\"" + this.searchResult.msg.downloadButton + "\"></a>"
            : "";
}

ResultHtmlBuilder.prototype._getLightBoxButton = function() {
    if (this.searchResult.enableLightBox) {
        return "<a id=\"lightbox" + this.resultRow.oid + "\" href=\"" + this._getLightBoxLink() + "\" title=\"" + this._getLightBoxTooltip() + "\"><img id=\"lightbox" +
               this.resultRow.oid + ".lbimage\" src=\"" + this._getLightBoxImage() + "\" border=\"0\" alt=\"" + this._getLightBoxTooltip() + "\"></a>"
    }
    return this.searchResult.enableRemoveFromLightBox ?
            "<a id=\"remLightbox" + this.resultRow.oid + "\" href=\"" + this._getRemoveFromLightBoxLink() + "\" title=\""  + this._getLightBoxTooltip() + "\"><img id=\"remLightbox" +
                this.resultRow.oid + ".lbimage\" src=\"" + this._getRemoveFromLightBoxImage() + "\" border=\"0\" alt=\"" + this._getLightBoxTooltip() + "\"></a>"
           : "";
}

/**
 * Lightbox
 */
ResultHtmlBuilder.prototype._getLightBoxImage = function() {
    var frame = window;
    var result = top;
    while (frame.parent != null) {
        try {
            if (frame.portalContainerFrame) {
                result = frame;
            }
            if (frame == top) {
                break;
            }
            frame = frame.parent;
        } catch (e) {
            break;
        }
    }
    return result.lightBoxHasOid(this.resultRow.oid) ? "images/lightbox_on.gif" : "images/lightbox.gif";
}

ResultHtmlBuilder.prototype._getLightBoxTooltip = function() {
    var frame = window;
    var result = top;
    while (frame.parent != null) {
        try {
            if (frame.portalContainerFrame) {
                result = frame;
            }
            if (frame == top) {
                break;
            }
            frame = frame.parent;
        } catch (e) {
            break;
        }
    }
    return result.lightBoxHasOid(this.resultRow.oid) ? this.searchResult.msg.removeFromLightBox : this.searchResult.msg.addToLightBox;
}

ResultHtmlBuilder.prototype._getRemoveFromLightBoxImage = function() {
    return "images/lightbox_on.gif"
}

/**
 * Returns the cart image URI for the current row
 **/
ResultHtmlBuilder.prototype._getCartImage = function() {
    return getTop().cartHasOid(this.resultRow.oid) ? "images/cart_on.gif" : "images/cart.gif";
}

/**
 * Returns the cart image tooltip for the current row
 */
ResultHtmlBuilder.prototype._getCartTooltip = function() {
    if (this.resultRow.licenseTypeId != null) {
        return getTop().cartHasOid(this.resultRow.oid) ? this.searchResult.msg.inCart : this.searchResult.msg.addToCartEuro;
    }
    else
        return getTop().cartHasOid(this.resultRow.oid) ? this.searchResult.msg.inCart : this.searchResult.msg.addToCart;
}

/**
 * Returns a text link for adding the current row to the shopping cart
 */
ResultHtmlBuilder.prototype._getCartTextLink = function() {
    return this.searchResult.enableCart ?
           "<a href=\"" + this._getCartLink() + "\" " + this.getStyleHtml(this.styles.textLink) + " title=\"" + this.searchResult.msg.addToCart + "\">"
            + this.searchResult.msg.addToCart + "</a>&nbsp;&nbsp;&nbsp;&nbsp;"
           : "";
}

/**
 * Returns text links for normal and inline download of the current row
 */
ResultHtmlBuilder.prototype._getDownloadTextLink = function() {
    var inlineDownload = this.resultRow.inlineDownloadAllowed
            ? "<a href=\"" + this._getInlineDownloadLink() + "\" target=\"_blank\"" + this.getStyleHtml(this.styles.textLink) + " title=\"" + this.searchResult.msg.downloadInlineButton + "\">"
            + this.searchResult.msg.downloadInlineButton + "</a>" + "&nbsp;&nbsp;&nbsp;&nbsp;"
              : "";
    return this.resultRow.showDownloadButton ?
        inlineDownload + "<a href=\"" + this._getDownloadLink() + "\"" + this.getStyleHtml(this.styles.textLink) + " title=\"" + this.searchResult.msg.downloadButton + "\">" + this.searchResult.msg.downloadButton + "</a>"
        : "";
}

ResultHtmlBuilder.prototype._getLightBoxTextLink = function() {
    if (this.searchResult.enableLightBox) {
        return  "<a href=\"" + this._getLightBoxLink() + "\" " + this.getStyleHtml((getTop().lightBoxHasOid(this.resultRow.oid)?this.styles.lightboxRemove:this.styles.lightboxAdd)) + " title=\"" + (getTop().lightBoxHasOid(this.resultRow.oid)?this.searchResult.msg.removeFromLightBox:this.searchResult.msg.addToLightBox) + "\">"
                + (getTop().lightBoxHasOid(this.resultRow.oid)?this.searchResult.msg.removeFromLightBox:this.searchResult.msg.addToLightBox) + "</a>&nbsp;&nbsp;&nbsp;&nbsp;";
    }
    return this.searchResult.enableRemoveFromLightBox ?
           "<a href=\"" + this._getRemoveFromLightBoxLink() + "\" " + this.getStyleHtml(this.styles.lightboxRemove) + " title=\"" + this.searchResult.msg.removeFromLightBox + "\">"
            + this.searchResult.msg.removeFromLightBox + "</a>&nbsp;&nbsp;&nbsp;&nbsp;"
           : "";
}

/**
 * Returns the javascript link for the shopping cart button
 */
ResultHtmlBuilder.prototype._getCartLink = function() {
    return "javascript:getTop().addToCart(" + this.resultRow.oid + ", false, true)";
}

ResultHtmlBuilder.prototype._getLightBoxLink = function() {
    return "javascript:getTop().addToLightBox(" + this.resultRow.oid +")";
}

ResultHtmlBuilder.prototype._getRemoveFromLightBoxLink = function() {
    return "javascript:getTop().removeFromLightBox(" + this.resultRow.oid +")";
}

ResultHtmlBuilder.prototype._getInlineDownloadLink = function() {
    return getBase() + "FineData?oid=" + this.resultRow.oid + "&version=" + this.resultRow.version + "&type=mars&inline=1";
}

ResultHtmlBuilder.prototype._getDownloadLink = function() {
    return "javascript:getTop().downloadFineData('" + getBase() + "FineData?oid=" + this.resultRow.oid + "&version=" + this.resultRow.version + "&type=mars');";
}