$(document).ready(function() {

    // Settings
    var UPDATE_INTERVAL = 10000;
    var DEV = true;
    
    // Outputs to Firebug console, remains silent otherwise
    $.log = function(msg) {
        if (!DEV) {
            return;
        }
        if ('console' in window) {
            console.log(msg);
        } else {
            //alert(msg);
        }
    }
    
    $('.zip-check button').click(function() {
        $(this).closest('form').submit();
        return false;
    });
    
    $('.zip-check input[type=text]').each(function() {
        var input = $(this);
        input.attr('spellcheck', false);
        input.data('initial', $(this).attr('value'));
        input.bind('keydown keyup change', function() {
            input.removeClass('unchanged');
        });
        var inputReset = function() {
            if (input.val() == input.data('initial')) {
                input.val('');
            }
        }
        input.focus(inputReset);
        input.blur(function() {
            if (input.val() == '') {
                input.val(input.data('initial'));
                input.addClass('unchanged');
            }
        });
        input.closest('form').submit(inputReset);
        input.addClass('unchanged');
    });
    
    function notificationsVisible()
    {
        return $('#notifications').data('visible');
    }
    
    function hasNotifications() {
        return $('#notifications ul').find('li').length;
    }

    function toggleNotifications(visible)
    {
        if (!visible) {
            $('#notifications ul').hide();
            $('#notifications').data('visible', false);
            $.get($('#notifications-mark-all-read').attr('href'));
            $('#show-notifications').addClass('collapsed');
            $('#show-notifications').removeClass('expanded');
        } else if (hasNotifications()) {
            $('#notifications ul').show();
            $('#notifications').data('visible', true);
            $('#show-notifications').addClass('expanded');
            $('#show-notifications').removeClass('collapsed');
        }
    }
    
    $('#show-notifications').click(function(event) {
        if (notificationsVisible()) {
            toggleNotifications(false);
        } else {
            toggleNotifications(true);
        }
    });
    /*
    $('#notifications ul').mouseleave(function(event) {
        $('#notifications ul').hide();
        $('#notifications ul').data('visible', false);
    });
    */
    
    function updateNotifications(data) {
        updateElement('#notifications-list', $(data));
        updateElement('#notifications-count', $(data));
        if (notificationsVisible()) {
            toggleNotifications(true);
        }
        if (hasNotifications()) {
            $('#show-notifications').removeClass('disabled');
        }
    }
    
    $('#id_accept_terms').change(function() {
        if (this.checked) {
            $(this).closest('.form-row').find('a.open-dialog').trigger('click');        
        }
    });
    
    $('.modal-confirm').each(function() {
        var dialog = $(this);
        dialog.dialog({
            autoOpen: false,
            title: 'Information',
            modal: true,
            open: function() {
                dialog.data('okClicked', false);
            },
            buttons: {
                'OK': function() {
                    dialog.data('okClicked', true);
                    $(this).dialog('close');
                }
            }
        });
    });

    $('#id_construction_status').change(function() {
        if ($(this).val() == 100) {
            $('.modal-confirm.plant-planned').dialog('open');
        }
    });
    
    $('a.make-bid').click(function() {
        $('.modal-confirm.make-bid').data('href', $(this).attr('href'));
        $('.modal-confirm.make-bid').dialog('open');
        return false;
    });
    
    $('.modal-confirm.make-bid').dialog('option', 'close', function() {
        if ($(this).data('okClicked')) {
            document.location.href = $(this).data('href');
        }
    });
    
    // Convert links with class="open-dialog" to open in JQuery dialog
    $('.open-dialog').click(function(event) {
        var link = $(this);
        var scrollToEnd = $(this).hasClass('scroll-to-end');
        event.preventDefault();
        var _this = $(this);
        var dialog = $('<div><span class="icon loading"><span>loading</span></span></div>');
        dialog.attr('id', 'dialog');
        dialog.dialog({
            autoOpen: false,
            title: _this.html(),
            close: function() {
                if (scrollToEnd) {
                    if (!$(this).data('scrolledToEnd')) {
                        var checkbox = link.closest('.form-row').find('input[type=checkbox]');
                        if (checkbox.length) {
                            checkbox[0].checked = false;
                        }
                    }
                }
            },
            buttons: (scrollToEnd ? {
                'OK': function() {
                    $(this).dialog('close');
                }
            } : null)
            
        });

        if (scrollToEnd) {
            var okButton = dialog.closest('.ui-dialog').find('.ui-dialog-buttonset button');
            okButton.attr('disabled', true);
            okButton.css('opacity', .5);
            dialog.scroll(function() {
                var diff = $(this).scrollTop() + $(this).outerHeight() - this.scrollHeight;
                if (diff == 0) {
                    $(this).data('scrolledToEnd', true);
                    okButton.css('opacity', 1);
                    okButton.attr('disabled', false);
                }
            });
        }
        
        var w = Math.max(100, $(window).width() *.75 );
        var h = Math.max(100, $(window).height() * .75);
        dialog.dialog('option', 'width', w);
        dialog.dialog('option', 'height', h);
        dialog.dialog('option', 'modal', true);
        dialog.dialog('open');
        $.get($(this).attr('href'), function(data) {
            dialog.html($(data).find('#content-main').html());
            if (scrollToEnd) {
                dialog.prepend('<p class="info-highlight">Bitte scrollen Sie bis ans Ende und lesen Sie den ganzen Text.</div>');
            }
        });
    });
    
    tooltipEvents = {
          def:     "click mouseover,blur mouseout",
          input:   "focus,blur",
          widget:  "focus mouseover,blur mouseout",
          tooltip: "click mouseover,blue mouseout"
    }

    function initTooltip(element, options) {
        var defaults = {
            events: tooltipEvents,
            // The IE behavior is slow and will result in the tooltip with box-shadow etc flickering 
            // in the top left corner before it is positioned. Fixed by assigning the classes after 
            // showing tooltip:
            onShow: function() {
                this.getTip().addClass('box-shadow rounded-corners');
            },
            onHide: function() {
                this.getTip().removeClass('box-shadow rounded-corners');
            }
        };  
        element.tooltip($.extend(defaults, options));
    }
    
    // Prepare form tooltips 
    $('.help-text').each(function() {
        var splitter = '|';
        var text = $(this).html();
        if (text.indexOf(splitter) != -1) {
            var split = text.split(splitter);
            var input = $(this).closest('div').find('input, textarea, select');
            var info_link = $(' <a class="info icon" href="javascript:void(0)" title="'+$.trim(split[1])+'">&nbsp;<span>Info</span></a>');
            $(this).html($.trim(split[0])+' ');
            $(this).append(info_link);
            initTooltip(info_link, {position: 'top center'});
        }
    });
    
    $.fn.initContents = function() {
        $(this).each(function() {
            // Prepare link tooltips
            $(this).find('.tip').each(function() {
                if ($(this).hasClass('side')) {
                    var position = 'center right';
                    var tipClass = 'tooltip side';
                } else {
                    var position = 'top center';
                    var tipClass = 'tooltip';
                }
                if ($(this).hasClass('nowrap')) {
                    tipClass += ' nowrap';
                }
                initTooltip($(this), {position: position, tipClass: tipClass});
            });
        });
    };
    $('body').initContents();
    
    $.fn.blink = function(repeat, dur) {
        if (repeat == undefined) {
            repeat = 0;
        }
        if (dur == undefined) {
            dur = 1000;
        }
        var params = [
            {fadeout: .4 * dur, stayout: .1 * dur, opout: .3, fadein: .3 * dur, stayin: .2 * dur, opin: 1},
        ]
        $(this).each(function() {
            $(this).cyclicFade({
                repeat: repeat,
                params: params
            });
        });
    };

    // Hides/shows an child element of parent
    function setIndicator(parent, sel, visible) 
    {
        if (visible) {
            parent.find(sel).show();
        } else {
            parent.find(sel).hide();
        }
    };

    // Hides/shows the tooltip of element
    function setTooltip(sel, visible) 
    {
        if (visible) {
            sel.data('tooltip').show();
        } else {
            sel.data('tooltip').hide();
        }
    };

    // Replaces an page elemented identified by `sel` with the same page element found in 
    // JQuery array `elements`, unless `elements` doesn't contain anything with that selector.
    function updateElement(sel, elements)
    {
        var found = elements.find(sel);
        if (found.length) {
            $('.tooltip').remove();
            found.initContents();
            $(sel).replaceWith(found);
            $.log('updateElement: updated: '+sel);
        } else {
            $.log('updateElement: not found: '+sel);
        }
    }

    function disablePostPrice(inputs) 
    {
        if (inputs == undefined) {
            inputs = $('#auction-ranking').find('.update-price input[name=price]');
        }
        inputs.attr('disabled', true);
    }

    function updateAuctionRanking(data)
    {
        var scrollTop = $('#auction-ranking').scrollTop();
        updateElement('#auction-ranking', $(data));
        $('#auction-ranking').scrollTop(scrollTop);
        initPostPrice();
        updateElement('#auction-ranking-updated', $(data));
    }
    
    var bidComparisonPlot;
    var priceDevelopmentPlot;

    function getChartsData(container)
    {
        var found = $(container).find('#auction-charts-data');
        if (found.length) {
            eval('var data = '+found.text());
            if (!data.bidComparison.series[0].length) {
                data.bidComparison.series[0] = [null];
            }
            if (!data.priceDevelopment.series[0].length) {
                data.priceDevelopment.series[0] = [null];
            }
            return data;
        } else {
            return false;
        }
    }
    
    function updateAuctionInfo(data)
    {
        updateElement('#auction-bid-history', $(data));
        updateElement('#auction-end', $(data));
        updateElement('#auction-status', $(data));
        updateNotifications(data);
        updateAuctionCharts(getChartsData(data));
    }
    
    // Prepares AJAX price updater forms 
    function initPostPrice() 
    {
        $('#auction-ranking').find('.update-price').each(function() {
            var input = $(this).find('input[name=price]');
            var form = $(this);
            var submitButton = form.closest('tr').find('.submit');
            var cancelButton = form.closest('tr').find('.remove');
            var setButtons = function(visible) {
                if (visible) {
                    submitButton.show();
                    cancelButton.show();
                } else {
                    submitButton.hide();
                    cancelButton.hide();
                }
            };
            input.focus(function(event) {
                $.log('focus');
                setIndicator($('#auction-bids h3'), '.loading.indicator', false);
                $(this).data('editing', true);
                input.addClass('typing');
                setButtons(true);
                input.select();
                setTooltip(input.closest('tr'), true);
            });
            var resetForm = function(event) {
                input.val(input.data('storedVal'));
                input.data('editing', false);
                setIndicator(form, '.error.indicator', false);
                setButtons(false);
                input.removeClass('typing');
                updateAuction();
//              setTooltip(input.closest('tr'), false);
            };
            submitButton.click(function(event) {
                form.submit();
            });
            cancelButton.click(function(event) {
                resetForm();
            });
            input.data('storedVal', input.val());
            var updatePrice = function() {
                var tableRowId = input.closest('tr').attr('id');
                var newVal = input.val();
                var storedVal = input.data('storedVal');
                if (newVal == storedVal) {
                    setIndicator(form, '.error.indicator', false);
                    resetForm();
                    return true;
                } else {
                    if (!newVal.match(/^[0-9]+$/) || parseInt(newVal) > parseInt(storedVal) || parseInt(newVal) == 0) {
                        setIndicator(form, '.error.indicator', true);
                        setTooltip(form.find('.error.indicator'), true);
                        input.focus();
                    } else {
                        setIndicator(form, '.loading.indicator', true);
                        setIndicator(form, '.error.indicator', false);
                        var inputs = form.find('input');
                        var formData = inputs.serializeArray();
                        form.data('updating', true);
                        setButtons(false);
                        input.data('editing', false);
                        disablePostPrice(input);
                        stopUpdateAuction();
                        $.ajax({
                            url: form.attr('action')
                            ,type: 'POST'
                            ,data: formData
                            ,dataType: 'html'
                            ,success: function(data) {
                                if (!isEditingPrices()) {
                                    updateAuctionRanking(data);
                                    $('#'+tableRowId).blink(2, 500);
                                }
                                updateAuctionInfo(data);
                            }
                            ,error: function() {
                                setIndicator(form, '.error.indicator', true);
                                input.val(input.data('storedVal'));
                            }
                            ,complete: function() {
                                initUpdateAuction();
                                setIndicator(form, '.loading.indicator', false);
                            }
                        });
                        return true;
                    }
                }
                return false;
            };
            input.blur(function(event) {
                $.log('blur');
                if (input.val() == input.data('storedVal')) {
                    resetForm();
                }
                setTooltip(form.find('.error.indicator'), false);
            });
            form.submit(function(event) {
                event.preventDefault();
                if (!form.data('updating') && !input.attr('disabled')) {
                    updatePrice();
                }
            });
        });
    };
    
    // Checks if user is currently editing any of the AJAX price updater inputs
    function isEditingPrices()
    {
        var isEditing = false;
        $('#auction-ranking').find('.update-price').each(function() {
            var input = $(this).find('input[name=price]');
            if (input.data('editing') == true) {
                $.log('currently editing '+input.val());
                isEditing = true;
            }
        });
        return isEditing;
    }
    
    var rankingTimeout = null;

    // Starts the timeout for automatic auction ranking update
    function stopUpdateAuction()
    {
        if (rankingTimeout != null) {
            clearTimeout(rankingTimeout);
            rankingTimeout = null;
        }
        
    }

    // Starts a timeout for automatic auction ranking update
    function initUpdateAuction()
    {
        rankingTimeout = setTimeout(updateAuction, UPDATE_INTERVAL);
        setIndicator($('#auction-bids h3'), '.loading.indicator', false);
    }

    // AJAX-updates the auction countdown and the ranking, unless user is currently editing any 
    // AJAX price updater inputs
    function updateAuction(countdownFinished) 
    {
        $.log('updateAuction()');
        stopUpdateAuction();
        if (countdownFinished || !isEditingPrices()) {
            setIndicator($('#auction-bids h3'), '.loading.indicator', true);
            $.ajax({
                url: document.location.href
                ,type: 'GET'
                ,dataType: 'html'
                ,success: function(data) {
                    $.log('fetched ranking');
                    if (countdownFinished || !isEditingPrices()) {
                        updateAuctionRanking(data);
                    }
                    if (!countdownFinished) {
                        initCountdown($(data));
                    }
                    updateAuctionInfo(data);
                }
                ,error: function() {
                    $.log('error fetching ranking');
                }
                ,complete: function() {
                    initUpdateAuction();
                }
            });
        } else {
            initUpdateAuction();
        }
    }
    
    var countdownAlreadyEnded = false;
    
    function initCountdown(fromData)
    {
        if (!fromData) {
            fromData = $('#auction-details');
        }
        var found = fromData.find('#auction-countdown-time');
        if (!found.length) {
            return false;
        }
        var time = found.text();
        var image = fromData.find('#auction-countdown-image').attr('src');
        if (!countdownAlreadyEnded) {
            countdownAlreadyEnded = time.match(/^[0\:]+$/);
        }
        var milliseconds = parseInt(fromData.find('#auction-countdown-milliseconds').text());
        $.log('initCountdown: '+time+' in '+milliseconds+' ms'+(countdownAlreadyEnded ? ' (already ended)' : ''));
        if (!countdownAlreadyEnded || !$('#auction-countdown').data('initialized')) {
            setTimeout(function() {
                $.log('setting countdown');
                $('#auction-countdown').data('initialized', true);
                $('#auction-countdown').html('');
                $('#auction-countdown').countdown({
                    stepTime: 60,
                    format: 'dd:hh:mm:ss',
                    startTime: time,
                    digitImages: 6,
                    digitWidth: 34,
                    digitHeight: 50,
                    timerEnd: function() { 
                        $.log('timer end');
                        if (!countdownAlreadyEnded) {
                            $.log('countdown end');
                            disablePostPrice();
                            updateAuction(true);
                            $("#auction-countdown").blink(0);
                        }
                    },
                    image: image
                });
            }, milliseconds);
        }
        return !countdownAlreadyEnded;
    }

    function initAuctionCharts(chartsData)
    {
        var gridOptions = {
            drawGridLines: true,        // wether to draw lines across the grid or not.
            gridLineColor: '#e8e8e8',    // *Color of the grid lines.
            background: '#f8f8f8',      // CSS color spec for background color of grid.
            borderColor: '#e0e0e0',     // CSS color spec for border around grid.
            borderWidth: 2.0,           // pixel width of border around grid.
            shadow: false               // draw a shadow for grid.
        };

        var seriesDefaults = {
            lineWidth: 2, // Width of the line in pixels.
            shadowAlpha: 0.05,   // Opacity of the shadow.
            showLine: true,     // whether to render the line segments or not.
            showMarker: true,   // render the data point markers or not.
            rendererOptions: {
                shadowDepth: 4,
                shadowAlpha: 0.03,   // Opacity of the shadow.
                barPadding: 4,
                barMargin: 4
            },
            markerOptions: {
                show: true,             // wether to show data point markers.
                style: 'filledCircle',  // circle, diamond, square, filledCircle.
                                        // filledDiamond or filledSquare.
                lineWidth: 2,       // width of the stroke drawing the marker.
                size: 9,            // size (diameter, edge length, etc.) of the marker.
                shadow: true,       // wether to draw shadow on marker or not.
                shadowAlpha: .05   // Opacity of the shadow
            }
        };
        
        var bidComparisonOptions = {
            grid: gridOptions,
            seriesDefaults: seriesDefaults,
            legend: {
                show: false
            },
            series: [
                {renderer:$.jqplot.BarRenderer, rendererOptions: {varyBarColor: true}}, 
            ],
            axes: {
                xaxis: {
                    renderer:$.jqplot.CategoryAxisRenderer
                }, 
                yaxis: {
                    min: 0
                }
            },
            cursor: {
                show: true,
                showVerticalLine: false,
                showHorizontalLine: false,
                showCursorLegend: false,
                showTooltip: true,
                zoom: false,
                dblClickReset: true,
                intersectionThreshold: 6
            } 
        };
    
        var priceDevelopmentOptions = { 
            grid: gridOptions,
            seriesDefaults: seriesDefaults,
            legend: {show: true, location: 'ne'},
            axes: { 
                xaxis: { 
                    renderer:$.jqplot.DateAxisRenderer, 
                    tickInterval: (chartsData.priceDevelopment.series[0].length < 7 ? '1 day' : '1 week') 
                }, 
                yaxis: { 
                    renderer: $.jqplot.LogAxisRenderer 
                } 
            }, 
            cursor: {
                show: true,
                showVerticalLine: false,
                showHorizontalLine: false,
                showCursorLegend: false,
                showTooltip: true,
                zoom: false,
                dblClickReset: true,
                intersectionThreshold: 6
            } 
        };  
    
        if ($('#auction-bid-comparison-chart').length) {
            $('#auction-bid-comparison-chart').empty();
            bidComparisonPlot = $.jqplot('auction-bid-comparison-chart', chartsData.bidComparison.series, 
                $.extend(true, bidComparisonOptions, chartsData.bidComparison.options));
        }
        if ($('#auction-price-development-chart').length) {
            $('#auction-price-development-chart').empty();
            priceDevelopmentPlot = $.jqplot('auction-price-development-chart', chartsData.priceDevelopment.series, 
                $.extend(true, priceDevelopmentOptions, chartsData.priceDevelopment.options));
        }
    }
    
    function updateAuctionCharts(chartsData)
    {
        if (!chartsData) {
            return;
        }
        // works but is currently not rescaling/updating number of xaxis ticks, nor the colors
        var data = [];
        var xVal = chartsData.bidComparison.options.axes.xaxis.ticks;
        var yVal = chartsData.bidComparison.series[0];
        for (var i in xVal) {
            data.push([xVal[i], yVal[i]]);
        }
        bidComparisonPlot.series[0].data = data;
        bidComparisonPlot.redraw();
    }
        
    // Initialize auction page features
    if ($('#auction-ranking').length) {
        if (initCountdown()) {
            initPostPrice();
            initUpdateAuction();
        }
        initAuctionCharts(getChartsData('body'));
    }
    
    $('.script-only').show();
});
