
Function.prototype.withScope = function( scope, args, appendArgs ) {
    var method = this;
    return function() {
        var callArgs = args || arguments;
        if ( appendArgs ) {
            callArgs = Array.prototype.slice.call( arguments, 0 );
            callArgs = callArgs.concat( args );
        }
        return method.apply( scope || window, callArgs );
    };
}

var POIRE = {

    tipConfig: { delay: 200, fadeIn: 100, fadeOut: 100, defaultPosition: 'top' },

    profile: null,
    staticData: {},
    formFields: {},
    columns: {},
    listing: {},
    sorting: {},
    sortBy: null,
    sortDesc: false,

    init: function() {

        this.profile = $.url.param( 'p' );
        
        $.each( this.profile.split( '.' ), function ( index, segment ) {
            $('head').append( '<link rel="stylesheet" href="css/' + segment + '.css" type="text/css">' );
        } );

        this.staticFill();
        this.formFill();

        $('#form-button').click( this.moveBand.withScope( this, [ '-100%' ], true ) );
        $('#list-button').click( this.moveBand.withScope( this, [ '0' ], true ) );
        $('#info-button').click( this.moveBand.withScope( this, [ '-100%' ], true ) );
        $('#xtra-button').click( this.moveBand.withScope( this, [ '-200%' ], true ) );

        $(window).resize( this.resize );
        this.resize();
    },

    moveBand: function( event, margin ) {

        $('#band').animate( { 'margin-left': margin }, 800 );
    },

    resize: function() {

        $('#form-contents').height( $('#view-form').height() - 100 );
        $('#list-contents').height( $('#view-list').height() - 145 );
        $('#info-contents').height( $('#view-info').height() - 100 );
        $('#xtra-contents').height( $('#view-xtra').height() - 100 );
    },

    request: function( name, params, success ) {

        if ( ! $.isFunction( success ) ) {
            success = this.responseHandler;
        }

        var data = { 'profile': this.profile, 'request': name, 'params': params };

        $.post( 'engine/request.php', data, success, 'json' );
    },

    staticFill: function() {

        this.request( 'getStaticData', null, this.staticFill_exec.withScope( this ) );
    },

    staticFill_exec: function( data, textStatus, xhr ) {

        if ( textStatus == 'success' ) {
            this.staticData = data;
            $.each( this.staticData, this.staticFill_replace.withScope( this ) );
        } else {
            alert( 'Error getting server data (form fields)' );
        }
    },

    staticFill_replace: function( name, data ) {

        var el = $('#staticData\\:' + name);
        if ( el ) {
            el.html( data );
        }
    },

    formFill: function() {

        $('#form-button').click( this.formSubmit.withScope( this ) );
        this.request( 'getFormFields', null, this.formFill_exec.withScope( this ) );
    },

    formFill_exec: function( data, textStatus, xhr ) {

        if ( textStatus == 'success' ) {
            this.formFields = data.fields;
            $.each( this.formFields, this.formFill_addField.withScope( this ) );
            $('.form-checkbox').click( function( event ) {
                $(event.currentTarget).toggleClass( 'form-checkbox-selected' );
                var rel = $(event.currentTarget).attr('rel');
                if ( rel ) {
                    eval( rel + '.withScope( this ).call()' );
                }
            }.withScope( this ) );
            $('.form-input-expand').click( function( event ) {
                var rel = $(event.currentTarget).attr('rel');
                $('#' + rel).css( 'height', 'auto' );
                $('#expand-' + rel).css( 'display', 'none' );
            } );
            $('.form-input-collapse').click( function( event ) {
                var rel = $(event.currentTarget).attr('rel');
                $('#' + rel).css( 'height', $('#' + rel).attr('rel') );
                $('#expand-' + rel).css( 'display', 'block' );
            } );
            $('#form-contents .tooltip').tipTip( this.tipConfig );
        } else {
            alert( 'Error getting server data (form fields)' );
        }
    },

    formFill_addField: function( name, data ) {

        var inputs = '';

        if ( data.skip )
            return;

        switch ( data.type ) {
            case 'text':
                inputs += '<input type="text" id="form-input-' + name + '-text" size="' + data.size + '">';
                if ( data.suffix ) {
                    inputs += '&nbsp;' + data.suffix;
                }
                break;
            case 'range':
                inputs += this.staticData[ 'formRangeFrom' ] + '&nbsp;';
                inputs += '<input type="text" id="form-input-' + name + '-min" size="' + data.size + '">';
                inputs += '&nbsp;' + this.staticData[ 'formRangeTo' ] + '&nbsp;';
                inputs += '<input type="text" id="form-input-' + name + '-max" size="' + data.size + '">';
                if ( data.suffix ) {
                    inputs += '&nbsp;' + data.suffix;
                }
                break;
            case 'checkbox':
                if ( data.expand ) {
                    inputs += '<div class="check-group form-input-expandable" id="check-group-' + name + '" rel="' + data.expand + '" style="height: ' + data.expand + '">';
                } else {
                    inputs += '<div class="check-group" id="check-group-' + name + '">';
                }
                var style = data.width ? ( ' style="width: ' + data.width + '"' ) : '';
                $.each( data.options, function( key, label ) {
                    style += data.onchange ? ( ' rel="' + data.onchange + '"' ) : '';
                    inputs += '<div class="form-checkbox" id="form-input-' + name + '-check-' + key + '"' + style + '><p>' + label + '</p></div>';
                }.withScope( this ) );
                if ( data.expand ) {
                    inputs += '<div class="form-input-collapse" rel="check-group-' + name + '">' + data.expand_less + '</div>';
                    inputs += '</div>';
                    inputs += '<div id="expand-check-group-' + name + '" class="form-input-expand" rel="check-group-' + name + '">' + data.expand_more + '</div>';
                } else {
                    inputs += '</div>';
                }
                break;
            case 'select':
                inputs += '<select id="form-input-' + name + '-select">';
                if ( data.undef ) {
                    inputs += '<option value="">' + data.undef + '</option>';
                }
                $.each( data.options, function( key, label ) {
                    inputs += '<option value="' + key + '">' + label + '</option>';
                }.withScope( this ) );
                inputs += '</select>';
                break;
        }

        if ( data.withprev ) {
            $('#form-tbody').children().last().children().last().append( '<span class="form-withprev">' + inputs + '</span>' );

        } else {
            var help = data.help ? ( ' <span class="form-help tooltip" title="' + data.help + '">&nbsp;</span>' ) : '';
            $('#form-tbody').append( '<tr><td class="label">' + data.label + help + '</td><td>' + inputs + '</td></tr>' );
        }
    },

    formSubmit: function() {

        var params = { 'query': {} };
        $.each( this.formFields, function( name, data ) {
            var quest = {};
            switch ( data.type ) {
                case 'text':
                    quest[ 'text' ] = $('#form-input-' + name + '-text').val();
                    break;
                case 'range':
                    quest[ 'min' ] = $('#form-input-' + name + '-min').val();
                    quest[ 'max' ] = $('#form-input-' + name + '-max').val();
                    break;
                case 'checkbox':
                    $.each( data.options, function( key, label, name ) {
                        quest[ 'check:' + key ] = $('#form-input-' + name + '-check-' + key).hasClass( 'form-checkbox-selected' ) ? '1' : '';
                    }.withScope( this, [ name ], true ) );
                    break;
                case 'select':
                    quest[ 'select' ] = $('#form-input-' + name + '-select').val();
                    break;
            }
            params.query[ name ] = quest;
        }.withScope( this ) );

        this.listReset();

        this.request( 'searchQuery', params, this.listResult_build.withScope( this ) );
    },

    listResult_build: function( data, textStatus, xhr ) {

        this.resultId = data.id;
        this.columns = data.columns;
        this.listing = data.result;
        this.sorting = data.sorting;
        this.sortBy = data.sortby;
        this.sortDesc = false;
        this.countRows = data.count;
        this.countJoin = data.countJoin;
        this.countText = data.countText;
        this.joinColumns = data.joincolumns;

        this.listGenerate();
        this.listActivate();
    },

    listReset: function() {

        $('#list-result-body').html( '<tr><td class="list-loading">' + this.staticData[ 'listLoading' ] + '</td></tr>' );
        $('#list-result-count').empty();
    },

    listGenerate: function() {

        $('#list-result-body').empty();

        var head = '<tr>';
        $.each( this.columns, function( name, data ) {
            if ( data.sortable ) {
                var thClass = 'list-result-column-' + name;
                var sortClass = 'list-result-header-sort';
                if ( name == this.sortBy ) {
                    thClass += ' sorted';
                    if ( this.sortDesc ) {
                        thClass += ' sorted-desc';
                    }
                }
                head += '<th class="' + thClass + '" rel="' + name + '"><a class="' + sortClass + '">' + data.header + '</a></th>';
            } else {
                head += '<th class="list-result-column-' + name + '">' + data.header + '</th>';
            }
        }.withScope( this ) );
        head += '</tr>';
        $('#list-result-head').html( head );

        $('.list-result-header-sort').click( this.listSort.withScope( this ) );

        if ( this.countRows ) {

            var sorted = this.sorting[ this.sortBy ].slice();
            if ( this.sortDesc ) {
                sorted.reverse();
            }
            this.lastEntry = '~';
            this.lastJoin = '~';
            this.joinRow = false;
            $.each( sorted, function( index, entry ) {

                if ( this.listing[ entry ].joinvalue == this.lastJoin  ) {
                    this.joinRow = true;
                } else {
                    if ( this.joinRow ) {
                        var fillRow = '<tr class="list-result-row-filler">';
                        $.each( this.columns, function( name, data ) {
                            if ( $.inArray( name, this.joinColumns ) == -1 ) {
                                fillRow += '<td class="list-result-column-' + name + '"></td>';
                            } else {
                                var cell = $('#list-result-cell-' + this.lastEntry + '-' + name);
                                var rowspan = cell.attr( 'rowspan' );
                                cell.attr( 'rowspan', rowspan ? ( 1 + rowspan ) : 2 );
                            }
                        }.withScope( this ) );
                        fillRow += '</tr>';
                        $('#list-result-body').append( fillRow );
                    }
                    this.joinRow = false;
                    this.lastEntry = entry;
                    this.lastJoin = this.listing[ entry ].joinvalue;
                }

                this.row = '<tr id="list-result-row-' + entry + '" rel="list-result-row-' + ( this.joinRow ? this.lastEntry : entry ) + '" xid="' + this.listing[ this.joinRow ? this.lastEntry : entry ].id + '" class="list-result-row">';

                $.each( this.columns, function( name, data, entry ) {
                    if ( ! this.joinRow || $.inArray( name, this.joinColumns ) == -1 ) {
                        var cellclass = 'list-result-column-' + name + ( this.joinRow ? '' : ' list-result-newrow' );
                        if ( this.listing[ entry ].cellclass[ name ] ) {
                            cellclass += ' ' + this.listing[ entry ].cellclass[ name ];
                        }
                        this.row += '<td id="list-result-cell-' + entry + '-' + name + '" class="' + cellclass + '">';
                        this.row += this.listing[ entry ].celldata[ name ] ? this.listing[ entry ].celldata[ name ] : '&nbsp;';
                        this.row += '</td>';
                    } else {
                        if ( this.joinRow ) {
                            var cell = $('#list-result-cell-' + this.lastEntry + '-' + name);
                            var rowspan = cell.attr( 'rowspan' );
                            cell.attr( 'rowspan', rowspan ? ( 1 + rowspan ) : 2 );
                        }
                    }
                }.withScope( this, [ entry ], true ) );

                this.row += '</tr>';
                $('#list-result-body').append( this.row );

            }.withScope( this ) );

            $('#list-result-count').html( this.countText );
            $('#view-list .tooltip').tipTip( this.tipConfig );

        } else {

            $('#list-result-count').empty();
            $('#list-result-body').html( '<tr><td class="list-loading">' + this.staticData[ 'listEmpty' ] + '</td></tr>' );
        }

    },

    listActivate: function() {
        $('.list-result-row').hover( function( event ) {
            $('#' + $(event.currentTarget).attr( 'rel' )).addClass( 'row-hover' );
            $(event.currentTarget).toggleClass( 'lowerhalf', $(event.currentTarget).offset().top - $('#list-contents').offset().top > $('#list-contents').height() / 2 );
        }, function( event ) {
            $('#' + $(event.currentTarget).attr( 'rel' )).removeClass( 'row-hover' );
        } );

        $('.list-result-row').click( function( event ) {
            var id = parseInt( $(event.currentTarget).attr( 'xid' ) );
            if ( id ) {
                this.infoId = id;
                this.request( 'getDetails', { 'id': id }, this.infoScreen_build.withScope( this ) );
                this.infoReset();
                this.moveBand( event, '-200%' );
            }
        }.withScope( this ) );
        $('#list-printer').attr( 'href', 'engine/printlist.php?profile=' + this.profile + '&result=' + this.resultId + '&sort=' + this.sortBy );
    },

    listSort: function( event ) {

        var sortBy = $(event.currentTarget.parentNode).attr('rel');
        if ( this.sorting[ sortBy ] ) {
            if ( sortBy == this.sortBy ) {
                this.sortDesc = ! this.sortDesc;
            } else {
                this.sortBy = sortBy;
                this.sortDesc = false;
            }
            this.listGenerate();
            this.listActivate();
        }
    },

    infoReset: function() {

        $('#info-contents').html( '<p class="info-loading">' + this.staticData[ 'infoLoading' ] + '</p>' );
    },

    infoScreen_build: function( data, textStatus, xhr ) {

        this.resize(); // IE needs this
        $('#info-contents').html( data.html );
        $('#view-info .tooltip').tipTip( this.tipConfig );
        $('#info-contents .slideshow').slimbox( { counterText: this.staticData[ 'slimboxText' ] } );
        $('.info-maplink').click( function( event ) {
            $('#xtra-contents').empty();
            $('#xtraHeader').html( this.staticData[ 'xtraHeaderMap' ] );
            var iframe = $(event.currentTarget).attr('rel');
            $('#xtra-contents').html( '<iframe class="xtra-iframe" src="' + iframe + '" frameborder="0"></iframe>' );
            this.moveBand( event, '-300%' );
        }.withScope( this ) );
        $('#info-printer').attr( 'href', 'engine/printinfo.php?profile=' + this.profile + '&id=' + this.infoId );
        $('#info-pdf').attr( 'href', 'engine/printpdf.php?profile=' + this.profile + '&id=' + this.infoId );
    }
}

$(document).ready( function() { POIRE.init() } );

