function MarkupToolbox(doc, mode, art_id) {
    var oThis = this;

    this.doc = doc;
    this.artId = art_id;

    this.config = { configFile: '/article-markup.xml',
                    extractedEntities: '/ArticlesHandler.ashx',
                    dockIcon: '/images/markup/dock_button.gif',
                    undockIcon: '/images/markup/undock_button.gif',
                    minusIcon: '/images/markup/minus.gif',
                    plusIcon: '/images/markup/plus.gif',
                    pointIcon: '/images/markup/point.gif',
                    closeIcon: '/images/markup/close_button.gif',
                    settingsIcon: '/images/markup/settings_button.gif',
                    maximizeIcon: '/images/markup/maximize_button.gif',
                    minimizeIcon: '/images/markup/minimize_button.gif',
                    showAllIcon: '/images/markup/opened_eye.jpg',
                    hideAllIcon: '/images/markup/closed_eye.jpg',
                    editPropsIcon: '/images/markup/edit_props.gif',
                    printIcon: '/images/markup/print.gif' }

    this.toolboxMenu = null;    //  Main top DIV
    this.toolboxTitle = null;
    this.toolboxContent = null;
    this.titleButtons = null;
    this.settingsButton = null;
    this.minimizeButton = null;
    this.maximizeButton = null;
    this.autoHideButton = null;

  	this.visible = false;

  	this.mode = mode;
    if( !$.browser.msie ) {
        this.mode = 'eViewMode';
    }

    this.viewMode = this.mode == 'eViewMode';
    this.editMode = this.mode == 'eEditMode';

    this.offsetTop = $.cookie('tb_offset_top') == null ? 20 : parseInt($.cookie('tb_offset_top'));
    this.offsetLeft = $.cookie('tb_offset_left') == null ? null : parseInt($.cookie('tb_offset_left'));

    this.xmlConfig = null;
    this.xmlEntities = null;

    $.get(this.config.configFile, {}, function(xml) {
        oThis.createMenu(xml);
    });

    this.showAll = true;
}

MarkupToolbox.prototype.isDocked = function () {
    if( $.cookie('toolbox_docked') == null )
        return true;

    return $.cookie('toolbox_docked') == '1'
}

MarkupToolbox.prototype.createMenu = function (xml) {
    var oThis = this;

    this.xmlConfig = xml;

	this.toolboxMenu = $('<div/>')
	                    .addClass('csm-toolbox')
	                    .attr('id', 'toolbar')
						.appendTo('body');

    this.toolboxMenu.css('top', this.offsetTop);
    if(this.offsetLeft != null) this.toolboxMenu.css('left', this.offsetLeft);

    this.generateTitle();
    this.generateContent();

    if( this.isDocked() ) {
    	this.visible = true;
    }
    else {
    	this.toolboxMenu.animate({"opacity": 0.2}, "fast");
    	this.visible = false;
    }

	var overTimeout = 0;
	var outTimeout = 0;
	this.toolboxMenu.mouseover(function() {
        if( !oThis.isDocked() ) {
    		window.clearTimeout(outTimeout);
	    	overTimeout = window.setTimeout(function() {
	    	    if(!oThis.visible) { 
    	            oThis.visible = true;
	    	        oThis.toolboxMenu.animate({"opacity": 1}, "fast");
	    	    } 
	    	}, 10);
    	}
	});
	this.toolboxMenu.mouseout(function() {
        if( !oThis.isDocked() ) {
		    window.clearTimeout(overTimeout);
	    	outTimeout = window.setTimeout(function() {
	    	    if(oThis.visible) { 
    	            oThis.visible = false;
	        	    oThis.toolboxMenu.animate({"opacity": 0.2}, "fast"); 
	        	}
	    	}, 100);
		}
	});

    this.toolboxMenu.draggable({    handle: this.toolboxTitle,
                                    stop: function() {
                                        oThis.offsetTop = oThis.toolboxMenu.offset().top - document.documentElement.scrollTop;
                                        $.cookie('tb_offset_top', oThis.offsetTop, { expires: 365 });
                                        $.cookie('tb_offset_left', oThis.toolboxMenu.offset().left, { expires: 365 });
                                    }
                                });

    $(window).scroll(function() {
        oThis.scrollToolbox();
    });

}

MarkupToolbox.prototype.generateTitle = function () {
    var oThis = this;

    this.toolboxTitle = $('<span/>')
	                    .addClass('csm-toolbox-title')
	                    .html('&nbsp;Article Markup')
						.appendTo(this.toolboxMenu);

    this.titleButtons = $('<span/>')
	                    .addClass('csm-toolbox-title-buttons')
						.appendTo(this.toolboxTitle);

    if( this.editMode ) {
        this.settingsButton = $('<a/>')
                            .attr('href', 'javascript:void(0);')
                            .attr('title', 'Markup Settings')
                            .click(function() {
                                curate.showSettingsDialog();
                                return false;
                            })
                            .appendTo(this.titleButtons);

        $('<img/>').attr('border', '0')
                   .attr('src', this.config.settingsIcon)
                   .appendTo(this.settingsButton);

        $('<span/>').html('&nbsp;').appendTo(this.titleButtons);
    }

    this.minimizeButton = $('<a/>')
                        .attr('href', 'javascript:void(0);')
                        .attr('title', 'Minimize')
                        .click(function() {
                            $.cookie('toolbox_minimized', '1', { expires: 365 });
                            oThis.toolboxContent.slideUp();
                            return false;
                        })
                        .appendTo(this.titleButtons);

    $('<img/>').attr('border', '0')
               .attr('src', this.config.minimizeIcon)
               .appendTo(this.minimizeButton);

    this.maximizeButton = $('<a/>')
                        .attr('href', 'javascript:void(0);')
                        .attr('title', 'Maximize')
                        .click(function() {
                            $.cookie('toolbox_minimized', '0', { expires: 365 });
                            oThis.toolboxContent.slideDown();
                            return false;
                        })
                        .appendTo(this.titleButtons);

    $('<img/>').attr('border', '0')
               .attr('src', this.config.maximizeIcon)
               .appendTo(this.maximizeButton);

    this.autoHideButton = $('<a/>')
                        .attr('href', 'javascript:void(0);')
                        .attr('title', 'Auto Hide')
                        .click(function() {
                            if( oThis.isDocked() ) {
                                $.cookie('toolbox_docked', '0', { expires: 365 })
                                $('#autohide').attr('src', oThis.config.dockIcon);
                            }
                            else {
                                $.cookie('toolbox_docked', '1', { expires: 365 })
                                $('#autohide').attr('src', oThis.config.undockIcon);
                            }
                            return false;
                        })
                        .appendTo(this.titleButtons);

    var autoHideImg = $('<img/>')
	                    .attr('id', 'autohide')
	                    .attr('border', '0')
                        .attr('src', !this.isDocked() ? this.config.dockIcon : this.config.undockIcon)
                        .appendTo(this.autoHideButton);
}

MarkupToolbox.prototype.generateContent = function () {
    var oThis = this;

    this.toolboxContent = $('<span/>')
	                    .addClass('csm-toolbox-content')
						.appendTo(this.toolboxMenu);

    this.generateTabs();

    if($.cookie('toolbox_minimized') == '1') this.toolboxContent.hide();

    this.generateToolbar(this.markupTab);
	this.markupMenu = $('<ul/>').appendTo(this.markupTab);
	this.generateSubMenu(this.markupMenu, $('markup>groups', this.xmlConfig).get()[0].childNodes);

    $.get(this.config.extractedEntities, {id: this.artId, type: 'entities', tmp: (new Date()).getTime()}, function(xml) {
        oThis.xmlEntities = xml;

        oThis.generateToolbar(oThis.entitiesTab);
        oThis.entitiesMenu = $('<ul/>').appendTo(oThis.entitiesTab);
        oThis.showEntities(oThis.entitiesMenu);
    });
}

MarkupToolbox.prototype.generateTabs = function () {
    var oThis = this;
    this.tabs = $('<div>' +
                    '<ul style="margin-bottom:0px;">' +
                    '    <li><a href="#markupTab"><span>Markup</span></a></li>' +
                    '    <li><a href="#entitiesTab"><span>Entities</span></a></li>' +
                    '</ul>' +
                    '<div id="markupTab" />' +
                    '<div id="entitiesTab" />' +
                '</div>').appendTo(this.toolboxContent);

    this.tabs.tabs({ onShow:  function(w, e, r) {
                                    $.cookie('tab', oThis.tabs.activeTab(), { expires: 365 })
                              }
                  });

    if( $.cookie('tab') != null ) {
        this.tabs.triggerTab(parseInt($.cookie('tab')));
    }

    this.markupTab = $('#markupTab', this.tabs);
    this.entitiesTab = $('#entitiesTab', this.tabs);
}

MarkupToolbox.prototype.generateToolbar = function (root) {
    var oThis = this;
    var toolbar = $('<div/>').appendTo(root);

    var hideAllButton = $('<a/>')
                        .css('float', 'right')
                        .addClass('toolbar-button')
                        .attr('href', 'javascript:void(0);')
                        .attr('title', 'Hide All Entities')
                        .click(function() {
                            oThis.showAll = false;
                            oThis.showHideAllEntities(oThis.showAll);
                            return false;
                        })
                        .append( $('<img />').attr('src', this.config.hideAllIcon) )
                        .append( $('<span />').text('Hide All') )
                        .appendTo(toolbar);

    var showAllButton = $('<a/>')
                        .css('float', 'right')
                        .addClass('toolbar-button')
                        .attr('href', 'javascript:void(0);')
                        .attr('title', 'Show All Entities')
                        .click(function() {
                            oThis.showAll = true;
                            oThis.showHideAllEntities(oThis.showAll);
                            return false;
                        })
                        .append( $('<img />').attr('src', this.config.showAllIcon) )
                        .append( $('<span />').text('Show All') )
                        .appendTo(toolbar);

    var printButton = $('<a/>')
                        .addClass('toolbar-button')
                        .attr('href', 'javascript:void(0);')
                        .attr('title', 'Print Document')
                        .click(function() {
                            window.frames["content_frame"].focus();
                            window.frames["content_frame"].print();
                            return false;
                        })
                        .append( $('<img />').attr('src', this.config.printIcon) )
                        .append( $('<span />').text('Print') )
                        .appendTo(toolbar);

    $('<span/>')
        .html('&nbsp;')
        .appendTo(toolbar);
}

MarkupToolbox.prototype.generateSubMenu = function (root, groupItems) {
    var oThis = this;

    var header = null;
    var token = null;
    var title = null;
	var li = null;
	var ul = null;
	var a = null;
	var buttons = null;

	$(groupItems).each(function(index) {
		if( this.tagName == 'group' ) {
    		li = $('<li/>').appendTo(root);

		    header = $(this).attr('header');
			li.attr('group', 'group_' + header.replace(/[ \/\\]/gi,'_'));

            li.append($('<input type="checkbox"' + (oThis.showAll ? ' checked="checked"' : '') + '" />')
                            .css('border', 'none')
                            .attr('token', token)
                            .click(function() {
                                var checked = this.checked;

                                $('input[type=checkbox]', $(this).parent()).each(function() {
                                    this.checked = checked;

                                    if( this.token != null ) {
                                        oThis.showHideEntities($(this).attr('token'), this.checked);
                                    }
                                });
                            }));

			li.append( $('<span />').addClass('title').html(header) );

			li.click( function(event) {
				if (this == event.target) {
				    $(this).children('UL').each(function() {
				        if($(this).is(':hidden')) {
						    $(this).parent().css('list-style-image','url(' + oThis.config.minusIcon + ')');
						    $(this).slideDown();

                            $.cookie($(this).parent().attr('group'), '1', { expires: 365 })
				        }
				        else {
						    $(this).parent().css('list-style-image','url(' + oThis.config.plusIcon + ')');
						    $(this).slideUp();

                            $.cookie($(this).parent().attr('group'), null)
				        }
				    });
				}
			});

			ul = $('<ul/>').appendTo(li);
			oThis.generateSubMenu(ul, this.childNodes);

            if( $.cookie(li.attr('group')) != null ) {
	    		li.css({cursor:'pointer', 'list-style-image':'url(' + oThis.config.minusIcon + ')'});
            }
            else {
    			li.css({cursor:'pointer', 'list-style-image':'url(' + oThis.config.plusIcon + ')'}).children('UL').hide();
            }
		}
		else if( this.tagName == 'entity' ) {
    		li = $('<li/>').appendTo(root);

		    token = $(this).attr('token');
		    title = $(this).attr('title');

			li.addClass('csm-' + token);
			if( token == 'structure-image' ) li.css('position', 'static');

			li.css({cursor: 'default', 'list-style-image':'url(' + oThis.config.pointIcon + ')'});

            $('<input type="checkbox"' + (oThis.showAll ? ' checked="checked"' : '') + '/>')
                .css('border', 'none')
                .attr('token', token)
                .click(function() {
                    oThis.showHideEntities($(this).attr('token'), this.checked);
                })
                .appendTo(li);

            if( oThis.editMode ) {
                a = $('<a/>').appendTo(li);
                a.attr('href', 'javascript:void(0);')
                    .html(title)
                    .attr('token', token)
                    .click( function(event) {
   			            if(top.MarkSelection($(this).attr('token')) ) {
			            }
			            return false;
    			    });
            }
            else {
                $('<span/>').html(title).appendTo(li);
            }
    	}
	});
}

MarkupToolbox.prototype.showEntities = function (root) {
    var oThis = this;

    var header = null;
    var token = null;
    var grpid = null;
    var title = null;
	var li = null;
	var ul = null;
	var a = null;
	var buttons = null;
	var hasAttrs = false;

	$('entity', this.xmlConfig).each(function(index) {
	    token = $(this).attr('token');
	    hasAttrs = $(this).is(':has(attribute)');

	    if( $(oThis.xmlEntities).is(':has(entity[ent_type="' + token + '"])') ) {
    		li = $('<li/>').appendTo(root);

		    header = $(this).attr('title');

            li.append($('<input type="checkbox"' + (oThis.showAll ? ' checked="checked"' : '') + '/>')
                            .css('border', 'none')
                            .attr('token', token)
                            .click(function() {
                                var checked = this.checked;

                                $('input[type=checkbox]', $(this).parent()).each(function() {
                                    this.checked = checked;
                                });

                                oThis.showHideEntities($(this).attr('token'), this.checked);
                            }));

			li.append( $('<span />').addClass('title').html(header) );

			li.click( function(event) {
				if (this == event.target) {
				    $(this).children('UL').each(function() {
				        if($(this).is(':hidden')) {
						    $(this).parent().css('list-style-image','url(' + oThis.config.minusIcon + ')');
						    $(this).slideDown();

//                            $.cookie($(this).parent().attr('group'), '1', { expires: 365 })
				        }
				        else {
						    $(this).parent().css('list-style-image','url(' + oThis.config.plusIcon + ')');
						    $(this).slideUp();

//                            $.cookie($(this).parent().attr('group'), null)
				        }
				    });
				}
			});

			ul = $('<ul/>').appendTo(li);
	        $('entity[ent_type="' + token + '"]', oThis.xmlEntities).each(function(index) {
            	    grpid = $(this).attr('group_id');

    		        var ent_li = $('<li/>').appendTo(ul);

		            token = $(this).attr('ent_type');
		            title = $(this).attr('ent_text');


			        ent_li.addClass('csm-' + token);
			        if( token == 'structure-image' ) {
			            ent_li.css('position', 'static');
                        if( title == null ) title = '<i>not converted</i>';
			        }

        			ent_li.css({cursor: 'default', 'list-style-image':'url(' + oThis.config.pointIcon + ')'});

                    $('<input type="checkbox"' + (oThis.showAll ? ' checked="checked"' : '') + '/>')
                        .css('border', 'none')
                        .attr('grpid', grpid != null ? grpid : '-1' )
                        .click(function() {
                            oThis.highlightGroup($(this).attr('grpid'), this.checked);
                        })
                        .appendTo(ent_li);
/*
                    if( oThis.editMode && hasAttrs ) {
                        $('<a/>')
                            .attr('href', 'javascript:void(0);')
                            .attr('title', 'Edit Properties')
                            .click(function() {
                                return false;
                            })
                            .append( $('<img/>').attr('src', oThis.config.editPropsIcon) )
                            .appendTo(ent_li);
                    }
*/
                    $('<a/>')
                        .attr('href', 'javascript:void(0);')
                        .css('text-decoration', 'none')
                        .attr('token', token)
                        .attr('grpid', grpid != null ? grpid : '-1')
                        .html(title)
                        .click(function() {
                            $('span[grpid="' + $(this).attr('grpid') + '"]:first', oThis.doc).each(function(index) {
                                this.scrollIntoView();
                            });
                        })
                        .hover(
                            function(e) {
               				    top.showToolbar(this, e);
                            },
                            function(e) {
                            }
                        )
                        .appendTo(ent_li);
	        });

   			li.css({cursor:'pointer', 'list-style-image':'url(' + oThis.config.plusIcon + ')'}).children('UL').hide();
	    }
	});
}

MarkupToolbox.prototype.refreshEntities = function () {
    var oThis = this;

    $.get(this.config.extractedEntities, {id: this.artId, type: 'entities', tmp: (new Date()).getTime()}, function(xml) {
        oThis.xmlEntities = xml;

        oThis.entitiesMenu.empty();
        oThis.showEntities(oThis.entitiesMenu);
    });
}

MarkupToolbox.prototype.showHideEntities = function (token, show) {
    var oThis = this;

    if( show ) {
        $('.csm-dis-' + token, oThis.doc).each(function() { 
            this.className = this.className.replace(/csm-dis-/i, 'csm-');
        });
    }
    else {
        $('.csm-' + token, oThis.doc).each(function() { 
            this.className = this.className.replace(/csm-/i, 'csm-dis-');
        });
    }
}

MarkupToolbox.prototype.showHideAllEntities = function (show) {
    var oThis = this;

    $('input[type=checkbox]', this.markupTab).each(function() {
        this.checked = show;

        if( $(this).attr('token') != null ) {
            oThis.showHideEntities($(this).attr('token'), show);
        }
    });

    $('input[type=checkbox]', this.entitiesTab).each(function() {
        this.checked = show;
    });
}

MarkupToolbox.prototype.highlightGroup = function (grpid, highlight) {
    var oThis = this;

    if( highlight ) {
        $('span[grpid="' + grpid + '"]', oThis.doc).each(function(index) {
            this.className = this.className.replace(/csm-dis-/i, 'csm-');
        });
    }
    else {
        $('span[grpid="' + grpid + '"]', oThis.doc).each(function(index) {
            this.className = this.className.replace(/csm-/i, 'csm-dis-');
        });
    }
}

MarkupToolbox.prototype.scrollToolbox = function () {
	var pos = 0;
	if (window.innerHeight)
	{
		  pos = window.pageYOffset
	}
	else if (document.documentElement && document.documentElement.scrollTop)
	{
		pos = document.documentElement.scrollTop
	}
	else if (document.body)
	{
		pos = document.body.scrollTop
	}

	this.toolboxMenu.css('top', pos + this.offsetTop);
}
