var CSManualCuration = function(mode, artId) {
    var oThis = this;

	this.doc = null;
	this.mode = mode;
	this.articleId = artId;

    if( !$.browser.msie ) {
        this.mode = 'eViewMode';
    }

    this.config = { configFile: '/article-markup.xml',
                    handler: '/ArticleMarkup.ashx',
                    css: 'markup.css',
                    progressIcon: '/images/progress2.gif'
                  }

	this.selectedImgBlock = null;
	this.selectedStructure = null;
	this.selectedArea = {x:0, y:0, w:0, h:0};

    this.markUpAll = false;
    this.clearAll = false;

    this.selection = {  id: '',         //  Selected item ID
                        grpId: 0,       //  Group ID
                        entityType: '', //  Type of entity
                        dtr: null,      //  Document Text Range,
                        span: null,     //  SPAN's instanse
                        text: '',       //  Inner SPAN text
                        html: '',       //  Outer SPAN HTML
                        area: null      //  Image selection area
                     };

    this.doBeforeAction = null;

    this.doOnMarkup = null;
    this.doOnClear = null;

    $.get(this.config.configFile, {}, function(xml) {
        oThis.configXml = xml;
    });

	$(document).ready(function() {
	    oThis.createSettingsDialog();
	    oThis.createConfirmDialog();
	    oThis.createClearConfirmDialog();
	    oThis.createEditDialog();
	    oThis.createProgressDialog();
	});

    $.ajaxSetup({   timeout:60000,
                    error: function(xhr) {
                        alert('AJAX Error: Timeout error!\n');
                        oThis.hideProgress();
                    }
                });
}

CSManualCuration.prototype.setStatus = function(msg) {
    top.status = msg;
}

CSManualCuration.prototype.clearStatus = function() {
    this.setStatus('');
}

CSManualCuration.prototype.getMarkAllEntries = function() {
    if( $.cookie('csm_mark_all') == null ) return true;
    else return $.cookie('csm_mark_all') == '1' ? true : false;
}

CSManualCuration.prototype.setMarkAllEntries = function(flag) {
    $.cookie('csm_mark_all', flag ? '1' : '0', { expires: 365 });
}

CSManualCuration.prototype.getClearAllEntries = function() {
    if( $.cookie('csm_clear_all') == null ) return true;
    else return $.cookie('csm_clear_all') == '1' ? true : false;
}

CSManualCuration.prototype.setClearAllEntries = function(flag) {
    $.cookie('csm_clear_all', flag ? '1' : '0', { expires: 365 });
}

CSManualCuration.prototype.getAskConfirmation = function() {
    if( $.cookie('csm_ask_confirm') == null ) return true;
    else return $.cookie('csm_ask_confirm') == '1' ? true : false;
}

CSManualCuration.prototype.setAskConfirmation = function(flag) {
    $.cookie('csm_ask_confirm', flag ? '1' : '0', { expires: 365 });
}

CSManualCuration.prototype.isViewMode = function() {
    return this.mode == 'eViewMode';
}

CSManualCuration.prototype.isEditMode = function() {
    return this.mode == 'eEditMode';
}

CSManualCuration.prototype.setDocument = function(doc) {
	this.doc = doc;

	this.attachCSS();
	this.attachScripts();
}

CSManualCuration.prototype.attachCSS = function() {
//	this.doc.createStyleSheet(this.css);

	var head = this.doc.documentElement.getElementsByTagName('HEAD')[0];
	var link = this.doc.createElement('LINK');
	link.setAttribute('rel', 'stylesheet');
	link.setAttribute('href', this.config.css);
	head.appendChild(link);
}

CSManualCuration.prototype.attachScripts = function() {
	var oThis = this;

//    if( $.browser.mozilla || $.browser.msie ) {
        loadScript(oThis.doc, '/js/jquery-1.3.2.js', function() {
            loadScript(oThis.doc, '/js/jquery.imgareaselect-0.4.2.js', function() {});
            loadScript(oThis.doc, '/js/jquery.cookie.js', function() {});
            loadScript(oThis.doc, '/js/cs-inside-markup.js', function() {
                window.frames["content_frame"].initMarkup();
            });
        });
//    }
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Selection entities functions
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.initSelectionFromTxtRange = function(txtRange, entityType) {
    this.selection = {  id: this.nextEntityId(),
                        grpId: 0,
                        entityType: entityType,
                        dtr: this.doc.body.createTextRange(),
                        span: null,
                        text: txtRange.text,
                        html: txtRange.htmlText,
                        area: null
                     };
}

CSManualCuration.prototype.initSelectionFromImage = function(span, area, entityType) {
	var urlRegExp = new RegExp("src[ ]*=[ ]*\"([^\"]+)\"", 'i');
	var tmpInnerHtml = span.innerHTML;

    this.selection = {  id: this.nextEntityId(),
                        grpId: 0,
                        entityType: entityType,
                        dtr: null,
                        span: span,
                        text: urlRegExp.test(tmpInnerHtml) ? urlRegExp.exec(tmpInnerHtml)[1] : '',
                        html: span.innerHTML,
                        area: {	width: span.offsetWidth, 
								height: span.offsetHeight,
								x: area.x,
								y: area.y,
								w: area.w,
								h: area.h }
                     };
}

CSManualCuration.prototype.initSelectionByID = function(id) {
    var oThis = this;

//    var entityRegEx = new RegExp('^csm-([a-zA-Z0-9_-]+)');

    if( id == '' || $('span#' + id, oThis.doc).length == 0 ) {
        alert('Cannot get SPAN by the specified ID: ' +  id);
        return false;
    }

    $('span#' + id, oThis.doc).each(function() {
        oThis.selection = {  id: $(this).attr('id'),
                            grpId: $(this).attr('grpid'),
                            entityType: oThis.getEntityType(this.className),//entityRegEx.test(this.className) ? entityRegEx.exec(this.className)[1] : 'underfined',
                            dtr: null,
                            span: this,
                            text: $(this).text(),
                            html: $(this).html(),
                            area: null
                         };
    });

    return true;
}

CSManualCuration.prototype.initSelectionByGroupID = function(id) {
    var oThis = this;

//    var entityRegEx = new RegExp('^csm-([a-zA-Z0-9_-]+)');

    if( id == '' || $('span[grpid=' + id + ']', oThis.doc).length == 0 ) {
        alert('Cannot get SPAN by the specified group ID: ' +  id);
        return false;
    }

    $('span[grpid=' + id + ']:first', oThis.doc).each(function() {
        oThis.selection = {  id: $(this).attr('id'),
                            grpId: $(this).attr('grpid'),
                            entityType: oThis.getEntityType(this.className),//entityRegEx.test(this.className) ? entityRegEx.exec(this.className)[1] : 'underfined',
                            dtr: null,
                            span: this,
                            text: $(this).text(),
                            html: $(this).html(),
                            area: null
                         };
    });

    return true;
}

CSManualCuration.prototype.currentSelection = function() {
    return this.selection;
}

CSManualCuration.prototype.nextEntityId = function() {
    return 'csm' + ((new Date()).getTime() + Math.floor(Math.random()*777));
}

CSManualCuration.prototype.getEntityType = function(classname) {
    classname = classname.replace(/csm-structure-wrapper/, "");
    classname = classname.replace(/  /, " ");

    var regEx = new RegExp('csm-([a-zA-Z0-9_-]+)');
    return regEx.test(classname) ? regEx.exec(classname)[1] : 'underfined';
}
/////////////////////////////////////////////////////////////////////////////////////////////////

CSManualCuration.prototype.getHTMLContent = function() {
	if( this.selectedStructure != null ) {
		$(this.selectedStructure).removeClass("csm-selected-strct-image");
	}

	return this.clearHTML(this.doc.documentElement.outerHTML);
}

CSManualCuration.prototype.clearHTML = function(html) {
	html = html.replace(/<LINK [^>]*HREF=[^>]*markup\.css[^>]*>(<\/LINK>)?(\r\n)?/gi, '');
	html = html.replace(/<SCRIPT [^>]*src=[^>]*jquery-1\.2\.6\.js[^>]*>(<\/SCRIPT>)?(\r\n)?/gi, '');
	html = html.replace(/<SCRIPT [^>]*src=[^>]*jquery\.imgareaselect-0\.4\.2\.js[^>]*>(<\/SCRIPT>)?(\r\n)?/gi, '');
	html = html.replace(/<SCRIPT [^>]*src=[^>]*cs-inside-markup\.js[^>]*>(<\/SCRIPT>)?(\r\n)?/gi, '');
	html = html.replace(/<SCRIPT [^>]*src=[^>]*jquery\.cookie\.js[^>]*>(<\/SCRIPT>)?(\r\n)?/gi, '');
	html = html.replace(/<SPAN [^>]*class=[^>]*csm-image-wrapper[^>]*>(.*?)<\/SPAN>/gi, '$1');
    html = html.replace(/(<SPAN [^>]*[^ ])( *csm-dis- *)([^>]*>)/gi, '$1csm-$3')

    //  Remove items for Image Area Selection plugin...
	html = html.replace(/<DIV [^>]*class=[^>]*ias-out-left[^>]*>(.*?)<\/DIV>(\r\n)?/gi, '');
	html = html.replace(/<DIV [^>]*class=[^>]*ias-out-top[^>]*>(.*?)<\/DIV>(\r\n)?/gi, '');
	html = html.replace(/<DIV [^>]*class=[^>]*ias-out-right[^>]*>(.*?)<\/DIV>(\r\n)?/gi, '');
	html = html.replace(/<DIV [^>]*class=[^>]*ias-out-bottom[^>]*>(.*?)<\/DIV>(\r\n)?/gi, '');
	html = html.replace(/<DIV [^>]*class=[^>]*ias-area[^>]*>(.*?)<\/DIV>(\r\n)?/gi, '');
	html = html.replace(/<DIV [^>]*class=[^>]*ias-border1[^>]*>(.*?)<\/DIV>(\r\n)?/gi, '');
	html = html.replace(/<DIV [^>]*class=[^>]*ias-border2[^>]*>(.*?)<\/DIV>(\r\n)?/gi, '');

	html = html.replace(/ +jQuery[0-9]*=\"?[0-9]*\"?/g, '');

	return html;
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Markup text functions
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.markUpTextRange = function(txtRange) {
    var oThis = this;

	var html = "<span class='csm-" + this.selection.entityType + "' id='" + this.selection.id + "'>" + txtRange.htmlText + "</span>";
	txtRange.pasteHTML(html)

	var span = this.doc.getElementById(this.selection.id);
	if(span != null) {
		//	When we attach function as a function() it won't appear in result 
		//	document HTML and we shouldn't remove it manually.
		span.title = span.innerText;
	    span.onmouseover = function(e) { top.showToolbar(this, e); }
	}

    this.setStatus('Do markup request...');

    $.post( this.config.handler,
            {   oper: 'markup',
                artId: this.articleId,
                entityType: this.selection.entityType,
                id: this.selection.id,
                text: this.selection.text,
                html: this.selection.html,
                replacement: html
            },
            function(data, textStatus) {
                oThis.ajaxCallback(data, textStatus);
            },
            'xml');

	return html;
}

CSManualCuration.prototype.markUpNextTextRange = function() {
    if( this.nextTextRange() ) {
	    if (!this.getAskConfirmation() || this.markUpAll ) {
	        this.markUpSelectedTextRange();
	    }
	    else {
	        this.showConfirmDialog()
	    }
    }
    else {
        this.MarkUpEnd();
    }
}

CSManualCuration.prototype.markUpSelectedTextRange = function() {
    this.selection.id = this.nextEntityId();
    this.markUpTextRange(this.selection.dtr);
}

CSManualCuration.prototype.nextTextRange = function() {
    var regExp = new RegExp("<span class=(\"|')?csm-" + this.selection.entityType + "(\"|')?","i");

    var dtr = this.selection.dtr;
    while (dtr != null && dtr.findText(this.selection.text, 100000, 2)) {
	    //	Check that found text is not yet marked up...
	    if( regExp.test(dtr.htmlText) ) {
		    dtr.collapse(false)
		    continue;
	    }

	    dtr.select();
	    dtr.scrollIntoView();

	    return true;
	}

	return false;
}

CSManualCuration.prototype.markTextSelection = function(entityType) {
	var txtRange = this.doc.selection.createRange();
	var htmlTxt = txtRange.htmlText;
	if( htmlTxt != '' ) {
		if( this.validateSelection(htmlTxt) ) {
            this.initSelectionFromTxtRange(txtRange, entityType);

			this.markUpTextRange(txtRange);

            if( this.doBeforeAction != null ) {
                this.doBeforeAction();
            }

			//	REFRESH DOCUMENT CONTENT AND ATTACH BALLOON TO THE CREATED SELECTION!!!
//			this.doc.parentWindow.CSBalloonMarkup();

			return true;
		}
		else {
			this.doc.selection.empty();
		}
	}
	else {
		alert('Make a selection at first!');
	}

	return false;
}

CSManualCuration.prototype.MarkUpEnd = function() {
    this.markUpAll = false;
    this.sendDoc('markup');
}
////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Markup image functions
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.markUpImage = function() {
    var oThis = this;

    var area = this.selection.area;

	var structSpan = this.doc.createElement('SPAN');
	structSpan.className = 'csm-' + this.selection.entityType;
	structSpan.setAttribute("id", this.selection.id);
	structSpan.style.top = area.y + 'px';
	structSpan.style.left = area.x + 'px';
	structSpan.style.width = area.w + 'px';
	structSpan.style.height = area.h + 'px';
	this.selection.span.appendChild(structSpan);

	$(structSpan)
	    .mousedown(function(evnt) {
		    oThis.setSelectedStructure(this);
		    return false;
	    })
	    .click(function() {
	        return false;
	    })
	    .mouseover(function(e) {
            top.showToolbar(this, e);
	    });

    this.showProgress();

    this.setStatus('Do markup request...');

    $.post( this.config.handler,
            {   oper: 'markup',
                artId: this.articleId,
                entityType: this.selection.entityType,
                id: this.selection.id,
                text: this.selection.text,
                html: this.selection.html,
                replacement: structSpan.outerHTML,
                area: 'width:' + area.width + ';height:' + area.height + ';x:' + area.x + ';y:' + area.y + ';w:' + area.w + ';h:' + area.h + ';'
            },
            function(data, textStatus) {
                oThis.ajaxCallback(data, textStatus);
            },
            'xml');
}

CSManualCuration.prototype.markImageSelection = function(entityType) {
	if( this.selectedImgBlock == null ) {
		alert('Select any image at first!');
		return false;
	}

	var oThis = this;

	$(this.selectedImgBlock).removeClass("csm-image-wrapper");
	if( !$(this.selectedImgBlock).hasClass("csm-structure-wrapper") ) {
		$(this.selectedImgBlock).addClass("csm-structure-wrapper");
	}

    this.initSelectionFromImage(this.selectedImgBlock, this.selectedArea, entityType);
    this.markUpImage();

	this.selectedImgBlock = null;

	this.doc.parentWindow.clearImgSelection();

	return true;
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Markup thumbnail
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.markThumbnailSelection = function(entityType) {
	if( this.selectedImgBlock == null ) {
		alert('Select any image at first!');
		return false;
	}

   	if( $(this.selectedImgBlock).hasClass("csm-thumbnail") ) {
		alert('Image is already marked as a Thumbnail!\nPlease choose another one!');
		return false;
   	}

    var checkRegEx = new RegExp('src="?(/ArticlesHandler.ashx\?[^ "]+)"?');
    if( !checkRegEx.test(this.selectedImgBlock.innerHTML) ) {
		alert('You cannot mark this image as a Thumbnail at this momment. It is not supported at this time!\nPlease choose another one!');
		return false;
    }

	var oThis = this;

    this.initSelectionFromImage(this.selectedImgBlock, this.selectedArea, entityType);
    this.markUpThumbnail();

	this.selectedImgBlock = null;

	this.doc.parentWindow.clearImgSelection();

	return true;
}

CSManualCuration.prototype.markUpThumbnail = function() {
    var oThis = this;

	$(this.selectedImgBlock).mouseover(function(e) { top.showToolbar(this, e); });

	$(this.selectedImgBlock).removeClass("csm-image-wrapper");
	if( !$(this.selectedImgBlock).hasClass("csm-thumbnail") ) {
		$(this.selectedImgBlock).addClass("csm-thumbnail");
	}

	this.selectedImgBlock.setAttribute("id", this.selection.id);

    this.setStatus('Do markup request...');

    var src = (new RegExp('src="?(/ArticlesHandler.ashx\?[^ "]+)"?')).exec(this.selectedImgBlock.innerHTML)[1];
    var imgId = (new RegExp('id=([0-9]+)')).exec(src)[1];

    $.post( this.config.handler,
            {   oper: 'markup',
                artId: this.articleId,
                entityType: this.selection.entityType,
                id: this.selection.id,
                text: imgId,
                html: '',
                replacement: this.selectedImgBlock.outerHTML,
                area: 'width:0;height:0;x:0;y:0;w:0;h:0;'
            },
            function(data, textStatus) {
                oThis.ajaxCallback(data, textStatus);
            },
            'xml');
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  General markup function...
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.markSelection = function(entityType) {
	if( entityType == 'structure-image' )
		return this.markImageSelection(entityType);
	else if ( entityType == 'thumbnail' )
	    return this.markThumbnailSelection(entityType);
	else
		return this.markTextSelection(entityType);
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Markup callback functions
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.ajaxCallback = function(data, textStatus) {
    this.hideProgress();

    if( textStatus == 'success' ) {
        if( $('markup', data).is(':has(error)') ) {
            //  Some error has occured...
            this.setStatus('Error: ' + $('error', data).text());
            alert('Error: ' + $('error', data).text());
        }
        else {
            var oper = $('entity', data).attr('oper');

            this.clearStatus();

            this.executeOperation(data);

            if( oper == 'markup' ) {
                //  Markup operation...
                var entityType = $('entity', data).attr('type');
                if( entityType == 'structure-image' ) {
                    //  Image mode...
                    this.MarkUpEnd();
                }
                else {
                    //	Text mode... Mark up all another text entries...
                    if( this.getMarkAllEntries() ) {
                        this.markUpNextTextRange();
                    }
                    else {
                        this.MarkUpEnd();
                    }
                }
            }
            else if(oper == 'clear') {
                if( this.getClearAllEntries() ) {
                    this.clearNextEntityFromGroup();
                }
                else {
                    this.ClearEnd();
                }
            }
            else if(oper == 'doc') {
                //  Send document for update operation...
            }
            else if(oper == 'list') {
                //  Add entity to list operation...
            }
            else if(oper == 'get_props') {
                //  Show Edit Properties dialog...
                this.displayEditPropertiesDialog(data);
            }
            else if(oper == 'set_props') {
                //  Set entity properties...
                this.closeEditDialog();
            }
        }
    }
    else {
        this.setStatus('Error: Internal markup error');
        alert('Error: Internal markup error!\n' + data.xml);
    }
}

CSManualCuration.prototype.executeOperation = function(data) {
    if( $('markup', data).is(':has(operation)') ) {
        var oper_name = $('operation', data).attr('name');

        var entity_id = $('entity', data).attr('id');
        var entity_type = $('entity', data).attr('type');

        if( oper_name == 'clear_selection' ) {
            this.clearAll = true;
            top.ClearSelectedText();
        }
        else if( oper_name == 'set_group_id' ) {
            this.selection.grpId = $('operation', data).attr('grp_id');
            $('#' + entity_id, this.doc).attr('grpid', this.selection.grpId);
        }
        else if( oper_name == 'mark_as_validated' ) {
            $('#' + entity_id, this.doc)
                .removeClass('csm-not-validated')
                .removeClass('csm-ambiguous');
            $('span[grpId="' + this.selection.grpId + '"]', this.doc).each(function() {
                $(this)
                    .removeClass('csm-not-validated')
                    .removeClass('csm-ambiguous');
            });

            this.sendDoc('markup');
        }
        else if( oper_name == 'event' ) {
            var eventName = $('operation', data).attr('event');
            if( eventName == 'OnMarkUp' ) {
                if( this.doOnMarkup != null ) {
                    this.doOnMarkup();
                }
            }
            else if( eventName == 'OnClear' ) {
                if( this.doOnClear != null ) {
                    this.doOnClear();
                }
//                this.doc.location = this.doc.location.href;
//                this.doc.location.reload();
            }
            this.RefreshEntities();
        }
        else if( oper_name == 'reload_window' ) {
            this.doc.location.reload();
//            this.RefreshEntities();
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Set document for update
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.sendDoc = function(oper_type) {
    var oThis = this;

    this.setStatus('Sending document for update...');
    $.post( this.config.handler,
            {   oper: 'doc',
                artId: this.articleId,
                oper_type: oper_type,
                doc: this.getHTMLContent()
            },
            function(data, textStatus) {
                oThis.ajaxCallback(data, textStatus);
            },
            'xml');
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Clear markup functions
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.clearSelection = function() {
    if( this.doBeforeAction != null ) {
        this.doBeforeAction();
    }

	if(this.selection.entityType == 'structure-image') {
	    //  Image mode...
        this.selection.span.parentElement.removeChild(this.selection.span);

    	this.selectedStructure = null;
	}
	else if(this.selection.entityType == 'thumbnail') {
        $(this.selection.span).unbind("mouseover");

        $(this.selection.span).removeClass("csm-thumbnail");
	    if( !$(this.selection.span).hasClass("csm-structure-wrapper") ) {
		    $(this.selection.span).addClass("csm-image-wrapper");
	    }

		this.clearSelectedImgBlock();
	}
	else {
	    //  Text mode...
		this.clearSelectedImgBlock();

		this.selection.span.outerHTML = this.selection.span.innerHTML;
	}

    var oThis = this;

    this.setStatus('Make clearing...');

    $.post( this.config.handler,
            {   oper: 'clear',
                artId: this.articleId,
                entityType: this.selection.entityType,
                id: this.selection.id,
                text: this.selection.text,
                html: this.selection.html
            },
            function(data, textStatus) {
                oThis.ajaxCallback(data, textStatus);
            },
            'xml');

	return true;
}

CSManualCuration.prototype.clearNextEntityFromGroup = function() {
    if( this.nextEntityFromGroup() ) {
	    if (!this.getAskConfirmation() || this.clearAll ) {
	        this.clearSelection();
	    }
	    else {
            this.showClearConfirmDialog();
	    }
    }
    else {
        this.ClearEnd();
    }
}

CSManualCuration.prototype.nextEntityFromGroup = function() {
    if( $('span[grpid=' + this.selection.grpId + ']', this.doc).length > 0 ) {
        var spanObj = $('span[grpid=' + this.selection.grpId + ']:first', this.doc);
        this.selection.span = spanObj.get()[0];
        this.selection.id = spanObj.attr('id');
        this.selection.text = spanObj.text();
        this.selection.html = spanObj.html();

        return true;
    }
    return false;
}

CSManualCuration.prototype.ClearEnd = function() {
    this.clearAll = false;
    this.sendDoc('clear');
}

CSManualCuration.prototype.validateSelection = function(html) {
	var match = /<(address|blockquote|center|dir|div|dl|fieldset|form|hr|isindex|menu|noframes|noscript|ol|p|pre|table|ul|dd|dt|frameset|li|tbody|td|tfoot|th|thead|tr|applet|button|del|iframe|ins|map|object|script|img)[^>]*>/gi.exec(html);
	if( match != null && match.length > 0 ) {
		var prohibited_tags = '';
		for(i=0; i<match.length; i++) {
			if( prohibited_tags != '' ) prohibited_tags += ', ';
			prohibited_tags += match[i];
		}

		alert('Selected HTML text contains prohibited tags which cannot be selected in this version.\n' + prohibited_tags + '\n\nTry another selection.');

		return false;
	}
	return true;
}

CSManualCuration.prototype.validateImageSelection = function(html) {
	var match = /<(img|v:imagedata)[^>]*>/gi.exec(html);
	if( match != null ) {
		if( match.length == 2 ) {
			return true;
		}
		else if( match.length > 2 ) {
			alert('You have selected more than one image. Try another selection.');
			return false;
		}
	}

	alert('Wrong selection. Try another one.');

	return false;
}

CSManualCuration.prototype.clearSelectedImgBlock = function() {
	if( this.selectedImgBlock != null ) {
	    //  DO NOT MOVE THIS CODE FROM THIS PLACE!!!
		this.selectedImgBlock = null;

		this.doc.parentWindow.clearImgSelection();
	}

	this.clearSelectedStructure();
}

CSManualCuration.prototype.clearSelectedStructure = function() {
	if( this.selectedStructure != null ) {
		$(this.selectedStructure).removeClass("csm-selected-strct-image");
		this.selectedStructure = null;
	}
}

CSManualCuration.prototype.setSelectedImageBlock = function(span) {
	this.selectedImgBlock = span;
}

CSManualCuration.prototype.setSelectedImageArea = function(area) {
	this.clearSelectedStructure();

	this.selectedArea = area;
}

CSManualCuration.prototype.setSelectedStructure = function(span) {
	this.clearSelectedStructure();

	this.selectedStructure = span;
	if( !$(this.selectedStructure).hasClass("csm-selected-strct-image") )
		$(this.selectedStructure).addClass("csm-selected-strct-image");
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Add to list functions...
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.addToList = function(type) {
    var oThis = this;

    this.setStatus('Adding to list...');

    $.post( this.config.handler,
            {   oper: 'list',
                artId: this.articleId,
                entityType: this.selection.entityType,
                id: this.selection.id,
                text: this.selection.text,
                html: this.selection.html,
                type: type
            },
            function(data, textStatus) {
                oThis.ajaxCallback(data, textStatus);
            },
            'xml');
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Progress dialog functions...
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.createProgressDialog = function() {
    var oThis = this;
	this.progressDialog = $('<div id="progressMarkup" class="flora" title="Progress..."></div>').appendTo(document.body);

    var div = $('<div/>')
                .appendTo(this.progressDialog);

    var label = $('<img/>')
                    .attr('src', this.config.progressIcon)
                    .attr('title', 'Working...')
                    .appendTo(div);

    $('<span/>').html('&nbsp;Please wait...').appendTo(div);

    div = $('<div/>')
            .appendTo(this.progressDialog);

	$("#progressMarkup").dialog({	autoOpen: false, 
		                            modal: true,
                                    overlay: { opacity: 0.3, background: "black" },
									resizable: false,
									height: 100,
									width: 300
							});
}

CSManualCuration.prototype.showProgress = function() {
    $('#progressMarkup').dialog('open');
}

CSManualCuration.prototype.hideProgress = function() {
    $('#progressMarkup').dialog('close');
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Edit properties functions...
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.createEditDialog = function() {
    var oThis = this;

	//	Create confirmation markup dialog...
	var dialog = $('<div id="editProperties" class="flora" title="Edit properties..."></div>')
	            .appendTo(document.body);

    $('<table id="propertiesTable" />')
//        .css('display', 'inline')
        .appendTo(dialog);

	dialog.dialog({	autoOpen: false, 
                    modal: true,
                    overlay: { opacity: 0.3, background: "black" },
					buttons: {	" Ok ": function() {
					                oThis.sendEntityProperties();
					            },
								"Cancel": function() {
					    	        oThis.closeEditDialog();
								}
							},
					resizable: false
				});
}

CSManualCuration.prototype.showEditDialog = function() {
    var oThis = this;

    this.setStatus('Getting properties...');

    $.post( this.config.handler,
            {   oper: 'get_props',
                artId: this.articleId,
                entityType: this.selection.entityType,
                id: this.selection.id
            },
            function(data, textStatus) {
                oThis.ajaxCallback(data, textStatus);
            },
            'xml');
}

CSManualCuration.prototype.closeEditDialog = function() {
    $('#editProperties').dialog('close');
}

CSManualCuration.prototype.displayEditPropertiesDialog = function(data) {
    var oThis = this;

    var table = $('#propertiesTable');
    table.empty();

    $('#editProperties').dialog('open');

    var entityType = $('entity', data).attr('type');
    var entityNode = $('entity[token="' + entityType + '"]', this.configXml);

    var tr = null;
    var td = null;

    var attrName = null;
    var attrValue = null;
    var attrTitle = null;
    var attrType = null;
    var attrNode = null;
    var attrField = null;
    $('attr', data).each(function(index) {
        attrName = $(this).attr('name');
        attrValue = $(this).attr('value');
        attrNode = $('attribute[name="' + attrName + '"]', entityNode);
        attrTitle = attrNode.attr('title');
        attrType = attrNode.attr('type');

        tr = $('<tr />').appendTo(table);
        td = $('<td />').appendTo(tr);
        $('<nobr />').text(attrTitle + ':').appendTo(td);

        td = $('<td />').appendTo(tr);
        if( attrType == 'string' || attrType == 'int' ) {
            attrField = $('<input type="text" />')
                            .attr('name', attrName)
                            .appendTo(td);
            if( attrValue != null ) attrField.attr('value', attrValue);
        }
        else if( attrType == 'list' ) {
            var list = attrNode.attr('list');
            var listNode = $('list[id="' + list + '"]', oThis.configXml);

            attrField = $('<select/>')
                            .attr('name', attrName)
                            .appendTo(td);

            $('item', listNode).each(function() {
                var option = $('<option />')
                                .attr('value', $(this).attr('value'))
                                .text($(this).attr('title'))
                                .appendTo(attrField);

                if( attrValue != null && attrValue == $(this).attr('value') ) option.attr('selected', 'selected');
            });
        }
        else if( attrType == 'boolean' ) {
            attrField = $('<input type="checkbox" />')
                            .attr('name', attrName)
                            .appendTo(td);

            if( attrValue != null && attrValue == 'true' ) attrField.attr('checked', 'checked');
        }
    });

    $("#editProperties").data("title.dialog", 'Edit ' + $(entityNode).attr('title') + ' properties...'); 
    $("#editProperties").data("width.dialog", table.width() + 30);
    $("#editProperties").data("height.dialog", table.height() + 100);
}

CSManualCuration.prototype.sendEntityProperties = function() {
    var oThis = this;

    var table = $('#propertiesTable');

    var data = new Object();
    $(data)
        .attr('oper', 'set_props')
        .attr('artId', this.articleId)
        .attr('entityType', this.selection.entityType)
        .attr('id', this.selection.id);

    var entityNode = $('entity[token="' + this.selection.entityType + '"]', this.configXml);

    var attrType = null;
    var attrName = null;
    var field = null;
    $('attribute', entityNode).each(function(index) {
        attrType = $(this).attr('type');
        attrName = $(this).attr('name');

        if( attrType == 'string' || attrType == 'int' ) {
            $(data).attr(attrName, $('input[name="' + attrName + '"]', table).attr('value'));
        }
        else if( attrType == 'list' ) {
            $(data).attr(attrName, $('select[name="' + attrName + '"]', table).attr('value'));
        }
        else if( attrType == 'boolean' ) {
            $(data).attr(attrName, $('input[name="' + attrName + '"]', table).attr('checked'));
        }
    });

    this.setStatus('Set new properties...');

    $.post( this.config.handler,
            data,
            function(data, textStatus) {
                oThis.ajaxCallback(data, textStatus);
            },
            'xml');
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Settings dialog functions...
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.createSettingsDialog = function() {
    var oThis = this;
	this.settingsDialog = $('<div id="settingsMarkup" class="flora" title="Settings..."></div>').appendTo(document.body);

    //  Mark all entries filed...
    var div = $('<div/>')
                .appendTo(this.settingsDialog);

    var label = $('<label/>')
                    .attr('for', 'markAllEntries')
                    .attr('title', 'Mark all similar entities found in this document')
                    .appendTo(div);

    $('<input type="checkbox"/>')
        .attr('id', 'markAllEntries')
//        .click(function() {
//            $('#askConfirmation').attr('disabled', !this.checked);
//        })
        .appendTo(label);

    $('<span/>').text('Mark All Entities').appendTo(label);

    //  Clear all entries filed...
    var div = $('<div/>')
                .appendTo(this.settingsDialog);

    var label = $('<label/>')
                    .attr('for', 'clearAllEntries')
                    .attr('title', 'Clear all similar entities from the same group')
                    .appendTo(div);

    $('<input type="checkbox"/>')
        .attr('id', 'clearAllEntries')
//        .click(function() {
//            $('#askConfirmation').attr('disabled', !this.checked);
//        })
        .appendTo(label);

    $('<span/>').text('Clear All Entities').appendTo(label);

    //  Ask confirmation filed...
    div = $('<div/>')
            .appendTo(this.settingsDialog);

    label = $('<label/>')
                .attr('for', 'askConfirmation')
                .attr('title', 'Ask confirmation before marking all similar entities found in this document (works in conjunction with Mark All Entities)')
                .appendTo(div);

    $('<input type="checkbox"/>')
        .attr('id', 'askConfirmation')
        .appendTo(label);

    $('<span/>').text('Ask Confirmation').appendTo(label);

	$("#settingsMarkup").dialog({	autoOpen: false, 
		                            modal: true,
                                    overlay: { opacity: 0.3, background: "black" },
									buttons: {	" Ok ": function() {
                                                        oThis.setMarkAllEntries($('#markAllEntries').get()[0].checked);
                                                        oThis.setClearAllEntries($('#clearAllEntries').get()[0].checked);
                                                        oThis.setAskConfirmation($('#askConfirmation').get()[0].checked);

									                    $("#settingsMarkup").dialog("close");
									                }, 
												"Cancel": function() {
												        $("#settingsMarkup").dialog("close");
												    }
											},
									resizable: false,
									height: 150,
									width: 300
							});
}

CSManualCuration.prototype.showSettingsDialog = function() {
    $('#settingsMarkup').dialog('open');

    if( this.getMarkAllEntries() ) {
        $('#markAllEntries').attr('checked', 'checked');
    }
    if( this.getClearAllEntries() ) {
        $('#clearAllEntries').attr('checked', 'checked');
    }
//    else {
//        $('#askConfirmation').attr('disabled', 'disabled');
//    }

    if( this.getAskConfirmation() ) {
        $('#askConfirmation').attr('checked', 'checked');
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Confirm markup dialog functions...
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.createConfirmDialog = function() {
    var oThis = this;

	//	Create confirmation markup dialog...
	$('<div id="confirmMarkup" class="flora" title="Do you want to continue?"></div>')
	    .text('Mark up this entity?')
	    .appendTo(document.body);

	$("#confirmMarkup").dialog({	autoOpen: false, 
		                            modal: true,
                                    overlay: { opacity: 0.3, background: "black" },
									buttons: {	" Ok ": function() {
						                	        oThis.markUpSelectedTextRange();
									    	        oThis.closeConfirmDialog();
									            },
												"Next": function() {
													oThis.selection.dtr.collapse(false);
												    if( !oThis.nextTextRange() ) {
												        alert('There is no any entity.');
    									    	        oThis.closeConfirmDialog();
												    }
												},
												" All ": function() {
												    oThis.markUpAll = true;
						                	        oThis.markUpSelectedTextRange();
									    	        oThis.closeConfirmDialog();
									            },
												"Stop": function() {
									    	        oThis.closeConfirmDialog();
                                                    oThis.MarkUpEnd();
												}
											},
									resizable: false,
									height: 120,
									width: 300
							});
}

CSManualCuration.prototype.showConfirmDialog = function() {
    $('#confirmMarkup').dialog('open');
}

CSManualCuration.prototype.closeConfirmDialog = function() {
    $('#confirmMarkup').dialog('close');
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Confirm clear dialog functions...
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.createClearConfirmDialog = function() {
    var oThis = this;

	//	Create confirmation markup dialog...
	$('<div id="confirmClear" class="flora" title="Do you want to continue?"></div>')
	    .text('Clear all another entities?')
	    .appendTo(document.body);

	$("#confirmClear").dialog({	autoOpen: false, 
		                        modal: true,
                                overlay: { opacity: 0.3, background: "black" },
					    		buttons: {	" Ok ": function() {
											    oThis.clearAll = true;
								    	        oThis.closeClearConfirmDialog();
					                	        oThis.clearSelection();
								            },
											"Cancel": function() {
                                                oThis.ClearEnd();
								    	        oThis.closeClearConfirmDialog();
											}
										},
								resizable: false,
								height: 120,
								width: 300
							});
}

CSManualCuration.prototype.showClearConfirmDialog = function() {
    $('#confirmClear').dialog('open');
}

CSManualCuration.prototype.closeClearConfirmDialog = function() {
    $('#confirmClear').dialog('close');
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Auto Markup functions
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.AutoMarkup = function(confidence) {
    var oThis = this;

    this.showProgress();
    this.setStatus('Do Auto Markup...');

    $.post( this.config.handler,
            {   oper: 'automarkup',
                artId: this.articleId,
                confidence: confidence
            },
            function(data, textStatus) {
                oThis.ajaxCallback(data, textStatus);
            },
            'xml');
}

CSManualCuration.prototype.Oscar3Markup = function(confidence) {
    var oThis = this;

    this.showProgress();
    this.setStatus('Do Auto Markup...');

    $.post( this.config.handler,
            {   oper: 'oscar3markup',
                artId: this.articleId,
                confidence: confidence
            },
            function(data, textStatus) {
                oThis.ajaxCallback(data, textStatus);
            },
            'xml');
}

///////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.RefreshEntities = function() {
    if( toolbox != null ) toolbox.refreshEntities();
}

////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Set article properties
//
////////////////////////////////////////////////////////////////////////////////////////////////
CSManualCuration.prototype.setProperies = function(name, value) {
    if(name == 'title') {
        this.doc.title = value;
    }
    else if(name == 'keywords') {
        if( $('HEAD>META[name=keywords]', this.doc).length > 0 ) {
            $('HEAD>META[name=keywords]', this.doc).replaceWith('<meta name="keywords" content="' + value + '">')
        }
        else {
            $('HEAD', this.doc).append('<meta name="keywords" content="' + value + '">')
        }
    }
}
