var gallery = {
    streamList: null,
    setsList: null,
    listnum: 12,
    init: function () {
        this.streamList = new NTES.ui.NavList($("#streamBody"), $("#streamBar"), {
            onChange: gallery.changePhoto.bind(this)
        });
        this.streamList.run($("#streamL"), 0).run($("#streamR"), 1);
        this.setsList = new NTES.ui.NavList($("#setsBody"), $("#setsBar"), {
            width: 120
        });
        this.setsList.run($("#setsL"), 0).run($("#setsR"), 1);
        NTES.ui.Template.load($("#temp > *"));

        var hash = window.location.hash,
            index = this.idx(hash);
        /^#q=\d+$/.test(hash) && index >= 0 && index < Math.ceil(this.streamList.len / this.listnum) ? this.viewWhole(index) : this.viewPhoto(/^#p=\d+$/.test(hash) && index >= 0 && index < this.streamList.len ? index : 0);

        $("#interval,  #select > a, #play, #pause, #close, #first, #last, #again, #pPrev, #pNext, #photoLink, #streamBody a, #streamL, #streamR, #streamBar, #setsL, #setsR, #setsBar, #stream a, #sPrev, #sNext").addEvent("click", function (e) {
            e.preventDefault();
        });

        $("#search input[type=text]").addEvent("focus", function () {
            this.value == this.defaultValue && (this.value = "");
        }).addEvent("blur", function () {
            this.value == "" && (this.value = this.defaultValue);
        });

        $("#select > a").addEvent("click", function () {
            $("#interval").innerHTML = $("#select > span")[0].innerHTML = this.innerHTML + "秒";
            gallery.play();
        });
        new NTES.ui.PopupLayer($("#interval"), $("#select"), "click");
        $("#play").addEvent("click", gallery.play.bind(this));
        $("#pause").addEvent("click", gallery.stop.bind(this));

        $("#first, #last, #again, #streamBody a, #pPrev, #pNext, #photoLink").addEvent("click", function () {
            var index = gallery.idx(this.href);
            index >= 0 && index < gallery.streamList.len ? gallery.streamList.goto(index) : $("#floatBox").removeCss("hidden");
        });
        $("#close").addEvent("click", function () {
            $("#floatBox").addCss("hidden");
        });

        var maxSize = {};
        switch ($("#pView > div")[0].className) {
        case "horizontal":
            maxSize = {
                width: 670,
                height: 600
            };
            break;
        case "vertical":
            maxSize = {
                width: 900,
                height: 600
            };
        }
        window.addEvent("load", gallery.resize.bind(this, $("#photo"), maxSize));
        $("#photo").addEvent("load", gallery.resize.bind(this, $("#photo"), maxSize));
    },
    viewWhole: function (idx) {
        $("#num,  #first, #play, #last, #intervalBox, #pView, #tStream").addCss("hidden");
        $("#total, #sView, #tSets").removeCss("hidden");
        this.changePage(idx);
    },
    viewPhoto: function (idx) {
        $("#num,#first,#play,#last,#intervalBox,#pView,#tStream").removeCss("hidden");
        $("#total,#sView,#tSets").addCss("hidden");
        this.streamList.goto(idx);
    },
    changePhoto: function () {
		$("#floatBox").addCss("hidden");
        $("#pView").addCss("loading");
        var info = $(this.streamList.curEle()),
            num = this.streamList.curIndex + 1;
        this.pv(info.$("a")[0].href);
        $("#num span")[0].innerHTML = num;
        $("#photo").src = info.$("img")[0].src.replace("img4", "img3").replace(/\.thumb\.jpg/, "").replace(/\/small/,"").replace("z","").replace("_s","_b");
        $("#pView .desc h2")[0].innerHTML = info.$("h3")[0].innerHTML;
        //$("#pView .desc p")[0].innerHTML = info.$("p")[0].innerHTML;
        $("#pPrev").href = "#p=" + (num - 1);
        $("#pNext").href = $("#photoLink").href = "#p=" + (num + 1);
    },
    changePage: function (idx) {
        var data = {
            start: idx * this.listnum,
            listnum: this.listnum,
            length: this.streamList.len,
            photos: []
        };
        for (var i = data.start, len = Math.min(data.start + data.listnum, data.length); i < len; i++) {
            data.photos.push({
                imgsrc: $(this.streamList.list[i]).$("img")[0].src.replace(/[s,n]_/, "t_"),
                title: $(this.streamList.list[i]).$("h3")[0].innerHTML
            })
        }
        $("#sView").innerHTML = NTES.ui.Template.parse("sView", data);
        $("#stream a").addEvent("click", function () {
            gallery.viewPhoto(gallery.idx(this.href));
        });
        $("#sPrev, #sNext").addEvent("click", function () {
            gallery.pv(this.href);
            gallery.changePage(gallery.idx(this.href));
        });
    },
    idx: function (href) {
        return parseInt(href.replace(/^.*#[p,q]=/, "")) - 1;
    },
    resize: function (photo, maxSize) {
        var image = new Image();
        image.src = photo.src;
        var width = image.width,
            height = image.height;
        photo.removeAttribute("width");
        photo.removeAttribute("height");
        maxSize = maxSize || {};
        if (maxSize.width && maxSize.height) {
            width * maxSize.height > maxSize.width * height ? (photo.width = Math.min(width, maxSize.width)) : (photo.height = Math.min(height, maxSize.height));
        } else {
            maxSize.width && (photo.width = Math.min(width, maxSize.width));
            maxSize.height && (photo.height = Math.min(height, maxSize.height));
        }
        $("#pView").removeCss("loading");
        (new Image).src = $(this.streamList.list[(this.streamList.curIndex + 1) % this.streamList.len]).$("img")[0].src.replace("img4", "img3").replace(/\.thumb\.jpg/, "").replace(/\/small/,"").replace("z","").replace("_s","_b");
    },
    play: function () {
        this.streamList.stop();
        var interval = parseInt($("#interval").innerHTML) * 1000;
        setTimeout(this.streamList.play.bind(this.streamList, interval), interval);
        $("#play").addCss("hidden");
        $("#pause").removeCss("hidden");
    },
    stop: function () {
        this.streamList.stop();
        $("#play").removeCss("hidden");
        $("#pause").addCss("hidden");
    },
    pv: function (url) {
        window.location.href = url;
        typeof vjEventTrack === "function" && vjEventTrack();
        typeof neteaseTracker === "function" && neteaseTracker();
    }
};

gallery.SearchResult = function (q, channelid, length, start) {
    this.q = q || "q=";
    this.channelid = channelid || "";
    this.length = length || 12;
    this.start = start || 0;
    NTES.ui.Template.load();
    this.load();
};
gallery.SearchResult.prototype = {
    show: function () {
        $("#view").innerHTML = NTES.ui.Template.parse("sets", jsonres);
        this.start != 0 && $("#prev").addEvent("click", function (e) {
            e.preventDefault();
            this.start -= this.length;
            this.load();
        }.bind(this));
        this.start + this.length < jsonres.availHits && $("#next").addEvent("click", function (e) {
            e.preventDefault();
            this.start += this.length;
            this.load();
        }.bind(this));

    },
    load: function () {
        NTES.ajax.importJs(
        String.format("", this.q, this.channelid, this.length, this.start), this.show.bind(this));
        gallery.pv("#page=" + (Math.floor(this.start / this.length) + 1));
    }
};

$.ui.NavList = function (body, bar, options) {
    this._body = body;
    this._bar = bar;

    this.options = {
        container: this._bar.parentNode,
        width: 110,
        num: 7,
		minBarWidth: 40,
        curCss: "active",
        onChange: function () {}
    };
    $.util.extend(this.options, options);

    this.list = this._body.$("> *");
    this.len = this.list.length;
    this.num = Math.min(this.options.num, this.len);
    this._extra = this.len - this.num;

    var conWidth = this.options.container.clientWidth;
    this._body.style.width = this.options.width * this.len + "px";
    this._bar.style.width = Math.max(this.options.minBarWidth, Math.min(Math.round(conWidth * this.num / this.len), conWidth)) + "px";
    this._slider = new $.ui.Slider(this.options.container, this._bar, {
        onMove: this.move.bind(this)
    });

    var i = this.len;
    while (--i >= 0) {
        if (this.list[i].className == this.options.curCss) {
            this.curIndex = i;
            var first = this.first();
            this._body.style.left = -first * this.options.width + "px";
            this._bar.style.left = Math.round(first * conWidth / this.len) + "px";
            break;
        }
    }
};

$.ui.NavList.prototype = {
    move: function () {
        this._body.style.left = -this.options.width * this._slider.pct() * this._extra + "px";
    },
    run: function (ele, bIncrease) {
        $.event.addEvent(ele, "mousedown", this._slider.run.bind(this._slider, bIncrease));
        $.event.addEvent(ele, "mouseup", this._slider.stop.bind(this._slider));
        return this;
    },
    first: function () {
        return Math.max(0, Math.min(this.curIndex - Math.floor((this.num - 1) / 2), this._extra));
    },
    goto: function (cur) {
        this.curEle(cur);
        this._slider.pct(this.first() / this._extra);
        this.options.onChange();
    },
    stop: function () {
        clearTimeout(this._timer);
    },
    play: function (interval) {
        this.goto((this.curIndex + 1) % this.len);
        this._timer = setTimeout(this.play.bind(this, interval), interval)
    },
    curEle: function (index) {
        if (index !== undefined) {
            this.curIndex !== undefined && $.style.removeCss(this.curEle(), this.options.curCss);
            this.curIndex = index;
            $.style.addCss(this.curEle(), this.options.curCss);
        } else {
            return this.list[this.curIndex];
        }
    }
};

var doc = document.documentElement,
    htmlBody = $(document.body);

$.ui.Drag = function (drag, options) {
    this.drag = drag;
    this.options = {
        handle: this.drag,
        container: null,
        onStart: function () {},
        onMove: function () {},
        onStop: function () {}
    }
    $.util.extend(this.options, options);

    this._fM = this.move.bind(this);
    this._fS = this.stop.bind(this);
    this._mxWidth = this.options.container.clientWidth || doc.scrollWidth;
    this._mxHeight = this.options.container.clientHeight || doc.scrollHeight;
    this._marginLeft = parseInt($.style.getCurrentStyle(this.drag, "margin-left")) || 0;
    this._marginTop = parseInt($.style.getCurrentStyle(this.drag, "margin-top")) || 0;
    $.event.addEvent(this.options.handle, "mousedown", this.start.bind(this));
};

$.ui.Drag.prototype = {
    start: function (e) {
        this._x = e.clientX - this.drag.offsetLeft;
        this._y = e.clientY - this.drag.offsetTop;
        if (this.options.handle.setCapture) {
            this.options.handle.setCapture();
        } else {
            $.event.addEvent(window, "blur", this._fS);
            e.preventDefault();
        }
        $.event.addEvent(htmlBody, "mousemove", this._fM);
        $.event.addEvent(htmlBody, "mouseup", this._fS);
        this.options.onStart();
    },
    move: function (e) {
        e.cancelBubble = true;
        this.pos(e.clientX - this._x, e.clientY - this._y);
    },
    pos: function (iLeft, iTop) {
        iLeft = Math.max(0, Math.min(iLeft, this._mxWidth - this.drag.offsetWidth));
        iTop = Math.max(0, Math.min(iTop, this._mxHeight - this.drag.offsetHeight));
        this.drag.style.left = iLeft - this._marginLeft + "px";
        this.drag.style.top = iTop - this._marginTop + "px";
        this.options.onMove();
    },
    stop: function () {
        $.event.removeEvent(htmlBody, "mousemove", this._fM);
        $.event.removeEvent(htmlBody, "mouseup", this._fS);
        if (this.options.handle.releaseCapture) {
            this.options.handle.releaseCapture();
        } else {
            $.event.removeEvent(window, "blur", this._fS);
        };
        this.options.onStop();
    }

};

$.ui.Slider = function (container, bar, options) {
    this.bar = bar;
    this.container = container;
    this._drag = new $.ui.Drag(this.bar, {
        container: this.container,
        onStart: this.dragStart.bind(this),
        onStop: this.dragStop.bind(this),
        onMove: this.move.bind(this)
    });
    this.options = {
        orientation: 'horizontal',
        //vertical || horizontal
        runTime: 20,
        runStep: 2,

        ease: true,
        easeStep: 10,

        onMin: function () {},
        onMax: function () {},
        onMid: function () {},

        onDragStart: function () {},
        onDragStop: function () {},
        onMove: function () {}
    };
    $.util.extend(this.options, options);

    this.orientation = this.options.orientation == 'vertical' ? 'vertical' : 'horizontal';
    this._ondrag = false;
    this._isMin = this._isMax = this._isMid = false;
    this._timer = null;
    this._exWidth = this.container.clientWidth - this.bar.offsetWidth;
    this._exHeight = this.container.clientHeight - this.bar.offsetHeight;

    $.event.addEvent(this.container, "click", function (e) {
        this._ondrag || this.clickCtrl(e);
    }.bind(this));
    $.event.addEvent(this.bar, "click", function (e) {
        e.cancelBubble = true;
    });
};

$.ui.Slider.prototype = {
    dragStart: function () {
        this.options.onDragStart();
        this._ondrag = true;
    },
    dragStop: function () {
        this.options.onDragStop();
        this._ondrag = false;
    },
    move: function () {
        this.options.onMove();
        var percent = this.pct();
        if (percent > 0) {
            this._isMin = false;
        } else if (!this._isMin) {
            this.options.onMin();
            this._isMin = true;
        }
        if (percent < 1) {
            this._isMax = false;
        } else if (!this._isMax) {
            this.options.onMax();
            this._isMax = true;
        }
        if (percent == 0 || percent == 1) {
            this._isMid = false;
        } else if (!this._isMid) {
            this.options.onMid();
            this._isMid = true;
        }
    },
    clickCtrl: function (e) {
        var o = this.container,
            iLeft = o.offsetLeft,
            iTop = o.offsetTop;
        while (o.offsetParent) {
            o = o.offsetParent;
            iLeft += o.offsetLeft;
            iTop += o.offsetTop;
        }
        this.easePos(e.pageX - iLeft - this.bar.offsetWidth / 2, e.pageY - iTop - this.bar.offsetHeight / 2);
    },
    pct: function (value) {
        if (value !== undefined) {
            this.easePos(this._exWidth * value, this._exHeight * value);
        } else {
            return this.orientation == "horizontal" ? this.bar.offsetLeft / this._exWidth : this.bar.offsetTop / this._exHeight;
        }
    },
    run: function (bIncrease) {
        this.stop();
        bIncrease = bIncrease;
        var percent = this.pct() + (bIncrease ? 1 : -1) * this.options.runStep / 100;
        this.pos(this._exWidth * percent, this._exHeight * percent);
        if (! (bIncrease ? this._isMax : this._isMin)) {
            this._timer = setTimeout(this.run.bind(this, bIncrease), this.options.runTime);
        }
    },
    stop: function () {
        clearTimeout(this._timer);
    },
    easePos: function (iLeftT, iTopT) {
        this.stop();
        iLeftT = Math.round(iLeftT);
        iTopT = Math.round(iTopT);
        if (!this.options.ease) {
            this.pos(iLeftT, iTopT);
            return;
        }
        var iLeftN = this.bar.offsetLeft,
            iLeftS = this.step(iLeftT, iLeftN),
            iTopN = this.bar.offsetTop,
            iTopS = this.step(iTopT, iTopN);
        if (this.orientation == "horizontal" ? iLeftS : iTopS) {
            this.pos(iLeftN + iLeftS, iTopN + iTopS);
            if (this._isMid) {
                this._timer = setTimeout(this.easePos.bind(this, iLeftT, iTopT), this.options.runTime);
            }
        }
    },
    step: function (iTarget, iNow) {
        var iStep = (iTarget - iNow) / this.options.easeStep;
        if (iStep == 0) return 0;
        if (Math.abs(iStep) < 1) return iStep > 0 ? 1 : -1;
        return iStep;
    },
    pos: function (iLeft, iTop) {
        this.stop();
        this._drag.pos(iLeft, iTop);
    }
};