$( function() {
    // flash multi file upload
    var handler = function( name ) { return function() { /* d( { handler: name, args: arguments } ); */ }; };
    
    $.extend( {
        create_uploader_handler: function( swfUpload, progress, check_url ) {
            return {
                queue: {},
                count: 0,
                progress: progress,
                interval: null,
                check_url: check_url,
                check_count: {},
                MAX_CHECKS: 500,
                error: 'Error: File damaged or unsupported.',
                timeout: 1500,
                number: 0,
                
                
                /* add
                    add file to queue (not uploading yet)
                */
                add: function( file ) {
                    this.queue[ file ] = {
                        status: 'waiting',
                        error: null,
                        html: $.uploader_queue_item( {
                            filename: file,
                            status: 'waiting..'
                        } ).appendTo( progress )
                    };
                },
                
                
                /* start
                    begin uploading this file
                */
                start: function( file ) {
                    var queue_file = this.queue[ file ];
                    queue_file.number = this.number++;
                    queue_file.status = 'uploading';
                    delete this.check_count[ file ];
                    $.uploader_queue_item( {
                        status: 'uploading..'
                    }, queue_file.html );
                },
                
                
                /* progress
                    having progress report in uploading this file
                */
                progress: function( file, progress_percent ) {
                    var queue_file = this.queue[ file ];
                    $.uploader_queue_item( {
                        progress_percent: progress_percent
                    }, queue_file.html );
                },
                
                
                /* success
                    single file finished uploading, going to transforming now!
                */
                success: function( file ) {
                    var queue_file = this.queue[ file ];
                    queue_file.status = 'transforming';
                    $.uploader_queue_item( {
                        status: '<span style="text-decoration: blink">transforming</span>',
                        progress_percent: 100
                    }, queue_file.html );
                    
                    
                    this.count++;
                    if ( ! this.IS_TRANSFORMING )
                        this.start_processing();
                },
                
                
                /* remove
                    remove file from upload queue
                */
                remove: function( file ) {
                    if ( this.queue[ file ] !== undefined ) {
                        var html = this.queue[ file ].html;
                        html.fadeOut( function() { html.remove(); } );
                        delete this.queue[ file ];
                    }
                },
                
                
                /* start_processing
                    start the transforming checks
                */
                start_processing: function() {
                    var files = this.files_processing();
                    if ( files.length == 0 ) return;
                    
                    // stop any transforming and set transforming
                    this.stop_processing();
                    this.IS_TRANSFORMING = true;
                    
                    // run the callback, if any
                    if ( ok( this.callback_start_processing ) )
                        this.callback_start_processing();
                    
                    // start delayed
                    var self = this;
                    this.interval = setTimeout( function() {
                        self.check_processing( files );
                    }, this.timeout );
                },
                
                
                /* check_processing
                    call a processing check.. file has been uploaded and instances are created
                */
                check_processing: function( files ) {
                    var self = this;
                    $.post( this.check_url, { 'files[]': files }, function( res ) {
                        
                        var finished = {};
                        
                        // work on successfully transformed (thumb implies all done)
                        if ( ok( res.thumbs ) ) {
                            for ( var s in res.thumbs ) {
                                finished[ s ] = true;
                                var queue_file = self.queue[ s ];
                                queue_file.status = 'done';
                                $.uploader_queue_item( {
                                    status: '<span style="color:green">done</span>',
                                    action_enable: true,
                                    img: res.thumbs[ s ],
                                    name: ok( res.names ) && ok( res.names[ s ] ) ? res.names[ s ] : null
                                }, queue_file.html );
                            }
                        }
                        
                        // for videos: converting status
                        if ( ok( res.status ) ) {
                            for ( var s in res.status ) {
                                if ( finished[ s ] === true ) continue;
                                var queue_file = self.queue[ s ];
                                queue_file.status = 'converting';
                                $.uploader_queue_item( {
                                    status: '<span style="text-decoration: blink">converting '+ res.status[ s ]+ '%</span>'
                                }, queue_file.html );
                            }
                        }
                        
                        // work on errorours
                        if ( ok( res.errors ) ) {
                            for ( var s in res.errors ) {
                                var queue_file = self.queue[ s ];
                                queue_file.status = 'error';
                                $.uploader_queue_item( {
                                    status: 'error',
                                    error: self.error
                                }, queue_file.html );
                            }
                        }
                        
                        // still not done:
                        var count_processing = self.files_processing().length;
                        if ( count_processing > 0 )
                            self.start_processing();
                        else self.stop_processing();
                    }, 'json' );
                },
                
                
                /* stop_processing
                    all transformings over, stop the checker
                */
                stop_processing: function() {
                    if ( this.interval !== null )
                        clearTimeout( this.interval );
                    this.IS_TRANSFORMING = false;
                    
                    // run the callback, if any
                    if ( ok( this.callback_finish_processing ) )
                        this.callback_finish_processing();
                },
                
                
                
                /* files_processing
                    get all files still transforming or converting
                */
                files_processing: function() {
                    var files = [];
                    for ( s in this.queue ) {
                        var status = this.queue[ s ].status;
                        if ( status == 'converting' || status == 'transforming' ) {
                            if ( !ok( this.check_count[ s ] ) )
                                this.check_count[ s ] = {}
                            if ( ! ok( this.check_count[ s ][ status ] ) ) 
                                this.check_count[ s ][ status ] = 1;
                            else
                                this.check_count[ s ][ status ] ++;
                            
                            if ( this.check_count[ s ][ status ] >= this.MAX_CHECKS ) {
                                this.queue[ s ].status = 'error';
                                $.uploader_queue_item( {
                                    status: 'error',
                                    error: this.error
                                }, this.queue[ s ].html );
                            }
                            else
                                files.push( s );
                        }
                    }
                    return files;
                }
            };
        },
        
        uploader_queue_item: function( args, item ) {
            if ( item === undefined || item == null )
                item = $( '<div class="queue">'+
                    '<div class="progress">'+
                    '</div>'+
                    '<div class="info">'+
                        '<span class="filename">Some file.jpg</span>'+
                        '<span class="status">uploading</span>'+
                        '<span class="error">Some error</span>'+
                        '<a href="#" class="action">delete</a>'+
                    '</div>'+
                '</div>' );
            
            // set all contents
            for ( s in args )
                item.find( '.'+ s ).html( args[ s ] );
            
            // having image ? set now
            if ( args.img !== undefined && args.img !== null ) {
                item.find( '.progress' ).empty().append( '<img width="40px" height="40px" src="'+ args.img+ '" />' );
                
                var name = ok( args.name )
                    ? args.name
                    : args.img.replace( /^.*\/(.*?)\-thumb.*?$/, function(a,b) { return b } )
                ;
                item.append( '<input type="hidden" class="uploaded_ok" name="data[uploaded][]" value="'+ name+ '" />' );
            }
            
            // or having progress ?
            else if ( args.progress_percent !== undefined && args.progress_percent !== null ) {
                var progress = item.find( '.progress' );
                var width = progress.width() * ( args.progress_percent / 100 );
                progress.empty().append( '<div class="progress_percent" style="width: '+ width+ 'px"></div>' ); 
            }
            
            // is done ? having action ..
            if ( args.action_enable === true ) {
                item.find( '.action' )
                    .css( 'display', 'block' )
                    .bind_only( 'remove_item', 'click', function() {
                        $( this ).parents( '.queue:first' ).fadeOut( function() { $( this ).remove() } );
                    } );
            }
            
            // having transformation error ?
            else if ( args.error !== undefined && args.error !== null && args.error != "" )
                item.find( '.error' ).css( 'display', 'block' );
            
            return item;
        }
    } );
    
    $.fn.extend( {
        
        
        /* init_uploader
            creates the flash uploader (swfupload) and links it to the upload button
        */
        init_uploader: function() {
            return $( this ).each( function() {
                var id = 'uploader_'+ ( new Date() ).getTime(),
                    form = $( this ).parents( 'form' ),
                    progress = $( this ).parents( 'form' ).find( '.uploader-progress' ),
                    text = $( this ).text();
                var upload_url = form.find( '.upload_url' ).val(),
                    check_url = form.find( '.check_url' ).val(),
                    media_type = form.find( '.media_type' ).val();
                
                $( this ).find( '.flash' ).append( '<span id="'+ id+ '"></span>' );
                
                var swfUpload;
                
                // create a new upload handler
                var uploadHandler = $.create_uploader_handler( swfUpload, progress, check_url );
                
                // stop the upload handler and all it calls on window closing
                $( window ).bind_only( 'uploader', 'fancybox_closed', function() {
                    uploadHandler.stop_processing();
                } );
                
                // handle while uploading/transforming and afterwards
                var submit = form.find( '*[type=submit]' );
                submit.attr( 'disabled', true ).css( { opacity: 0.5 } );
                
                uploadHandler.callback_start_processing = function() {
                    submit.attr( 'disabled', true ).css( { opacity: 0.5 } );
                };
                uploadHandler.callback_finish_processing = function() {
                    var count_ok = form.find( '.uploaded_ok' ).length;
                    if ( count_ok > 0 )
                        submit.attr( 'disabled', false ).css( { opacity: 1.0 } );
                };
                if ( media_type == 'video' )
                    uploadHandler.timeout = 5000;
                
                var file_dialog = SWFUpload.BUTTON_ACTION.SELECT_FILES;
                if ( form.find( 'input[name=upload_portrait]' ).length > 0 )
                    file_dialog = SWFUpload.BUTTON_ACTION.SELECT_FILE;
                
                var queue_ids = [];
                
                // generate the swf uploader
                swfUpload = new SWFUpload( {
                    
                    button_action: file_dialog,
                    
                    // urls
                    upload_url: upload_url,
                    flash_url: '/swf/swfupload.swf',
                    
                    // button
                    button_placeholder_id: id,
                    /* button_text: '<span class="button">'+ text+ '</span>',
                    button_text_style: '.button { text-align: center; font-size: 12px; font-family: Arial; color: #FFFFFF }',
                    button_image_url: '/img/highlight-red.gif', */
                    button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
                    button_width: 345,
                    button_height: 14,
                    
                    debug: false,
                    
                    // upload restrictions:
                    file_size_limit: "24 MB",
                    file_types: media_type == 'image'
                        ? "*.jpg;*.jpeg;*.gif;*.png"
                        : "*.mpg;*.mpeg;*.avi;*.mov;*.flv;*.mp4;*.mkv;*.avi;*.wmv;*.m4v;*.3gp"
                    ,
                    file_types_description: media_type == 'image' ? 'Image Files' : 'Video Files',
                    file_upload_limit: 99,
                    file_queue_limit: 0,
                    
                    // handler
                    file_dialog_start_handler: function() {
                        if ( file_dialog == SWFUpload.BUTTON_ACTION.SELECT_FILE ) {
                            for ( var i = 0; i< queue_ids.length; i++ )
                                swfUpload.cancelUpload( queue_ids[i] );
                            queue_ids = [];
                            progress.empty();
                        }
                    },
                    file_queued_handler: function( data ) {
                        uploadHandler.add( data.name );
                    },
                    file_queue_error_handler: handler( 'fileQueueError' ),
                    file_dialog_complete_handler: function() {
                        try {
                            if ( this.getStats().files_queued > 0 )
                                swfUpload.startUpload();
                        }
                        catch(e) {}
                    },
                    upload_start_handler: function( data ) {
                        queue_ids.push( data.id );
                        uploadHandler.start( data.name );
                    },
                    upload_progress_handler: function( data, count, max ) {
                        uploadHandler.progress( data.name, ( count * 100 ) / max );
                    },
                    upload_error_handler: handler( 'uploadError' ),
                    upload_success_handler: function( data ) {
                        uploadHandler.success( data.name );
                    },
                    upload_complete_handler: function( data ) {
                        try {
                            if ( this.getStats().files_queued > 0 )
                                swfUpload.startUpload();
                        }
                        catch(e) {}
                    }
                    
                } );
            } );
        },
        
        
        /* init_bbcode
            setups the bbcode edit window
        */
         
        init_bbcode: function() {
            return $( this ).each( function() {
                function rr(x) { return x.replace( /([\*\\\/\.\?\(\)])/g, function(a,b) { return "\\"+ b } ) } 
                $( '.bbcode', this ).each( function() {
                    var actions = $( '.action', this ), text = $( 'textarea', this );
                    var ttext = text.get(0);
                    actions.click( function() {
                        
                        // get the text and selection range
                        var v = text.val(), vl = text.val().length;
                        var s = document.selection !== undefined
                            ? document.selection.createRange().text
                            : v.substring( ttext.selectionStart, ttext.selectionEnd )
                        ;
                        
                        // determine mode
                        var mode = $( this ).attr( 'rel' );
                        
                        // link prompt
                        if ( mode.match( /\blink=(.+?)$/ ) ) {
                            var u = prompt( RegExp.$1 );
                            if ( u !== null && u != "" )
                                s = "["+ s+ "]("+ u+ ")";
                        }
                        
                        // wrappigg
                        else if ( mode.match( /\bwrap=(.+?)$/ ) ) {
                            var w = RegExp.$1, t = new RegExp( rr(w)+ "\(.\*\?\)"+ rr(w) ), ts = new RegExp( "^"+ rr(w)+ "\(.\*\?\)"+ rr(w)+ "$" );
                            
                            // unwrap it
                            if ( ts.exec( s ) !== null )
                                var l = s.length, s = s.replace( ts, function(a,b){ return b } );
                            
                            // wrap it
                            else {
                                // found "within", replace it (double not required)
                                if ( t.exec( s ) !== null )
                                    var l = s.length, s = s.replace( t, function(a,b){ return b } );
                                s = w+ s+ w;
                            }
                        }
                        
                        // line prefix
                        else if ( mode.match( /\blineprefix=(.*?)$/ ) ) {
                            var w = RegExp.$1, t = new RegExp( "\^"+ rr( w ) );
                            var x = s.split( /(?:\r\n|\n|\r)/ );
                            for ( var i = 0; i< x.length; i++ )
                                if ( x[i].length > 0 && x[i].match( /\S/ ) )
                                    x[i] = "\n"+ w+ x[i].replace( t, '' );
                            s = x.join( "" ) + "\n";
                        }
                        
                        var scroll = ttext.scrollTop;
                        
                        if ( document.selection !== undefined ) {
                            var range = document.selection.createRange();
                            range.text = s;
                        }
                        else {
                            var ss = ttext.selectionStart, se = ttext.selectionEnd;
                            var p = text.val().substring( 0, ss ),
                                a = text.val().substring( se, vl )
                            ;
                            text.val( p+ s+ a );
                            ttext.select();
                            ttext.selectionStart = ss;
                            ttext.selectionEnd = ss + s.length;
                        }
                        
                        ttext.scrollTop = scroll;
                        
                        return  false;
                    } );
                } );
            } );
        },
        
        
        
        
        /* init_associated_selects
            two selects with a left <-> right shifting
        */
        init_associated_selects: function() {
            return $( this ).each( function() {
                $( this ).find( '.associated-selects' ).each( function() {
                    var sl = $( '.select-left select', this ), sr = $( '.select-right select', this );
                    $( '.move-left', this ).click( function() {
                        sr.find( 'option:selected' ).appendTo( sl );
                        return false;
                    } );
                    $( '.move-right', this ).click( function() {
                        sl.find( 'option:selected' ).appendTo( sr );
                        return false;
                    } );
                        
                } );
            } );
        },
        
        
        
        
        /* init_comment_remove
            link the comment remove buttons with purpose
        */
        init_comment_remove: function() {
            $( '.remove-comment', this ).bind_only( 'remove_comment', 'click', function() {
                var p = $( this ).parents( '.comment:first' );
                if ( p.parents( '.c:first' ).length > 0 ) p = p.parents( '.c:first' );
                p.animate( { opacity: '0.5' } );
                $.post( $( this ).attr( 'href' ), {}, function() {
                    p.slideUp( function() { p.remove(); } );
                } );
                return false;
            } );
        },
        
        
        /* init_edit_form
            init all edit functions on a formular
                * sortables
                * uploader
                * bbcode
        */
        init_edit_form: function() {
            return $( this ).each( function() {
                var form = $( this );
                form.find( '.sortable-list' ).each( function() {
                    var $list = $( this );
                    $list
                        // make sortable
                        .sortable()
                    
                        // on delete -> move to end of list an fade out
                        .find( '.sortitem' ).each( function() {
                            var $item = $( this );
                            var $checkbox = $item.find( '.delete input[type=checkbox]' );
                            var on_change = function() {
                                if ( ! $checkbox.attr( 'checked' ) )
                                    $item.animate( { opacity: 1.0 } );
                                else
                                    $list.append( $item.animate( { opacity: 0.5 } ) );
                            };
                            
                            // bind the checkbxo .. regular
                            $checkbox.bind_only( 'check_delete', 'change', on_change );
                            
                            // for iex
                            $item.find( '.delete' ).bind_only( 'click_delete', 'click', function() {
                                setTimeout( on_change, 100 );
                            } );
                        } );
                } );
                
                form.find( '#media_edit' ).click( function() {
                    var url = '/media/edit/'+ form.find( '#media_id' ).val();
                    $.open_fancybox( url );
                    return false;
                } );
                
                var toggle = function() {
                    var selects = $( this ).parents( '.date' ).find( 'select' );
                    selects.attr( 'disabled', $( '#ProfileNoBirthday' ).attr( 'checked' ) ? 'disabled' : '' );
                };
                $( '#ProfileNoBirthday' ).click( toggle ).change( toggle );
                
                
                form.find( '.uploader' ).init_uploader();
                form.init_bbcode();
                form.init_associated_selects();
            } );
        }
    } );
    
} );
