var current_toolbar;
var current_iframe;
var renew_defer_active;
var last_succesfull_renew;
var block_info = {};
var toolbar_save_query;
var toolbar_cancel_query;
var toolbar_original;
var sh_switch_open_actions = new Array();

var wiki_rpc = new dojo.rpc.JsonService( { smdObj : {
    "serviceType": "JSON-RPC", 
    "serviceURL": "/wiki_json/" + DicoleTargetId + "/", 
    "methods":[ 
        {
            "name": "start_editing",
            "parameters":[ {"name": "named_params"} ]
        },
        {
            "name": "page_content",
            "parameters":[ {"name": "named_params"} ]
        },
        {
            "name": "renew_lock",
            "parameters":[ {"name": "named_params"} ]
        }
    ]
} } );

window.onbeforeunload = function() {
    if ( document.forms[0].edit_lock.value && ! document.forms[0].cancel.value == 1 &&
            ! document.forms[0].save.value == 1 ) {
        return content_data['strings']['warning'];
    }
}

function wiki_init() {
    var changed = _assign_restrictions_to_blocks( content_data.locks )
    _set_buttons_and_locks( changed );
}

function _assign_restrictions_to_blocks( locks, changes ) {

    var modified_blocks = {};

    for (var block_id in content_data.blocks) {

        if ( ! block_info[block_id] ) {
            block_info[block_id] = {
                content_locked : 0,
                block_locked : 0
            };
            modified_blocks[block_id] = 1;
        }

        // lock is never removed
        if ( block_info[block_id]['content_locked'] > 0 ) continue;

        var block = content_data.blocks[block_id];

        if ( !locks ) locks = [];
        for (var lock in locks) {
            lock = locks[lock];
            var ordered = (block.position < lock.position) ?
                [block,lock] : [lock,block];
            if ( ordered[0].position + ordered[0].size >
                    ordered[1].position ) {
                if ( lock.user_id == content_data.user_id &&
                        ordered[0].position == ordered[1].position ) {
                    if ( ordered[0].size == ordered[1].size ) {
                        block_info[block_id]['content_locked'] = 2;
                    }
                    else {
                        block_info[block_id]['content_locked'] = 3;
                    }
                }
                else {
                    if ( ordered[0].position == ordered[1].position ) {
                        block_info[block_id]['content_locked'] = 1;
                    }
                    else {
                        block_info[block_id]['content_locked'] = 4;
                    }
                }
                block_info[block_id]['lock_info'] = lock.message;
                modified_blocks[block_id] = 1;
                break;
            }
        }

        if ( block_info[block_id]['content_locked'] > 0 ) continue;

        if ( !changes ) changes = [];
        for (var change in changes) {
            change = changes[change];
            var ordered = (block.position < change.position) ?
                [block,change] : [change,block];
            if ( ordered[0].position + ordered[0].size >
                    ordered[1].position ) {
                block_info[block_id]['content_locked'] = 1;
                block_info[block_id]['lock_info'] = change.message;
                modified_blocks[block_id] = 1;
                break;
            }
        }
    }

    for (var block_id in content_data.blocks) {
        // lock is never removed
        if ( block_info[block_id]['block_locked'] > 0 ) continue;

        var blocked = 0;

        var block = content_data.blocks[block_id];
        if ( block.children.length > 1 ) {
            for (var c = 0; c < block.children.length; c++) {
                if ( block_info[block.children[c]]['content_locked'] > 0 ) {
                    blocked = 1;
                    break;
                }
            }
        }
        else {
            blocked = 1;
        }

        if ( blocked ) {
            block_info[block_id]['block_locked'] = 1;
            modified_blocks[block_id] = 1;
        }
    }

    var modified = [];
    for ( var block_id in modified_blocks ) modified.push( block_id );

    return modified;
}

function _set_buttons_and_locks( containers ) {

    for (var i = 0; i < containers.length; i++) {
        var id = containers[i];
        var elem = dojo.byId('wiki_content_' + id );

        if (!elem) continue;

        _empty_wiki_controls( id );

        if ( block_info[id]['content_locked'] > 0 ) {
            dojo.html.addClass( elem, 'wiki_content_locked' );
        }

        if ( block_info[id]['content_locked'] == 1 ) {
            _add_edit_info( id, block_info[id]['lock_info'] );
        }
        else if ( block_info[id]['content_locked'] == 2 ) {
            _add_edit_button( elem, id, 'content', 'own', block_info[id]['lock_info'] );
        }
        else if ( block_info[id]['content_locked'] == 3 ) {
            _add_edit_button( elem, id, 'block', 'own', block_info[id]['lock_info']);
        }
        else if ( block_info[id]['content_locked'] == 0 ) {
            _add_edit_button( elem, id, 'content' );

            if ( block_info[id]['block_locked'] == 0 ) {
                _add_wiki_controls( id, document.createTextNode(' | ') );
                _add_edit_button( elem, id, 'block' );
            }
        }
    }

    var toc_header = dojo.byId('toc_header');
    var toc_block = dojo.byId('toc_block');
    if ( toc_header && toc_block ) {
        var plus = document.createElement('a');
        plus.innerHTML = '[' + content_data.strings['show'] + ']';
        plus.setAttribute('href', '#');
        dojo.html.addClass( plus, 'sh_switch_open' );
        dojo.html.addClass( plus, 'sh_switch_open_toc' );

        var minus = document.createElement('a');
        minus.innerHTML = '[' + content_data.strings['hide'] + ']';
        minus.setAttribute('href', '#');
        dojo.html.addClass( minus, 'sh_switch_close' );
        dojo.html.addClass( minus, 'sh_switch_close_toc' );

        dojo.html.addClass( toc_block, 'sh_switch_block' );
        dojo.html.addClass( toc_block, 'sh_switch_block_toc' );

        dojo.dom.insertAtPosition(plus, toc_header, 'last');
        dojo.dom.insertAtPosition(minus, toc_header, 'last');
    }

    _process_sh_switches();

    sh_switch_open_actions.push( function( alink ) {
        if ( dojo.html.hasClass( alink, 'wiki_content_fetcher' ) ) {
            dojo.html.removeClass( alink, 'wiki_content_fetcher' );

            var classes = dojo.html.getClass( alink );
            var parts = classes.match(/wiki_content_fetcher_(\d+)_(\d+)/);
            if ( ! parts || ! parts[1] || ! parts[2] ) return true;

            var hlinks = dojo.html.getElementsByClass(
                'wiki_header_link_' + parts[2]
            );
            if ( ! hlinks || ! hlinks[0] || ! hlinks[0].title ) return true;

            var defer = wiki_rpc.page_content( {
                raw_title : hlinks[0].title,
                header_base : parts[1]
            } );

            var id = parts[2];
            defer.addCallback( function(data) {
                if ( data && data.content ) {
                    var blocks = dojo.html.getElementsByClass(
                        'sh_switch_block_' + id
                    );
                    if ( blocks && blocks[0] ) {
                        blocks[0].innerHTML = data.content;
                    }
                }
            } );
        }
        return true;
    } );
}

function _process_sh_switches() {
    var plusses = dojo.html.getElementsByClass('sh_switch_open');
    var minuses = dojo.html.getElementsByClass('sh_switch_close');

    var ids = {};

    for ( var i in plusses ) {
        var plus = plusses[i];
        var classes = dojo.html.getClasses(plus);
        for ( var j in classes ) {
            var clss = classes[j];
            var parts = clss.match(/^sw_switch_open_(.+)$/);
            if ( parts ) ids[ parts[1] ]++;
        }
    }

    for ( var i in minuses ) {
        var minus = minuses[i];
        var classes = dojo.html.getClasses(minus);
        for ( var j in classes ) {
            var clss = classes[j];
            var parts = clss.match(/^sh_switch_close_(.+)$/);
            if ( parts ) ids[ parts[1] ]++;
        }
    }

    for ( var id in ids ) {
        var id_plusses = dojo.html.getElementsByClass('sh_switch_open_'+id );
        var id_minuses = dojo.html.getElementsByClass('sh_switch_close_'+id );
        var id_blocks = dojo.html.getElementsByClass('sh_switch_block_'+id );

        var open_found = false;
        var closed_found = false;

        for ( var i in id_blocks ) {
            if ( dojo.html.hasClass( id_blocks[i], 'hiddenBlock') )
                closed_found = true;
            else
                open_found = true;
        }

        if ( closed_found && open_found ) {
            _sh_switch_set_visibility( id_blocks, 0 );
            _sh_switch_set_visibility( id_plusses, 1 );
            _sh_switch_set_visibility( id_minuses, 0 );
        }
        else if ( closed_found ) {
            _sh_switch_set_visibility( id_plusses, 1 );
            _sh_switch_set_visibility( id_minuses, 0 );
        }
        else if ( open_found ) {
            _sh_switch_set_visibility( id_plusses, 0 );
            _sh_switch_set_visibility( id_minuses, 1 );
        }
        else continue;

        for ( var i in id_plusses ) {
            _sh_switch_connect_toggle(
                id_plusses[i], id_plusses,
                id_minuses, id_blocks, 1
            );
        }
        for ( var i in id_minuses ) {
            _sh_switch_connect_toggle(
                id_minuses[i], id_plusses,
                id_minuses, id_blocks, 0
            );
        }
    }
}

function _sh_switch_connect_toggle( node, plusses, minuses, blocks, if_show) {
    dojo.event.connect( node, 'onclick', function(e) {
        e.preventDefault();
        if ( if_show ) {
            _sh_switch_set_visibility( blocks, 1 );
            _sh_switch_set_visibility( plusses, 0 );
            _sh_switch_set_visibility( minuses, 1 );

            for (var i in sh_switch_open_actions) {
                var cont = sh_switch_open_actions[i]( node );
                if ( ! cont ) break;
            }
        }
        else {
            _sh_switch_set_visibility( blocks, 0 );
            _sh_switch_set_visibility( plusses, 1 );
            _sh_switch_set_visibility( minuses, 0 );
        }
    } );
}

function _sh_switch_set_visibility( elements, if_show ) {
    if ( if_show ) {
        for ( var i in elements ) {
            if ( dojo.html.hasClass( elements[i], 'hiddenBlock') ) {
                dojo.html.removeClass( elements[i], 'hiddenBlock' );
            }
        }
    }
    else {
        for ( var i in elements ) {
            if ( ! dojo.html.hasClass( elements[i], 'hiddenBlock') ) {
                dojo.html.addClass( elements[i], 'hiddenBlock' );
            }
        }
    }
}
function _hide_sh_switches() {
    var plusses = dojo.html.getElementsByClass('sh_switch_open');
    var minuses = dojo.html.getElementsByClass('sh_switch_close');
    _sh_switch_set_visibility( plusses, 0 );
    _sh_switch_set_visibility( minuses, 0 );
}

function _add_edit_button( elem, id, type, own, info ) {
    var target_element = (type == 'block') ?
        elem.parentNode : elem;

    var alink = document.createElement('a');
    if ( own ) {
        alink.innerHTML = content_data.strings['Resume edit'];
    }
    else if ( id != 1 ) {
        alink.innerHTML = content_data.strings['Edit ' + type];
    }
    else {
        alink.innerHTML = ( type == 'block' ) ?
            content_data.strings['Edit whole'] :
            content_data.strings['Edit begin'];
    }
    dojo.html.addClass( alink, 'wiki_edit_button' );
//     dojo.html.addClass( alink, 'linkButton' );
    alink.setAttribute('href', '#');
    dojo.event.connect(alink, "onclick", function(e) {
        e.preventDefault();
        return _start_edit( target_element, id, type );
    });
    dojo.event.connect(alink, "onmouseover", function() {
        return _wiki_highlight( target_element );
    });
    dojo.event.connect(alink, "onmouseout", function() {
        return _wiki_dehighlight( target_element );
    });

    _add_wiki_controls( id, alink );

    if ( own ) {
        _add_wiki_controls( id, document.createTextNode(' | ') );

        var span = document.createElement('span');
        span.innerHTML = info;
        dojo.html.setClass( span, 'wiki_edit_info' );
        _add_wiki_controls( id, span );
    }
}

function _add_edit_info( id, message ) {
    var span = document.createElement('span');
    span.innerHTML = message;
    dojo.html.setClass( span, 'wiki_edit_info' );

    _add_wiki_controls( id, span );
}

function _start_edit( elem, id, type ) {

    _wiki_dehighlight( elem );

    _set_edit_values(id, type);
    _hide_wiki_controls();
    _hide_sh_switches();
    _gray_backgrounds_except( elem.id );

    _empty_wiki_controls( id );
    _add_edit_info( id, content_data.strings['Reserving lock..'] );
    _show_wiki_controls( id );

    var defer = wiki_rpc.start_editing( page_params );
    defer.addCallback( function(data) {
        _handle_start_response( data, elem, id, type );
    } );

    return false;
}

function _handle_start_response(data, elem, id, type) {
    if ( data && data.lock_granted == 1 ) {
        _remove_wiki_controls();

        elem.innerHTML = data.content;

        document.forms[0].edit_lock.value = data.lock_id;

        tinyMCE.execCommand('mceAddControl', false, elem.id);

        _create_space_for_toolbar();
        _lock_renew_loop();

        _delayed_document_actions();
    }
    else if ( data && data.lock_granted == 0 ) {
        var changed = _assign_restrictions_to_blocks(
            data.locks, data.changes
        );
        _set_buttons_and_locks( changed );
        _show_wiki_controls();
        _ungray_backgrounds_except( elem.id );
    }
    else {
        alert( 'Something unexpected happened. Please reload page.' );
    }
}

function _delayed_document_actions() {
        try {
            tinyMCE.selectedInstance.getDoc();
        }
        catch(e) {
            dojo.lang.setTimeout( function() {_delayed_document_actions();}, 50);
            return;
        }

        _resize_editor_loop();
        _position_toolbar_loop();

        // We don't want auto_resize to make conflicting resize
        // operations but we need the plugin to disable scrolling
        // on the iframe on IE since there it can't be done
        // afterwards.

        tinyMCE.settings['auto_resize'] = false;
}

function _lock_renew_loop() {
    var now = new Date();
    var renew_timeout = 15000;

    if ( ! last_succesfull_renew ||
         last_succesfull_renew + renew_timeout < now.valueOf() ) {

        if ( ! renew_defer_active ) {

            renew_defer_active = true;

            var defer = wiki_rpc.renew_lock( {
                lock_id : document.forms[0].edit_lock.value,
                autosave_content : tinyMCE.getContent()
            } );

            defer.addCallback( function(data) {
                if (data && data.renew_succesfull ) {
                    var d = new Date();
                    last_succesfull_renew = d.valueOf();
                }
                else {
                    // TODO: Handle failure ?
                }

                renew_defer_active = false;
            } );

            defer.addErrback( function(data) {
                // TODO: Handle failure ?
                renew_defer_active = false;
            } );
        }
    }

    dojo.lang.setTimeout( function() {_lock_renew_loop();}, 1000);
}

function _gray_backgrounds_except( id ) {
    var elems = dojo.html.getElementsByClass('wiki_content_container');
    for (var i = 0; i < elems.length; i++) {
        if ( elems[i].id == id ) continue;
        dojo.html.addClass(elems[i], 'wiki_content_grayed');
    }
}

function _ungray_backgrounds_except( id ) {
    var elems = dojo.html.getElementsByClass('wiki_content_container');
    for (var i = 0; i < elems.length; i++) {
        if ( elems[i].id == id ) continue;
        dojo.html.removeClass(elems[i], 'wiki_content_grayed');
    }
}

function _create_space_for_toolbar() {
    var toolbar = dojo.byId('mce_editor_0_toolbar');
    var height = dojo.html.getBorderBoxHeight(toolbar);
    var div = document.createElement('div');
    div.style.height = 4 + height + 'px';
    var parent = dojo.byId('mce_editor_0_parent');
    parent.insertBefore(div, parent.childNodes[0]);
}

function _resize_editor_loop() {
/**
    inst.iframeElement.style.height = '300px';

    var dech = doc.documentElement ? doc.documentElement.clientHeight : '';
    var desh = doc.documentElement ? doc.documentElement.scrollHeight : '';

    alert(
        "; body.offsetHeight " + doc.body.offsetHeight + 
        "; body.scrollHeight " + doc.body.scrollHeight + 
        "; body.clientHeight " + doc.body.clientHeight +
        "; documentElement.clientHeight " + dech +
        "; documentElement.scrollHeight " + desh
    );
**/
    _resize_editor();
    dojo.lang.setTimeout( function() {_resize_editor_loop();}, 200);
}

function _resize_editor() {

    var inst = tinyMCE.selectedInstance;
    var doc = inst.getDoc();

    if ( doc.body.scrollTop + doc.documentElement.scrollTop > 0 ) {
        var scrollX = doc.body.scrollLeft + doc.documentElement.scrollLeft;
        inst.contentWindow.scrollTo( scrollX, 0 );
    }

    if ( ! current_iframe ) {
        current_iframe = new Object();
        current_iframe['height'] = 0;
    }

    var wanted_height = doc.body.scrollHeight;
    if ( doc.documentElement ) {
        var de = doc.documentElement;
        if ( de.scrollHeight && de.clientHeight == de.scrollHeight ) {
            wanted_height = de.scrollHeight;
        }
    }

    wanted_height = wanted_height + 1;
    var diff = current_iframe['height'] - wanted_height;
    if ( diff > 2 || diff < -2 ) {
        inst.iframeElement.style.height = wanted_height + 'px';
        current_iframe['height'] = wanted_height;
    }
}

function _position_toolbar_loop() {
    _position_toolbar( false );
    dojo.lang.setTimeout( function() {_position_toolbar_loop();}, 200);
}

function _position_toolbar( recalculate ) {
    if ( ! current_toolbar || recalculate ) {
        current_toolbar = new Object();
        var toolbar = dojo.byId('mce_editor_0_toolbar');
        current_toolbar['element'] = toolbar;
        _calculate_info( current_toolbar);

        toolbar.style.width = current_toolbar['optimal_width'] + 'px';
    }

    var intended_top;
    var intended_left;

    if ( dojo.html.getScrollTop() > current_toolbar['optimal_top'] ) {
        intended_top = dojo.html.getScrollTop();
    }
    else {
        intended_top = current_toolbar['optimal_top'];
    }

    if ( dojo.html.getScrollLeft() > current_toolbar['optimal_left'] ) {
        intended_left = dojo.html.getScrollLeft();
    }
    else {
        intended_left = current_toolbar['optimal_left'];
    }

    if (intended_top != current_toolbar['top']) {
        current_toolbar['top'] = intended_top;
        current_toolbar['element'].style.top = intended_top + 'px'
    }

    if (intended_left != current_toolbar['left']) {
        current_toolbar['left'] = intended_left;
        current_toolbar['element'].style.left = intended_left + 'px'
    }
}

function _calculate_info( object ) {
    var iframe = tinyMCE.selectedInstance.iframeElement;
    var element = object['element'];
    object['height'] = dojo.html.getBorderBoxHeight(element);
    object['width'] = dojo.html.getBorderBoxWidth(element);
    object['top'] = dojo.html.totalOffsetTop(element, true);
    object['left'] = dojo.html.totalOffsetLeft(element, true);
    object['optimal_top'] = dojo.html.totalOffsetTop( iframe, true) - 
        dojo.html.getBorderBoxHeight(element) - 2;
    object['optimal_left'] = dojo.html.totalOffsetLeft(
        iframe, true) - 1;
    object['optimal_width'] = dojo.html.getBorderBoxWidth(iframe);

}

function _set_edit_values(edit_id, edit_type) {
    document.forms[0].edit_target_id.value = edit_id;
    document.forms[0].edit_target_type.value = edit_type;
    page_params.edit_target_id = edit_id;
    page_params.edit_target_type = edit_type;
}

// not used anymore?
function _get_original_html_from_block( elem ) {
    var elems = dojo.html.getElementsByClass('wiki_content_container', elem);
    var html = '';
    for (var i = 0; i < elems.length; i++) {
        // Dojo does not work.. IT does not return only
        // Elements below elem :( So we do this:
        if (dojo.html.isDescendantOf(elems[i], elem) ) {
            html = html + elems[i].innerHTML;
        }
    }
    return html;
}

function _remove_wiki_controls() {
    var elems = dojo.html.getElementsByClass('wiki_controls');
    for (var i = 0; i < elems.length; i++) {
        elems[i].parentNode.removeChild(elems[i]);
    }
}

function _empty_wiki_controls( id ) {
    var controls = dojo.byId( 'wiki_controls_' + id );
    controls.innerHTML= '';
}

function _add_wiki_controls( id, elem ) {
    var controls = dojo.byId( 'wiki_controls_' + id );
    dojo.dom.insertAtPosition(elem, controls, 'first');
}

function _hide_wiki_controls( id ) {
    var elems = id ? [ dojo.byId( 'wiki_controls_' + id ) ] :
        dojo.html.getElementsByClass('wiki_controls');
    for (var i = 0; i < elems.length; i++) {
        dojo.html.addClass(elems[i], 'hidden_wiki_controls' );
    }
}

function _show_wiki_controls( id ) {
    var elems = id ? [ dojo.byId( 'wiki_controls_' + id ) ] :
        dojo.html.getElementsByClass('wiki_controls');
    for (var i = 0; i < elems.length; i++) {
        dojo.html.removeClass(elems[i], 'hidden_wiki_controls' );
    }
}

function _wiki_highlight( elem ) {
    dojo.html.addClass(elem, 'wiki_content_highlight');
}

function _wiki_dehighlight( elem ) {
    dojo.html.removeClass(elem, 'wiki_content_highlight');
}

function _cancel_wiki_edit() {
    toolbar = dojo.byId('mce_editor_0_toolbar');

    if ( ! toolbar_cancel_query ) {
        _init_toolbar_queries_and_original(toolbar);
    }

    dojo.html.removeClass( toolbar_cancel_query, 'hiddenBlock' );

    for (i in toolbar_original ) {
        if ( toolbar_original[i] ) {
            dojo.html.addClass( toolbar_original[i], 'hiddenBlock' );
        }
    }
}

function _save_wiki_edit() {

    toolbar = dojo.byId('mce_editor_0_toolbar');

    if ( ! toolbar_save_query ) {
        _init_toolbar_queries_and_original(toolbar);
    }

    dojo.html.removeClass( toolbar_save_query, 'hiddenBlock' );

    for (i in toolbar_original ) {
        if ( toolbar_original[i] ) {
            dojo.html.addClass( toolbar_original[i], 'hiddenBlock' );
        }
    }
}

function _init_toolbar_queries_and_original(toolbar) {

    // copy just current children
    toolbar_original = [];
    var cn = toolbar.childNodes;
    for (i in cn) toolbar_original.push( cn[i] );

    toolbar_save_query = dojo.byId('toolbar_comment_query');
    dojo.dom.insertAtPosition(toolbar_save_query, toolbar, 'first');

    toolbar_cancel_query = dojo.byId('toolbar_cancel_query');
    dojo.dom.insertAtPosition(toolbar_cancel_query, toolbar, 'first');

    var confirm = dojo.byId('confirm_save');
    dojo.event.connect( confirm, 'onclick', function(e) {
        e.preventDefault();
        var desc = dojo.byId('edit_description').value;
        document.forms[0].change_description.value = desc;
        var minor = dojo.byId('edit_minor').checked;
        if ( minor ) document.forms[0].change_minor.value = 1;

        document.forms[0].base_version_number.value = 
            page_params.base_version_number 
        document.forms[0].edit_content.value = tinyMCE.getContent();
        document.forms[0].save.value = 1;
        document.forms[0].submit();
    } );

    var cancel_accept = dojo.byId('cancel_accept');
    dojo.event.connect( cancel_accept, 'onclick', function(e) {
        e.preventDefault();
        document.forms[0].cancel.value = 1;
        document.forms[0].submit();
    } );

    var cancel = dojo.byId('confirm_cancel');
    dojo.event.connect( cancel, 'onclick', function(e) {
        e.preventDefault();

        dojo.html.addClass( toolbar_save_query, 'hiddenBlock' );

        for (i in toolbar_original ) {
            if ( toolbar_original[i] ) {
                dojo.html.removeClass(
                    toolbar_original[i], 'hiddenBlock'
                );
            }
        }
    } );

    var cancel_back = dojo.byId('cancel_back');
    dojo.event.connect( cancel_back, 'onclick', function(e) {
        e.preventDefault();

        dojo.html.addClass( toolbar_cancel_query, 'hiddenBlock' );

        for (i in toolbar_original ) {
            if ( toolbar_original[i] ) {
                dojo.html.removeClass(
                    toolbar_original[i], 'hiddenBlock'
                );
            }
        }
    } );
}
