/*   2/14/2011
		PikaChoose
	Jquery plugin for photo galleries
    Copyright (C) 2011 Jeremy Fry

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
(function ($) {
    var defaults = {
        autoPlay: true,
        speed: 5000,
        text: {
            play: "",
            stop: "",
            previous: "<img src='images/gallery-arrow-left.gif' />",
            next: "<img src='images/gallery-arrow-right.gif' />"
        },
        transition: [1],
        showCaption: true,
        IESafe: false,
        showTooltips: false,
        animationFinished: null
    };
    $.fn.PikaChoose = function (o) {
        return this.each(function () {
            $(this).data('pikachoose', new $pc(this, o))
        })
    };
    $.PikaChoose = function (e, o) {
        this.options = $.extend({}, defaults, o || {});
        this.list = null;
        this.image = null;
        this.anchor = null;
        this.caption = null;
        this.imgNav = null;
        this.imgPlay = null;
        this.imgPrev = null;
        this.imgNext = null;
        this.textNext = null;
        this.textPrev = null;
        this.previous = null;
        this.next = null;
        this.aniDiv = null;
        this.thumbs = null;
        this.transition = null;
        this.active = null;
        this.tooltip = null;
        this.animating = false;
        this.stillOut = null;
        if (e.nodeName == 'UL' || e.nodeName == 'OL') {
            this.list = $(e);
            this.build();
            this.bindEvents()
        } else {
            return
        }
        var y = 0;
        var x = 0;
        for (var t = 0; t < 25; t++) {
            var a = '<div col="' + y + '" row="' + x + '"></div>';
            this.aniDiv.append(a);
            y++;
            if (y == 5) {
                x++;
                y = 0
            }
        }
    };
    var $pc = $.PikaChoose;
    $pc.fn = $pc.prototype = {
        pikachoose: '4.1.6'
    };
    $pc.fn.extend = $pc.extend = $.extend;
    $pc.fn.extend({
        build: function () {
            this.step = 0;
            this.wrap = $("<div class='pika-image'></div>").insertBefore(this.list);
            this.image = $("<img>").appendTo(this.wrap);
            this.anchor = this.image.wrap("").parent();
            this.imgNav = $("<div class='pika-imgnav'></div>").insertAfter(this.image);
            this.imgPlay = $("<a></a>").appendTo(this.imgNav);
            if (this.options.autoPlay) {
                this.imgPlay.addClass('pause')
            } else {
                this.imgPlay.addClass('play')
            }
            this.imgPrev = $("<a class='previous'></a>").insertAfter(this.imgPlay);
            this.imgNext = $("<a class='next'></a>").insertAfter(this.imgPrev);
            this.caption = $("<div class='caption'></div>").insertAfter(this.imgNav);
            if (!this.options.showCaption) {
                this.caption.hide()
            }
            this.tooltip = $("<div class='pika-tooltip'></div>").insertAfter(this.list);
            this.tooltip.hide();
            this.aniDiv = $("<div class='animation'></div>").insertAfter(this.caption);
            this.textNav = $("<div class='pika-textnav'></div>").insertAfter(this.aniDiv);
            this.textPrev = $("<a class='previous'>" + this.options.text.previous + "</a>").appendTo(this.textNav);
            this.textNext = $("<a class='next'>" + this.options.text.next + "</a>").appendTo(this.textNav);
            this.list.addClass('pika-thumbs');
            this.list.children('li').wrapInner("<div class='clip' />");
            this.thumbs = this.list.find('img');
            this.active = this.thumbs.eq(0);
            this.finishAnimating({
                'source': this.active.attr('ref') || this.active.attr('src'),
                'caption': this.active.parents('li:first').find('span:first').html(),
                'clickThrough': this.active.parent().attr('href') || "",
                'clickThroughTitle': this.active.parent().attr('title') || ""
            });
            var self = this;
            this.thumbs.each(function () {
                self.createThumb($(this), self)
            });
            if (typeof(this.options.buildFinished) == 'function') {
                this.options.buildFinished(this)
            }
        },
        createThumb: function (ele) {
            var self = ele;
            var that = this;
            self.hide();
            $.data(ele[0], 'clickThrough', self.parent('a').attr('href') || "");
            $.data(ele[0], 'clickThroughTitle', self.parent('a').attr('title') || "");
            if (self.parent('a').length > 0) {
                self.unwrap()
            }
            $.data(ele[0], 'caption', self.next('span').html() || "");
            self.next('span').remove();
            $.data(ele[0], 'source', self.attr('ref') || self.attr('src'));
            $.data(ele[0], 'order', self.closest('ul').find('li').index(self.parents('li')));
            var data = $.data(ele[0]);
            $('<img />').bind('load', {
                data: data
            }, function () {
                if (typeof(that.options.buildThumbStart) == 'function') {
                    that.options.buildThumbStart(that)
                }
                var img = $(this);
                var w = img.width();
                var h = img.height();
                if (w === 0) {
                    w = img.attr("width")
                }
                if (h === 0) {
                    h = img.attr("height")
                }
                var rw = parseInt(self.parents('.clip').css('width').slice(0, -2)) / w;
                var rh = parseInt(self.parents('.clip').css('height').slice(0, -2)) / h;
                var ratio;
                if (rw < rh) {
                    ratio = rh;
                    var left = ((w * ratio - parseInt(self.parents('.clip').css('width').slice(0, -2))) / 2) * -1;
                    left = Math.round(left);
                    self.css({
                        left: left
                    })
                } else {
                    ratio = rw;
                    self.css({
                        top: 0
                    })
                }
                var width = Math.round(w * ratio);
                var height = Math.round(h * ratio);
                self.css("position", "relative");
                var imgcss = {
                    width: width + "px",
                    height: height + "px"
                };
                self.css(imgcss);
                self.hover(function (e) {
                    clearTimeout(that.stillOut);
                    $(this).stop(true, true).fadeTo(250, 1);
                    if (!that.options.showTooltips) {
                        return
                    }
                    that.tooltip.show().stop(true, true).html(data.caption).animate({
                        top: $(this).parent().position().top,
                        left: $(this).parent().position().left,
                        opacity: 1.0
                    }, 'fast')
                }, function (e) {
                    if (!$(this).hasClass("active")) {
                        $(this).stop(true, true).fadeTo(250, 0.4);
                        that.stillOut = setTimeout(that.hideTooltip, 700)
                    }
                });
                if (data.order == 0) {
                    self.fadeTo(250, 1);
                    self.addClass('active')
                } else {
                    self.fadeTo(250, 0.4)
                }
                if (typeof(that.options.buildThumbFinish) == 'function') {
                    that.options.buildThumbFinish(that)
                }
            }).attr('src', self.attr('src'))
        },
        bindEvents: function () {
            this.thumbs.bind('click', {
                self: this
            }, this.imgClick);
            //this.imgNext.bind('click', {
            //    self: this
            //}, this.nextClick);
            this.textNext.bind('click', {
                self: this
            }, this.nextClick);
            //this.imgPrev.bind('click', {
            //    self: this
            //}, this.prevClick);
            this.textPrev.bind('click', {
                self: this
            }, this.prevClick);
            //this.imgPlay.bind('click', {
            //    self: this
            //}, this.playClick);
            //this.wrap.bind('mouseenter', {
            //    self: this
            //}, function (e) {
            //    e.data.self.imgPlay.stop(true, true).fadeIn('fast')
            //});
           // this.wrap.bind('mouseleave', {
            //    self: this
            //}, function (e) {
            //    e.data.self.imgPlay.stop(true, true).fadeOut('fast')
           // });
            this.tooltip.bind('mouseenter', {
                self: this
            }, function (e) {
                clearTimeout(e.data.self.stillOut)
            });
            this.tooltip.bind('mouseleave', {
                self: this
            }, function (e) {
                e.data.self.stillOut = setTimeout(e.data.self.hideTooltip, 700)
            })
        },
        hideTooltip: function (e) {
            $(".pika-tooltip").animate({
                opacity: 0.01
            })
        },
        imgClick: function (e, x) {
            var self = e.data.self;
            var data = $.data(this);
            if (self.animating) {
                return
            }
            self.caption.fadeOut('slow');
            if (typeof(x) == 'undefined' || x.how != "auto") {
                if (self.options.autoPlay) {
                    self.imgPlay.trigger('click')
                }
            }
            self.animating = true;
            self.active.fadeTo(300, 0.4).removeClass('active');
            self.active = $(this);
            self.active.addClass('active').fadeTo(200, 1);
            $('<img />').bind('load', {
                self: self,
                data: data
            }, function () {
                self.aniDiv.css({
                    height: self.image.height(),
                    width: self.image.width()
                }).fadeIn('fast');
                self.aniDiv.children('div').css({
                    'width': '20%',
                    'height': '20%',
                    'float': 'left'
                });
                var n = 0;
                if (self.options.transition[0] == -1) {
                    n = Math.floor(Math.random() * 6) + 1
                } else {
                    n = self.options.transition[self.step];
                    self.step++;
                    if (self.step >= self.options.transition.length) {
                        self.step = 0
                    }
                }
                if (self.options.IESafe && $.browser.msie) {
                    n = 1
                }
                self.doAnimation(n, data)
            }).attr('src', $.data(this).source)
        },
        doAnimation: function (n, data) {
            var self = this;
            var aWidth = self.aniDiv.children('div').eq(0).width();
            var aHeight = self.aniDiv.children('div').eq(0).height();
            self.aniDiv.children().each(function () {
                var div = $(this);
                var xOffset = Math.floor(div.parent().width() / 5) * div.attr('col');
                var yOffset = Math.floor(div.parent().height() / 5) * div.attr('row');
                div.css({
                    'background': 'url(' + data.source + ') -' + xOffset + 'px -' + yOffset + 'px',
                    'width': '0px',
                    'height': '0px',
                    'position': 'absolute',
                    'top': yOffset + 'px',
                    'left': xOffset + 'px',
                    'float': 'none'
                })
            });
            switch (n) {
            case 0:
                self.aniDiv.hide();
                self.image.stop(true, true).fadeOut('slow', function () {
                    self.image.attr('src', data.source).fadeIn('slow', function () {
                        self.finishAnimating(data)
                    })
                });
                break;
            case 1:
                self.aniDiv.height(self.image.height()).hide().css({
                    'background': 'url(' + data.source + ') top left no-repeat'
                });
                self.aniDiv.children('div').hide();
                self.aniDiv.fadeIn('slow', function () {
                    self.finishAnimating(data);
                    self.aniDiv.css({
                        'background': 'transparent'
                    })
                });
                break;
            case 2:
                self.aniDiv.children().hide().each(function (index) {
                    var delay = index * 30;
                    $(this).css({
                        opacity: 0.1
                    }).show().delay(delay).animate({
                        opacity: 1,
                        "width": aWidth,
                        "height": aHeight
                    }, 200, 'linear', function () {
                        if ($(this).parents('.animation').find("div").index(this) == 24) {
                            self.finishAnimating(data)
                        }
                    })
                });
                break;
            case 3:
                self.aniDiv.children("div:lt(5)").hide().each(function (index) {
                    var delay = $(this).attr('col') * 100;
                    $(this).css({
                        opacity: 0.1,
                        "width": aWidth
                    }).show().delay(delay).animate({
                        opacity: 1,
                        "height": self.image.height()
                    }, 700, 'linear', function () {
                        if ($(this).parents('.animation').find(" div").index(this) == 4) {
                            self.finishAnimating(data)
                        }
                    })
                });
                break;
            case 4:
                self.aniDiv.children().hide().each(function (index) {
                    var delay = $(this).attr('col') * 10;
                    aHeight = self.gapper($(this), aHeight);
                    $(this).css({
                        opacity: 0.1,
                        "height": aHeight
                    }).show().delay(delay).animate({
                        opacity: 1,
                        "width": aWidth
                    }, 800, 'linear', function () {
                        if ($(this).parents('.animation').find(" div").index(this) == 24) {
                            self.finishAnimating(data)
                        }
                    })
                });
                break;
            case 5:
                self.aniDiv.children().show().each(function (index) {
                    var delay = index * Math.floor(Math.random() * 5) * 10;
                    aHeight = self.gapper($(this), aHeight);
                    if ($(".animation div").index(this) == 24) {
                        delay = 800
                    }
                    $(this).css({
                        "height": aHeight,
                        "width": aWidth,
                        "opacity": .01
                    }).delay(delay).animate({
                        "opacity": 1
                    }, 800, function () {
                        if ($(this).parents('.animation').find(" div").index(this) == 24) {
                            self.finishAnimating(data)
                        }
                    })
                });
                break;
            case 6:
                self.aniDiv.height(self.image.height()).hide().css({
                    'background': 'url(' + data.source + ') top left no-repeat'
                });
                self.aniDiv.children('div').hide();
                self.aniDiv.css({
                    width: 0
                }).show().animate({
                    width: self.image.width()
                }, 'slow', function () {
                    self.finishAnimating(data);
                    self.aniDiv.css({
                        'background': 'transparent'
                    })
                });
                break
            }
        },
        finishAnimating: function (data) {
            this.animating = false;
            this.image.attr('src', data.source);
            this.aniDiv.hide();
            this.anchor.attr('href', data.clickThrough);
            this.anchor.attr('title', data.clickThroughTitle);
            if (this.options.showCaption) {
                this.caption.html(data.caption).fadeIn('slow')
            }
            if (this.options.autoPlay == true) {
                var self = this;
                this.image.delay(this.options.speed).fadeIn(0, function () {
                    if (self.options.autoPlay) {
                        self.nextClick()
                    }
                })
            }
            if (typeof(this.options.animationFinished) == 'function') {
                this.options.animationFinished(this)
            }
        },
        gapper: function (ele, aHeight) {
            if (ele.attr('row') == 9 && ele.attr('col') == 0) {
                var gap = ani_divs.height() - (aHeight * 9);
                return gap
            }
            return aHeight
        },
        nextClick: function (e) {
            var how = "natural";
            try {
                var self = e.data.self;
                if (typeof(e.data.self.options.next) == 'function') {
                    e.data.self.options.next(this)
                }
            } catch (err) {
                var self = this;
                how = "auto"
            }
            var next = self.active.parents('li:first').next().find('img');
            if (next.length == 0) {
                next = self.list.find('img').eq(0)
            };
            next.trigger('click', {
                how: how
            })
        },
        prevClick: function (e) {
            if (typeof(e.data.self.options.previous) == 'function') {
                e.data.self.options.previous(this)
            }
            var self = e.data.self;
            var prev = self.active.parents('li:first').prev().find('img');
            if (prev.length == 0) {
                prev = self.list.find('img:last')
            };
            prev.trigger('click')
        },
        playClick: function (e) {
            var self = e.data.self;
            self.options.autoPlay = !self.options.autoPlay;
            self.imgPlay.toggleClass('play').toggleClass('pause');
            if (self.options.autoPlay) {
                self.nextClick()
            }
        }
    })
})(jQuery);

