//=========================================================================================================
//
// Copyright 2002 Macromedia, Inc. All rights reserved.
//
// Feature: Paste Fix
// Author:  JDH
// Module:  PasteManager.js
// Purpose:	Main Paste Manager class (and entry points).
// Updates:
//	5/17/02 - Started file control
//	5/31/02 - Added more comments
//
//=========================================================================================================

//  The paste manager which handles the entire clipboard conversion process

function PasteManager()
{
	// Initialize the phases array

	this.phases = new Array();

	// Put together the initial list of content handlers

	var handlers = new Array();
	handlers.push( new ParseMetaTags );
	handlers.push( new IdentifyMSApplications );
	handlers.push( new FixupMSGarbage );
	handlers.push( new RetainStructure );
	handlers.push( new DecomposeClasses );
	handlers.push( new RemoveUnsupportedAttributes );
	handlers.push( new RemoveParsingRequiredStructuralTags );
	handlers.push( new RemoveCSSClasses );
	handlers.push( new DemoteToParagraphs );
	handlers.push( new SingleSpaceParagraphs );
	handlers.push( new MergeRedundantFontTags );
	handlers.push( new ChangeToStrongAndEm );

	// Iterate through the content handlers and put organize them by
	// priority number into the phases member.

	for( index in handlers )
	{
		// Get the phase descriptor from the handler

		var phase_desc = handlers[ index ].getPhase();
	
		// Get the phase priority

		var phase = phase_desc.priority;

		// If the phase is currently empty then create the array to put the
		// handlers into

		if ( this.phases[ phase ] == null )
		{
			this.phases[ phase ] = new Array();
			this.phases[ phase ].name = phase_desc.name;
			this.phases[ phase ].elements = new Array();
		}

		// Push the handler into the handlers list for this phase number

		this.phases[ phase ].elements.push( handlers[ index ] );
	}
}

PasteManager.prototype.run = PasteManager_run;
PasteManager.prototype.getClipHTML = PasteManager_getClipHTML;
PasteManager.prototype.getDebugText = PasteManager_getDebugText;
PasteManager.prototype.getDebugHTML = PasteManager_getDebugHTML;

function PasteManager_run( clipDOM, clipCSS, targetDOM, targetCSS, settings )
{
	// Put together the new context

	this.pasteContext = new PasteContext( clipDOM, clipCSS, targetDOM, targetCSS, settings );

	// Start the debug trace

	for( var setting in settings )
		this.pasteContext.debugInformation( "PasteManager", "Setting : " + setting );
	this.pasteContext.debugInformation( "PasteManager", "Start run" );

	// Iterate through the phases

	for ( var phase_index = 0; phase_index < PHASE_MAX; phase_index++ )
	{
		// If we have elements in this phase then iterate through them

		if ( this.phases[ phase_index ] )
		{
			// Put out the debugging information

			this.pasteContext.debugInformation( "PasteManager", "Phase: " + this.phases[ phase_index ].name );

			// Get the phase elements and interate through them and run each one

			var phase = this.phases[ phase_index ].elements;
			for( handler_index in phase )
			{
				var handler = phase[ handler_index ];
				handler.run( this.pasteContext );
			}
		}
	}

	// Finish the debug trace

	this.pasteContext.debugInformation( "PasteManager", "End run" );
	this.pasteContext.updateClipDOM();

	if ( this.pasteContext.settingDefined( SETTINGS_NO_FILTER ) )
		return false;
	return true;
}

function PasteManager_getDebugText( ) { return this.pasteContext.getDebugText(); }

function PasteManager_getDebugHTML( ) { return this.pasteContext.getDebugHTML(); }

function PasteManager_getClipHTML( )
{
	// JDH: This is pretty brute force.  First we turn the whole document into text, then we 
	// find the start and end of the fragment, suck it out, and then remove the markers from the
	// finished piece.

	var full_html = this.pasteContext.getClipText();

	full_html = full_html.replace( /[\r\n]/g, " " );

	var out_html = full_html.match( /\<body\>(.*?)\<\/body\>/g );
	out_html = out_html.toString();

	out_html = out_html.replace( /\<body\>/, "" );
	out_html = out_html.replace( /\<\/body\>/, "" );
	out_html = out_html.replace( /\<\!\-\-(\s*)StartFragment(\s*)\-\-\>/, "" );
	out_html = out_html.replace( /\<\!\-\-(\s*)EndFragment(\s*)\-\-\>/, "" );

	return out_html;
}



function smartPaste( bSilent, inputDOM, returnValue )
{
	// Check to make sure we aren't trying to paste in something huge

//	alert( inputDOM.documentElement.outerHTML );
//	alert( "vesion: jdh_021203" );
//	var deb = new DebugScanner();
//	deb.scan( inputDOM.documentElement.outerHTML );
//	return;
	
	if ( bSilent == false )
	{
		var text = inputDOM.documentElement.outerHTML;
		if ( text.length > MM.od_MaxThreshold)
		{
			alert( MM.MSG_odStop );
			returnValue[ 0 ] = true;
			return;
		}
		if ( text.length > MM.od_WarnThreshold )
		{
			if ( ! confirm( MM.MSG_odWarn ) )
			{
				returnValue[ 0 ] = true;
				return;
			}
		}
	}

	try {


		// Put together a new paste manager

		var mgr = new PasteManager();

		// Define the settings for the paste

		var settings = {};
		settings[ SETTINGS_CONTRIBUTE ] = 1;

		// Look for Contribute specific settings
		
		if ( dreamweaver.appName == "Contribute" )
		{
			if ( dreamweaver.getDocumentDOM().getCCSharedSetting_TextOnlyInNonTemplates() )
				settings[ SETTINGS_ETO ] = 1;

			if ( dreamweaver.getDocumentDOM().getCCSharedSetting_FontsEmitFontOrSpan() == "font" )
				settings[ SETTINGS_CHANGE_SPAN_TO_FONT ] = 1;

			if ( ! dreamweaver.getDocumentDOM().getCCSharedSetting_FontsLetUserChange() )
				settings[ SETTINGS_NO_CSS ] = 1;

			if ( ! dreamweaver.getDocumentDOM().getCCSharedSetting_StyleHTMLHeadings() )
				settings[ SETTINGS_DEMOTE_TO_PARAGRAPHS ] = 1;

			if ( ! dreamweaver.getDocumentDOM().getCCSharedSetting_StyleCSS() )
				settings[ SETTINGS_NO_CSS ] = 1;

			if ( dreamweaver.getDocumentDOM().getCCSharedSetting_SingleSpaceParagraphsCSS() )
				settings[ SETTINGS_SINGLE_SPACE_P ] = 1;
		}

		if ( dreamweaver.appName.match( /dreamweaver/i ) )
		{
			if ( dw.getPasteSettings().match( /high/ ) )
			{
				settings[ SETTINGS_CREATE_CLASSES ] = 1;
				settings[ SETTINGS_NO_FONT_MAP ] = 1;
			}
			else
			{
				settings[ SETTINGS_NO_CSS ] = 1;
				settings[ SETTINGS_LOW ] = 1;
			}
		}

		if ( dw.getPreferenceString("General Preferences", "Avoid Bold and Italic", 'TRUE') == 'TRUE')
			settings[ SETTINGS_USE_EMPHASIS ] = 1;

		if ( dw.getPreferenceString("General", "Use <strong> and <em> in place of <b> and <i>", "") )
			settings[ SETTINGS_USE_EMPHASIS ] = 1;

		// Get the names of the classes in the target

		var targetCSS = new CSSReferenceClassCollection();

		// Here we add referenced classes to the target CSS representative.  All that we
		// use is the class name.
		var styles = dreamweaver.cssStylePalette.getStyles();
		for ( var index in styles )
			targetCSS.add( styles[ index ] );

		// Get the CSS definitions from the clipboard

		var clipCSS = new CSSClassCollection( targetCSS );

		Utils_LoadCSSFromDOM( inputDOM, clipCSS );

		var filtered = mgr.run( inputDOM, clipCSS, null, targetCSS, settings );

		if ( filtered )
		{
			used_styles = clipCSS.create_used();
	
			out = mgr.getClipHTML();

			var htmlOut = "";
			htmlOut += "<html>\n";
			htmlOut += "<!--StartFragment-->\n";
			htmlOut += "<head>\n";
			if ( used_styles.length > 0 )
			{
				htmlOut += "<style type=\"text/css\"><!--\n" + used_styles + "--></style>\n";
			}
			htmlOut += "</head>\n";
			htmlOut += "<body>\n";
			htmlOut += out;
			htmlOut += "</body>\n";
			htmlOut += "<!--EndFragment-->\n";
			htmlOut += "</html>\n";

			inputDOM.documentElement.outerHTML = htmlOut;

//			alert( inputDOM.documentElement.outerHTML );
		}

		dw.forceGarbageCollection();

		formatSource( inputDOM );

	}
	catch( e )
	{
		alert( MM.MSG_odProblem );
		dw.getDocumentDOM().clipPasteText();
		returnValue[ 0 ] = true;
	}

	return true;
}
