(function ($) {
    jQuery.fn.timeliner = function (n) {
        var o = $.extend({
            containerwidth: 700,
            containerheight: 200,
            showpauseplay: false,
            showprevnext: false,
            timelinewidth: 650,
            timelineheight: 3,
            timelinehorizontalmargin: 'auto',
            timelineverticalmargin: 10,
            timelineposition: 'bottom',
            showtimedisplay: false,
            timedisplayposition: 'above',
            showtotaltime: false,
            showtooltip: true,
            showtooltiptime: false,
            tooltipposition: 'above',
            interval: 10,
            repeat: true,
            autoplay: true,
            keyboard: true,
            transition: 'fade'
        }, n);
        $(this).each(function () {
            function getdisplaytime(a) {
                var b = Math.floor(a / 60);
                a = (a - (b * 60));
                if (a < 10) {
                    a = '0' + a
                }
                return b + ':' + a
            }
            var c, prenodepos = [0],
                nodepos = [0, 0],
                nodesec = [0, 0],
                nodeinterval = [0],
                targetpos, x = 1,
                activenode = 1,
                seconds = 0,
                timeinterval, totaltime = 0,
                playing = false,
                timeremaining, animationtime, $container = $(this).show(),
                $slides = $container.find('> li'),
                $timeline = $('<li class="timeline"></li>').prependTo($container),
                $innertimeline = $('<div class="innertimeline">&nbsp;</div>').prependTo($timeline),
                nodes = $slides.length;
            if (o.showtimedisplay) {
                var d = $('<div class="timedisplay">0:00</div>').prependTo($timeline);
                if (o.showtotaltime) {
                    d.append(' / 0:00')
                }
                var f = Math.round(d.outerWidth(true) / 2)
            }
            if (o.showpauseplay) {
                var g = $('<li class="play"></li>').prependTo($container).animate({
                    opacity: 0
                }, 0);
                if (o.showprevnext) {
                    var h = $('<li class="previous"></li>').prependTo($container).animate({
                        opacity: 0
                    }, 0);
                    var i = $('<li class="next"></li>').prependTo($container).animate({
                        opacity: 0
                    }, 0)
                }
            }
            $slides.each(function () {
                $(this).addClass('slide').addClass('slide' + x).data('title', $(this).attr('title')).removeAttr('title').animate({
                    opacity: 0
                }, 0);
                if (x < nodes || o.repeat) {
                    if ($(this).attr('lang')) {
                        nodeinterval[x] = parseInt($(this).attr('lang'))
                    } else {
                        nodeinterval[x] = o.interval
                    }
                    totaltime = +totaltime + nodeinterval[x]
                } else {
                    nodeinterval[x] = 0
                }
                nodesec[x] = +nodesec[(x - 1)] + nodeinterval[(x - 1)];
                x++
            });
            x = 1;
            if (o.timelinehorizontalmargin == 'auto') {
                c = (o.containerwidth - o.timelinewidth) / 2
            } else {
                c = o.timelinehorizontalmargin
            }
            var j = getdisplaytime(totaltime);
            for (x = 1; x < (nodes + 1); x++) {
                $('<div class="node node' + x + '"></div>').appendTo($timeline).data('id', x)
            }
            var k = $timeline.find('.node');
            x = 1;
            var l = k.outerWidth(true),
                nodeheight = k.outerHeight(true),
                halfnodewidth = Math.round(l / 2);
            k.each(function () {
                prenodepos[x] = ((nodeinterval[(x - 1)] / totaltime) * 100).toFixed(4);
                nodepos[x] = +nodepos[(x - 1)] + Math.round(o.timelinewidth * (prenodepos[x] / 100));
                $(this).css({
                    left: (nodepos[x] - halfnodewidth),
                    top: -(Math.round(nodeheight / 2) - Math.round(o.timelineheight / 2))
                });
                if (o.showtooltip) {
                    var a = $container.find('.slide' + x).data('title');
                    if (a) {
                        $(this).prepend('<div class="tooltip">' + a + '</div>')
                    }
                }
                if (o.showtooltiptime) {
                    $(this).find('.tooltip').prepend('<label class="tooltiptime">' + getdisplaytime(nodesec[x]) + '</label><br>')
                }
                x++
            });
            if (o.showtooltip) {
                var m = $container.find('.tooltip')
            }
            $container.css({
                width: o.containerwidth,
                height: o.containerheight
            });
            if (o.transition == 'slide' || o.transition == 'reveal' || o.transition == 'cover') {
                $container.css({
                    overflow: 'hidden'
                })
            }
            $slides.css({
                width: o.containerwidth,
                height: o.containerheight
            });
            $timeline.css({
                width: o.timelinewidth,
                height: o.timelineheight,
                margin: c,
                marginTop: o.timelineverticalmargin,
                marginBottom: o.timelineverticalmargin
            }).css(o.timelineposition, 0);
            $innertimeline.css({
                height: o.timelineheight
            });
            if (o.showtimedisplay && o.timedisplayposition == 'below') {
                d.css({
                    top: (o.timelineheight + 5),
                    left: -f
                })
            } else if (o.showtimedisplay) {
                d.css({
                    bottom: (o.timelineheight + 5),
                    left: -f
                })
            }
            if (o.showtooltip) {
                if (o.tooltipposition == 'below') {
                    m.css({
                        top: nodeheight + 5
                    })
                } else {
                    m.css({
                        bottom: nodeheight + 5
                    })
                }
                m.each(function () {
                    $(this).css({
                        left: -(Math.round($(this).outerWidth(true) / 2) - halfnodewidth)
                    })
                })
            }
            if (o.showpauseplay) {
                g.css({
                    top: (Math.round(o.containerheight / 2) - Math.round(g.outerHeight(true) / 2)),
                    left: (Math.round(o.containerwidth / 2) - Math.round(g.outerWidth(true) / 2))
                });
                if (o.showprevnext) {
                    h.css({
                        top: (Math.round(o.containerheight / 2) - Math.round(h.outerHeight(true) / 2)),
                        right: (Math.round(o.containerwidth / 2) + Math.round(g.outerWidth(true) / 2))
                    });
                    i.css({
                        top: (Math.round(o.containerheight / 2) - Math.round(i.outerHeight(true) / 2)),
                        left: (Math.round(o.containerwidth / 2) + Math.round(g.outerWidth(true) / 2))
                    })
                }
            }
            $slides.each(function () {
                if ($(this).outerWidth() > o.containerwidth) {
                    $(this).width(($(this).width() - parseInt($(this).css('paddingLeft')) - parseInt($(this).css('paddingRight'))))
                }
                if ($(this).outerHeight() > o.containerheight) {
                    $(this).height(($(this).height() - parseInt($(this).css('paddingTop')) - parseInt($(this).css('paddingBottom'))))
                }
            });

            function dtime(a) {
                d.html(getdisplaytime(a));
                if (o.showtotaltime) {
                    d.append(' / ' + j)
                }
            }
            function time_start(a) {
                dtime(a);
                timeinterval = setInterval(function () {
                    seconds++;
                    dtime(seconds)
                }, 1000)
            }
            function time_stop() {
                clearInterval(timeinterval)
            }
            function stop() {
                $innertimeline.stop();
                if (o.showtimedisplay) {
                    time_stop();
                    d.stop()
                }
                playing = false;
                if (o.showpauseplay) {
                    g.attr('class', 'play')
                }
            }
            function start(a, b) {
                if (!b) {
                    seconds = nodesec[a]
                }
                if (o.showtimedisplay) {
                    time_start(seconds)
                }
                if (!b) {
                    $innertimeline.css({
                        width: nodepos[a]
                    });
                    if (o.showtimedisplay) {
                        d.css({
                            left: nodepos[a] - f
                        })
                    }
                }
                if (b) {
                    animationtime = (b * 1000)
                } else {
                    animationtime = (nodeinterval[a] * 1000)
                }
                if (a < nodes) {
                    targetpos = nodepos[(a + 1)]
                } else {
                    targetpos = o.timelinewidth
                }
                if (o.showtimedisplay) {
                    d.animate({
                        left: (targetpos - f)
                    }, animationtime, 'linear')
                }
                $innertimeline.animate({
                    width: targetpos
                }, animationtime, 'linear', function () {
                    if (o.showtimedisplay) {
                        time_stop()
                    }
                    if (a < nodes) {
                        start((a + 1))
                    } else if (o.repeat) {
                        start(1)
                    }
                });
                if (a != activenode) {
                    $container.find('.slide:not(.slide' + a + '):not(.slide' + activenode + ')').stop().animate({
                        opacity: 0
                    }, 0).css({
                        'z-index': 0
                    });
                    if (o.transition == 'fade') {
                        $container.find('.slide' + activenode).stop().animate({
                            opacity: 0
                        }, 300, function () {
                            $(this).css({
                                'z-index': 0
                            })
                        });
                        $container.find('.slide' + a).stop().animate({
                            opacity: 1
                        }, 300, function () {
                            $(this).css({
                                'z-index': 1
                            })
                        })
                    }
                    if (o.transition == 'slide' || o.transition == 'reveal') {
                        $container.find('.slide' + activenode).css({
                            'z-index': 1
                        }).stop(true, true).animate({
                            left: -o.containerwidth
                        }, 600, function () {
                            $(this).css({
                                'z-index': 0,
                                left: 0
                            }).animate({
                                opacity: 0
                            }, 0)
                        })
                    }
                    if (o.transition == 'reveal') {
                        $container.find('.slide' + a).css({
                            'z-index': 0
                        }).stop(true, true).animate({
                            opacity: 1
                        }, 0)
                    }
                    if (o.transition == 'slide') {
                        $container.find('.slide' + a).css({
                            'z-index': 1,
                            left: o.containerwidth
                        }).stop(true, true).animate({
                            opacity: 1
                        }, 0).animate({
                            left: 0
                        }, 600)
                    }
                    if (o.transition == 'instant') {
                        $container.find('.slide' + activenode).animate({
                            opacity: 0
                        }, 0);
                        $container.find('.slide' + a).animate({
                            opacity: 1
                        }, 0)
                    }
                }
                $container.find('.node' + activenode).removeClass('node_active');
                $container.find('.node' + a).addClass('node_active');
                activenode = a;
                playing = true;
                if (o.showpauseplay) {
                    g.attr('class', 'pause')
                }
                if (o.showpauseplay && (a == nodes && !o.repeat)) {
                    stop()
                }
            }
            $.fn.timeliner.pauseplay = function () {
                g.click()
            };
            $.fn.timeliner.play = function () {
                if (!playing) {
                    g.click()
                }
            };
            $.fn.timeliner.pause = function () {
                if (playing) {
                    g.click()
                }
            };
            $.fn.timeliner.next = function () {
                i.click()
            };
            $.fn.timeliner.prev = function () {
                h.click()
            };
            k.click(function () {
                stop();
                start($(this).data('id'))
            }).hover(function () {
                if (o.showtooltip) {
                    $(this).find('.tooltip').show()
                }
            }, function () {
                if (o.showtooltip) {
                    $(this).find('.tooltip').hide()
                }
            });
            if (o.showpauseplay) {
                $container.hover(function () {
                    g.stop().animate({
                        opacity: 0.5
                    }, 300);
                    if (o.showprevnext) {
                        h.stop().animate({
                            opacity: 0.5
                        }, 300);
                        i.stop().animate({
                            opacity: 0.5
                        }, 300)
                    }
                }, function () {
                    g.stop().animate({
                        opacity: 0
                    }, 200);
                    if (o.showprevnext) {
                        h.stop().animate({
                            opacity: 0
                        }, 200);
                        i.stop().animate({
                            opacity: 0
                        }, 200)
                    }
                });
                g.click(function () {
                    if (playing) {
                        stop();
                        timeremaining = (nodeinterval[activenode] - seconds + nodesec[activenode])
                    } else {
                        if (activenode == nodes && !o.repeat) {
                            start(1)
                        } else {
                            start(activenode, timeremaining)
                        }
                    }
                }).hover(function () {
                    $(this).stop().animate({
                        opacity: 0.9
                    }, 200)
                }, function () {
                    $(this).stop().animate({
                        opacity: 0.5
                    }, 400)
                });
                if (o.showprevnext) {
                    h.click(function () {
                        if (activenode == 1) {
                            $container.find('.node' + nodes).click()
                        } else {
                            $container.find('.node' + (activenode - 1)).click()
                        }
                    }).hover(function () {
                        $(this).stop().animate({
                            opacity: 0.9
                        }, 200)
                    }, function () {
                        $(this).stop().animate({
                            opacity: 0.5
                        }, 400)
                    });
                    i.click(function () {
                        if (activenode == nodes) {
                            $container.find('.node1').click()
                        } else {
                            $container.find('.node' + (activenode + 1)).click()
                        }
                    }).hover(function () {
                        $(this).stop().animate({
                            opacity: 0.9
                        }, 200)
                    }, function () {
                        $(this).stop().animate({
                            opacity: 0.5
                        }, 400)
                    })
                }
            }
            $timeline.click(function (e) {
                var a = ((e.pageX - $(this).offset().left) + halfnodewidth);
                var b;
                x = 1;
                for (x in nodepos) {
                    if (x > 0 && x < nodes) {
                        if ((nodepos[x] < a) && (nodepos[(+x + 1)] > a)) {
                            b = x
                        }
                    }
                }
                if (a > nodepos[nodes]) {
                    b = nodes
                }
                if (a < 0) {
                    b = 1
                }
                if (b != activenode) {
                    $timeline.find('.node' + b).click()
                }
            });
            if (o.keyboard) {
                $(document).keydown(function (e) {
                    if (e.keyCode == 32) {
                        e.preventDefault();
                        g.click()
                    }
                })
            }
            $container.find('.slide1').animate({
                opacity: 1
            }, 0).css({
                'z-index': 1
            });
            if (o.autoplay) {
                start(1)
            }
        })
    }
})(jQuery);
