/*
#---------------------------------------------------------------------------
# Copyright   : rexx systems GmbH, 20097 Hamburg, Heidenkampsweg 101
#               Veraenderung oder Nutzung der Scripte/Anwendung ist nur mit
#               schriftlicher Genehmigung der rexx systems GmbH gestattet.
#
# $Id: zoomer.js,v 1.31 2011-12-28 12:06:43 lutz Exp $
#---------------------------------------------------------------------------
*/

var zoomerJs = (function () {

    /*
     * articlePicture Objekt, wird fuer alle Bilder via php instanziert
     * und in zoomerJs.pictures abgelegt
     *
     * @param ...
     */
    function ArticlePicture(position, text, thumbUrl, thumbWidth, thumbHeight, prevUrl, prevWidth, prevHeight, fullUrl, zoomUrl, colorId) {
        this.position    = position;
        this.text        = text;
        this.thumbUrl    = thumbUrl;
        this.thumbWidth  = thumbWidth;
        this.thumbHeight = thumbHeight;
        this.prevUrl     = prevUrl;
        this.prevWidth   = prevWidth;
        this.prevHeight  = prevHeight;
        this.fullUrl     = fullUrl;
        this.zoomUrl     = zoomUrl;
        this.colorId     = colorId;

        this.width  = 0;
        this.height = 0;
        this.setSize = function (w, h) {
            this.width  = w;
            this.height = h;
        };

        // typ sollte Image sein ( new Image() )
        this.fullImage = null;
        this.setFullImage = function (img) {
            this.fullImage = img;
        };
        this.getFullImage = function () {
            if (!this.fullImage) {
                this.fullImage = new Image();
                this.fullImage.src = this.fullUrl;
            }
            return this.fullImage;
        };
    }

    function logLayerCall() {
        $.get("../inc/functions/xml_http_requests.php",
              {f: "log_request",
               p0: "ARTIKEL_LAYER",
               p1: 0,
               p2: window.articleId,
               sid: window.mySession});
    }

    var zoomer,                 // div-Container
        zoomLayer,              // Layer als Hintergrund um Zoomer bei Click wieder auszublenden
        active = false,         // === true wenn zoomlayer angezeigt wird
        thuH = 0,               // Hoehe der Thumbnails inkl. text
        picW = 0, picH = 0,     // Breite/Hoehe der mittleren Bilder
        minW = 604, minH = 476, // min. Hoehe/Breite wenn das mittlere Bild gross genug ist
        pictures = [],          // Array Aus ArticlePictures
        currentImage,           // ArticlePicture das grad angezeigt wird
        handler = {},
        tracker,
        lensePic,
        zoomH,
        articleId,
        currentDetailId,
        initZoomer = false,
        ie6                     // === true wenn IE6 Benutzt wird
        ;

    function hideLenseAndTracker(e) {
        $("#lense").css("display", "none");
        tracker.css("display", "none");
        lensePic.attr("src", "/images/transparent.gif");
    }

    return {
        article: null,
        strings: [],

        /* Seiten-Initialisierung, gerufen wenn $(document).ready() */
        init: function () {

            ie6 = ($.browser.msie && parseInt($.browser.version, 10) < 7);

            var body = $(document.getElementsByTagName('body')[0]);

            // Layer als Hintergrund um Zoomer bei Click wieder
            // auszublenden opacity einmal direkt im CSS fuer Browser die
            // es so unterstuetzen (und mit jquery.css('opacity') nicht
            // zurecht kommen
            zoomLayer = $("<div id=\"zoomer-bg\" style=\"background-color: #000; opacity: 0.3; display: none; position: fixed; top: 0; left: 0; right: 0; bottom: auto; width: 100%; height: 100%; z-index: 10;\">&nbsp;</div>");
            // und einmal per jQuery fuer das Sorgenkind IE
            zoomLayer.css("opacity", 0.3);

            // Zoom Layer mit aktuellem bild & thumbnails und dem
            //  vergroesserten Bild(=lense)
            body.append(
                '<div id="zoomer" style="z-index: 11">' +
                  '<div class="toolbar"><div class="title"></div><span class="close"><img src="/images/close.png" alt=""></span></div>' +
                    '<div class="actionbar"><span class="left"><select></select></span><div class="right"></div></div>' +
                  '<div class="current">' +
                    '<div class="description"></div>' +
                    '<div class="img"><img>' +
                      '<div class="tracker" style="opacity: 0.4"></div>' +
                    '</div></div>' +
                  '<div class="images"></div>' +

                '</div>' +
                '<div id="lense" style="z-index: 12"><h3></h3><div><img></div></div>'

            );

            body.append(zoomLayer);
            zoomer = $("#zoomer");

            tracker = $(".tracker", zoomer);
            tracker.css("opacity", 0.4);
            lensePic = $("#lense img");
            function hideZoomer() {
                hideLenseAndTracker();
                zoomer.hide();
                zoomLayer.fadeOut(
                    300,
                    function () {
                        zoomLayer.hide();
                    }
                );
                active = false;
            }
            zoomLayer.click(
                function (e) {
                    if (e.target === this) {
                        hideZoomer();
                    }
                });
            $(".toolbar .close", zoomer).click(hideZoomer);

            // Zoomer Layer anpassen
            $(window).resize(
                function (e) {
                    if (active) {
                        zoomerJs.windowResized(e);
                        window.setTimeout(
                            function () {
                                zoomerJs.showZoomer(currentImage);
                            }, 100);
                    }
                }
            );
        },

        /**
         * An alle tags mit rel="zoomer" als click Event das oeffnen des
         * Zoomers haengen
         */
        attachZoomerLink: function () {

            $("[rel=zoomer]").click(
                function (e) {
                    var imgUrl = e.currentTarget.href,
                        l = imgUrl.length,
                        p, img, i;

                    for (i = 0; i < pictures.length; i++) {
                        p = pictures[i];
                        if (imgUrl.slice(l - p.fullUrl.length) === p.fullUrl) {
                            img = pictures[i];
                        }
                    }
                    if (!img) {
                        img = pictures[0];
                    }

                    active = true;
                    if (!initZoomer) {
                        zoomLayer.fadeIn(300);
                        active = true;
                        zoomerJs.initZoomer(img);
                        initZoomer = true;
                    }
                    else {
                        zoomLayer.fadeIn(
                            300,
                            function () {
                                zoomer.show();
                                zoomerJs.windowResized();
                                zoomerJs.showZoomer(img);
                            });

                    }

                    return false;
                });


        },

        /**
         * Initialiseren des Zoomers kurz bevor er angezeigt werden soll
         */
        initZoomer: function (startImg) {

            logLayerCall();

            if (this.article && this.article.details.length) {
                this.initActionBar();
            }
            else {
                $(".actionbar", zoomer).css("visibility", "hidden");
            }
            this.preloadImages(0, startImg);
        },

        /**
         * Bilder Vorladen vor dem Anzeigen die Richtige groesse
         *  ermittelt werden kann.
         * Die Bilder werden nacheinander geladen, parallel sollte
         *  moeglich und schneller sein.
         */
        preloadImages: function (i, startImg) {

            if (i >= pictures.length) {
                zoomLayer.show();
                zoomer.show();

                this.initZoomer2();

                if (!ie6) {
                    zoomer.mousemove(this.over);
                }
                this.showZoomer(startImg);

                return;
            }
            else {

                var img = new Image();

                img.onload = (
                    function (that, i) {
                        return function () {
                            that.preloadImages(i, startImg);
                        };
                    }(this, i + 1));
                img.src = pictures[i].fullUrl;
                pictures[i].fullImg = img;
                pictures[i].setFullImage(img);
            }

        },

        /**
         * Nach dem laden der Bilder den Zoomer die richtige groesse
         *  geben und die onclick handler fuer die thumbnails
         *  einstellen.
         */
        initZoomer2: function () {
            var div, pic, img, w, h, i,
                images = $(".images", zoomer),
                lineHeight = parseInt($(".images div").css("line-height"), 10);

            for (i = pictures.length;i--;) {
                pic  = pictures[i];
                div = $("<div><img src=\"" + pic.prevUrl +
                        "\" title=\"" + pic.text +
                        "\" alt=\"" + pic.text +
                        "\"><br>" + pic.text + "</div>");

                div.click(
                    function (pic, that) {
                        return function () {
                            that.showZoomer(pic);
                            return false;
                        };
                    }(pic, this));

                images.append(div);
                pic.container = div;

                h = div.outerHeight();

                thuH += h;
                // das 1. bild ist nicht vorgeladen deswegen groesse aus DB nehmen
                if (h < pic.prevHeight) {
                    thuH += pic.prevHeight;
                }

                img =  pic.getFullImage();

                w = img.width;
                h = img.height;

                if (h > picH) {
                    picH = h;
                }
                if (w > picW) {
                    picW = w;
                }

            }
            thuH = Math.max(thuH, images.outerHeight());
            this.windowResized();
        },

        /**
         * WindowResized Handler um die Groesse des Zoomers zu berechnen
         *  und zu setzen.
         */
        windowResized: function () {
            if (!active) {
                return;
            }
            var div, pic, i, img,
                barWidth, width,
                zoomW,
                w, h,
                s, ws, hs, // skalierung
                winH = Math.floor($(window).height() * 0.8),
                winW = Math.floor($(window).width() * 0.6),
                images = $(".images", zoomer);

            // Aktuelle max. Breite/Hoehe bestimmen
            if (picH <= winH) {
                zoomH = picH;
            }
            else {
                if (picH < minH || winH >= minH) {
                    zoomH = winH;
                }
                else {
                    zoomH = minH;
                }
            }
            if (thuH > zoomH) {
                if (thuH > winH) {
                    zoomH = winH;
                    images
                        .css("overflow-y", "scroll")
                        .css("height", zoomH);

                }
                else {
                    zoomH = thuH;
                }
            }

            if (picW >= winW) {
                zoomW = Math.max(minW, winW);
            }
            else {
                zoomW = picW;
            }
            // TODO zoomW besser berechnen s.u. width
            barWidth = ($(".actionbar .left", zoomer).outerWidth() +
                        $(".actionbar .right", zoomer).outerWidth() -
                        100);

            if (barWidth > zoomW) {
                zoomW = barWidth;
            }

            for (i = pictures.length;i--;) {
                pic = pictures[i];

                img = pic.getFullImage();
                w = img.width;
                h = img.height;
                if (w > zoomW || h > zoomH) {
                    s  = 1;
                    ws = 1;
                    hs = 1;

                    if (w > zoomW) {
                        ws = zoomW / w;
                    }
                    if (h > zoomH) {
                        hs = zoomH / h;
                    }

                    s = (ws < hs) ? ws : hs;

                    w = Math.floor(s * w);
                    h = Math.floor(s * h);
                    if (!pic.zoomUrl.length || pic.zoomUrl === pic.fullUrl) {

                        if (s < 0.8) {
                            pic.zoomUrl = pic.fullUrl;
                        }
                        else {
                            pic.zoomUrl = "";
                        }
                    }
                }
                else if (pic.zoomURL === pic.fullUrl) {
                    pic.zoomUrl = "";
                }

                pic.setSize(w, h);

                if (!ie6 && pic.zoomUrl.length) {
                    this.addLense(pic.container);
                }
                else {
                    this.removeLense(pic.container);
                }
            }

            width =
                Math.max(zoomW + $(".images", zoomer).outerWidth(),
                         $(".actionbar .left", zoomer).outerWidth() +
                         $(".actionbar .right", zoomer).outerWidth() +
                         0
                        );

            zoomer
                .width(width)
                .height(zoomH +
                        $(".toolbar", zoomer).outerHeight() +
                        $(".actionbar", zoomer).outerHeight() +
                        3);
            $(".current", zoomer).width(zoomW).height(zoomH);
            var a = $(".current .description", zoomer).height(),
                b = $(".current .description", zoomer).outerHeight();
            $(".current .description", zoomer).height(zoomH - (b - a));

            // Positionieren
            var lense = $("#lense"),
                zw = zoomW + $(".images", zoomer).outerWidth(),
                ww = $(window).width(),
                lw = lense.width(),
                lo = 10,
                d  = (ww - zw) / 2;

            if (d > lw + lo) {
                zoomer.css("left", d);
            }
            lense.css("left", Math.max(parseInt(zoomer.css("left"), 10) - 10 - lw, 0));

            zoomLayer.width($(window).width());
            zoomLayer.height($(window).height());

        },

        /**
         * zoomer Anzeigen
         *
         * @param img ArticlePicture Element von pictures
         * @param dontChangeSelection boolean Auswahl in der Selectionbox
         *    aendern? um Schleife zu verhindern (siehe changeSelection())
         */
        showZoomer: function (img, dontChangeSelection) {
            var $current, marginTop = 0, title = "";

            $(".current .img", zoomer).css("display", "block");
            $(".current .description", zoomer).css("display", "none");

            handler.zoomedImage = null;

            if (!img) {
                img = pictures[0];
            }

            handler.img = currentImage = img;

            if (this.article) {
                title += this.article.name;
            }
            if (img.text.length) {
                if (title.length) {
                    title += " - ";
                }
                title += img.text;
            }

            $(".toolbar .title", zoomer).html(title);

            $current = $("<img src=\"" + img.fullUrl + "\" width=\"" + img.width + "\" height=\"" + img.height + "\">");

            // Farblich passenden Artikel auswaehlen
            if (!dontChangeSelection && this.article && img.colorId > 0) {
                var colorId, i, l, d, details;
                details = $(".actionbar select option", zoomer).get();
                l = details.length;
                for (i = 0; i < l; i++) {
                    d = $(details[i]);
                    if (d.data("colorId") === img.colorId) {
                        $(".actionbar select").val([d.val()]);
                        this.changeSelection($(".actionbar select").get(0), true);
                        break;
                    }
                }
            }

            marginTop = zoomH - img.height;
            if (marginTop > 0) {
                marginTop = Math.floor(marginTop / 2);
            }
            else {
                marginTop = 0;
            }

            $("div.current div.img img", zoomer).replaceWith($current);
            $("div.current div.img", zoomer)
                .css("width", img.width + "px")
                .css("height", img.height + "px")
                .css("marginTop", marginTop + "px")
            ;

            if (!img.zoomUrl.length) {
                $("#lense").css("display", "none");
                tracker.css("display", "none");
                return false;
            }

            handler.p = $("div.current div.img img").offset();
            handler.current = $current.get(0);
            handler.tracker = tracker.get(0);

            function showLenseAndTracker() {

                $("#lense h3").html("Zoom");
                $("#lense").css("display", "block");

                $("#lense h3").html(img.text);
                lensePic.attr("src", img.zoomUrl);

                handler.zoomedImage = new Image();
                handler.zoomedImage.src = img.zoomUrl;

                handler.lenseWidth  = lensePic.parent().width();
                handler.lenseHeight = lensePic.parent().height();
                return true;
            }

            if (!ie6) {
                $current.mouseover(showLenseAndTracker);
            }

            return true;
        },

        addPicture: function (position, text, thumbUrl, thumbWidth, thumbHeight, prevUrl, prevWidth, prevHeight, fullUrl, zoomUrl) {
            pictures.push(new ArticlePicture(position, text, thumbUrl, thumbWidth, thumbHeight, prevUrl, prevWidth, prevHeight, fullUrl, zoomUrl));
        },

        setPictures: function (images) {
            var i = 0,
                l = images.length,
                p,
                newpics = [];

            for (;i < l;i++) {
                p = images[i];
                newpics.push(new ArticlePicture(p.position, p.text, p.thumbUrl, p.thumbWidth, p.thumbHeight, p.prevUrl, p.prevWidth, p.prevHeight, p.fullUrl, p.zoomUrl, p.colorId));
            }
            pictures = newpics;
        },

        /**
         * Zu einem container das Zoom Icon hinzufuegen bzw. anzeigen
         */
        addLense: function (container) {
            if (!container.lense) {
                container.lense = $('<img class="zoomable" src="/images/zoom-in.gif" alt="zoom">');
                container.append(container.lense);
            }
            else {
                container.lense.show();
            }
        },

        /**
         * Von einem container die Linse verstecken
         */
        removeLense: function (container) {
            if (container && container.lense) {
                container.lense.hide();
            }
        },

        /**
         * MouseOver handler fuer das aktuell angezeigte Bild
         */
        over: function (e) {

            // Teilweise kommt es vor das hoverIn noch nicht getriggert wurde
            if (handler.zoomedImage &&
                    handler.zoomedImage.width > 0 &&
                    handler.zoomedImage.height > 0) {

                if (e.target !== handler.current && e.target !== handler.tracker) {
                    hideLenseAndTracker();
                    return true;
                }
                var x = 0, y = 0,
                    sX = e.pageX - handler.p.left,
                    sY = e.pageY - handler.p.top,
                    t = {
                        x_max: handler.zoomedImage.width,
                        y_max: handler.zoomedImage.height,
                        x: handler.zoomedImage.width * sX / handler.img.width,
                        y: handler.zoomedImage.height * sY / handler.img.height
                    };

                x = Math.max(Math.min(0, -t.x + handler.lenseWidth / 2),
                             -t.x_max + handler.lenseWidth);
                y = Math.max(Math.min(0, -t.y + handler.lenseHeight / 2),
                             -t.y_max + handler.lenseHeight);


                var S = handler.img.width / t.x_max,
                    w = handler.lenseWidth * S + 2,
                    h = handler.lenseHeight * S + 2;

                if (S < 1) {
                    lensePic.css("left", "" + x + "px").css("top", "" + y + "px");

                    $("#lense").css("display", "block");

                    x = Math.min(handler.img.width  - w, Math.max(0, sX - Math.floor(w / 2)));
                    y = Math.min(handler.img.height - h, Math.max(0, sY - Math.floor(h / 2)));

                    tracker.css("left", "" + x + "px").css("top", "" + y + "px");
                    tracker.css("width", w).css("height", h);
                    tracker.css("display", "block");
                }
                // Aus irgendeinem Grund ist das Original kleiner als
                // das angezeigte Bild
                else {
                    hideLenseAndTracker();
                }

            }

            return true;
        },

        /**
         * Leiste mit Aktionen zum Artikel anzeigen
         *
         * TODO: Status/Verfuegbarkeit nur anzeigen wenn vorhanden
         */
        initActionBar: function () {
            var $actionbar = $(".actionbar .left", zoomer),
                basketImage = $('<img width="18" height="17" class="basket" title="' + this.strings.SHOP_ADD_TO_BASKET + '" alt="' + this.strings.SHOP_ADD_TO_BASKET + '" style="cursor: pointer;" src="./images/basket.gif">'),
                statusId = this.article.details[0].status,
                $recommend, $addthis, $articleDescription
            ;

            this.statusImage = $('<img class="status" src="/images/status-' + statusId + '.gif" width="17" height="17">');

            if (statusId == 5) {
                this.statusImage
                    .attr("alt", this.article.details[0].statusText)
                    .attr("title", this.article.details[0].statusText);
            }
            else {
                this.statusImage
                    .attr("alt", this.strings["SHOP_STATUS_" + statusId])
                    .attr("title", this.strings["SHOP_STATUS_" + statusId]);
            }

            currentDetailId = this.article.details[0].id;

            // detailauswahl befuellen
            var $sb = $("select", $actionbar);
            if (this.article.details.length) {
                $.each(this.article.details,
                       function (ignore, detail) {
                           var attr = detail.attributes.concat(detail.price + " Euro ").join(" | "),
                               option = $('<option value="' + detail.id + '">' + attr + "</option>");


                           $sb.append(option);
                           option.data("status", detail.status);
                           option.data("colorId", detail.colorId);
                           if (detail.status == 5) {
                               option.data("statusText", detail.statusText);
                           }
                       });
            }

            $sb.change(
                (function (that) {
                     return function () {
                         that.changeSelection(this, false);
                     };
                 }(this))
            );

            $actionbar.append(this.statusImage);

            basketImage.click(
                function () {
                    shopArticles.addToBasket(currentDetailId, 1, 'ARTIKEL_LAYER');
                });
            $actionbar.append(basketImage);

            // Link zur Artikel Beschreibung
            if (this.article.description) {
                $articleDescription = $('<span class="info">' + this.strings["ARTICLE_DESCRIPTION"] + '</span>');
                $articleDescription.click(
                    (function (that) {
                         return function () {
                             that.showDescription();
                         };
                     }(this))
                );
            }

            $actionbar.append($articleDescription);

            // Hack da die recommendbox im Template selber ist
            $recommend = $(".recommendLinkBox").clone();
            $(".actionbar .right").append($recommend);
            $recommend
                .addClass("recommendLinkAction")
                .removeClass("recommendLinkBox")
                ;
            $recommend.click(recommendPage.loadForm);

            // Hack da die recommendbox im Template selber ist
            var bml = $("." + bookmarkList.buttonClass).clone();
            $(".actionbar .right").append(bml);
            bml
                .addClass("recommendLinkAction")
                .removeClass("recommendLinkBox")
                ;
            bml.click(bookmarkList.addBookmarkArticle);

            // addthis nachladen
            $addthis = $("<a class=\"addthis_button\" style=\"display: none\" href=\"http://www.addthis.com/bookmark.php?v=250&amp;username=xa-4bdab4c663305586\"></a>");
            $.getScript("http://s7.addthis.com/js/250/addthis_widget.js#username=xa-4bdab4c663305586&domready=1&async=1",
                        function () {
                            addthis.init();
                            $(".actionbar .right").append($addthis);
                            addthis.button(".addthis_button");
                            $addthis.css("display", "inline");
                        });

            // Schließen button mit ZK versehen
            $("#zoomer .close img")
                .attr("alt", this.strings.CLOSE_WINDOW)
                .attr("title", this.strings.CLOSE_WINDOW);
        },

        /**
         * Nach Aenderung des Artikeldetails Verfuegbarkeit und angezeigtes
         * Bild aendern
         */
        changeSelection: function (select, dontChangeImage) {
            var $option = $(select.options[select.options.selectedIndex]),
                statusId = $option.data("status"),
                colorId = $option.data("colorId"),
                statusText = (statusId == 5) ? $option.data("statusText") : '',
                p, i
                ;

            currentDetailId = $(select).val();

            if (statusId == 5) {
                this.statusImage
                    .attr("src", this.statusImage.attr("src").replace(/status-./, "status-" + statusId))
                    .attr("alt", statusText)
                    .attr("title", statusText);
            }
            else {
                this.statusImage
                    .attr("src", this.statusImage.attr("src").replace(/status-./, "status-" + statusId))
                    .attr("alt", this.strings["SHOP_STATUS_" + statusId])
                    .attr("title", this.strings["SHOP_STATUS_" + statusId]);
            }

            // nur das Bild aendern wenns sich nicht geaendert hat
            if (!dontChangeImage && colorId > 0) {
                for (i in pictures) {
                    p = pictures[i];
                    if (p.colorId === colorId) {
                        this.showZoomer(p, true);
                        break;
                    }
                }
            }
        },

        /**
         * Artikeldaten, Bilder und ZKs holen, bzw aus jsonData nutzen
         */
        loadArticle: function (id, jsonData) {
            articleId = id;
            var handleData = (
                function (that) {
                    return function (reply) {

                        if (reply.article) {
                            that.article = reply.article;
                            that.strings = reply.strings;
                        }

                        if (reply.images && reply.images.length) {
                            that.setPictures(reply.images);
                            pictures.sort(
                                function (a, b) {
                                    return a.position - b.position;
                                }
                            );
                        }

                        if (!reply.error) {
                            that.attachZoomerLink();
                        }
                    };
                }(this));

            if (typeof jsonData === "undefined") {
                $.get("../inc/functions/xml_http_requests.php",
                      {f: "json_get_article_data",
                       p0: articleId,
                       sid: mySession},
                      handleData,
                      'json');
            }
            else {
                handleData(jsonData);
            }
        },

        /**
         * Artikelbeschreibung anzeigen
         */
        showDescription: function () {
            $(".current .img", zoomer).css("display", "none");
            $(".current .description", zoomer)
                .html(this.article.description)
                .css("display", "block");
        }
    };
}());


/*
 * Seiten-Initialisierung aufrufen
 */
$(document).ready(function () {
    zoomerJs.init();
});
