/**************************************************************************
*
*  @@@BUILDINFO@@@ 24scripts-2.jsx 2.0.1.67   15-May-2007
*  Copyright 2006-2007 Adobe Systems Incorporated
*  All Rights Reserved.
*
* NOTICE:  All information contained herein is, and remains the property of
* Adobe Systems Incorporated  and its suppliers,  if any.  The intellectual
* and technical concepts contained herein are proprietary to  Adobe Systems
* Incorporated  and its suppliers  and may be  covered by U.S.  and Foreign
* Patents,patents in process,and are protected by trade secret or copyright
* law.  Dissemination of this  information or reproduction of this material
* is strictly  forbidden  unless prior written permission is  obtained from
* Adobe Systems Incorporated.
**************************************************************************/

// Code to add to the Scripts pane
// The output field of the scripts pane is a list box. The array scriptIDs
// takes a list of all script IDs. This list is used during Document.onSave()
// to determine if a document belongs to a target app and whether that app
// should receive a PutScript message.

// Get the script IDs and populate the Scripts pane. Each line contains
// two words. The first, is the display name, while the second word is the
// script ID. The script ID must be a path name if it starts with '/' or '~'. If
// it starts with anything else but a '(' (which is reserved for new scripts),
// it is app specific, and the app will have to supply the script on request.
// Application-supplied script IDs should be system unique.

// The "info" property is an object with script IDs as property names. Each
// object has the properties displayName, scriptID, status and readOnly. If a script
// is not executable, the status is "noexec". The object is also attached to
// the list item.

scripts = null;

app.createScripts = function( where, suppresPrefs, remote )
{
    //
    // create window
    //
    scripts = new Window(
        "dockpalette {											\
            text:'$$$/ESToolkit/Panes/Scripts/Title=Scripts',	\
            properties:                                         \
            {                                                   \
                defaultVisibility : true,						\
                flyoutmenu:true,								\
                name:'scripts',									\
                icon : '#PScripts_N',	                        \
                rollover : '#PScripts_R',                       \
                " + where + "			                        \
            },                                                  \
            preferredSize: [100, 100],							\
            margins      : 2,                                   \
            spacing      : 2,                                   \
            orientation  : 'column',                            \
                                                                \
            targetGroup : Group                                 \
            {                                                   \
                alignment : ['fill','top'],                     \
                orientation: 'row',                             \
                margins:0,                                      \
                                                                \
            targets: DropDownList                               \
            {									                \
                preferredSize: [40, 20],						\
                alignment    : ['fill','fill']                  \
                helpTip      : '$$$/ESToolkit/Panes/Scripts/htTargets=Select a target application.' \
            },								                    \
            engines: DropDownList                               \
            {									                \
                preferredSize: [40, 20],						\
                alignment    : ['fill','fill']                  \
                helpTip      : '$$$/ESToolkit/Panes/Scripts/htEngine=Select an engine of the selected target application.' \
            }								                    \
        },                                                      \
        output: TreeView                                        \
        {										                \
            preferredSize: [10, 20],							\
            alignment: ['fill', 'fill' ]						\
        }				                                        \
        infogrp : Group                                         \
        {                                                       \
            orientation : 'row',                                \
            margins      : 0,                                   \
            spacing      : 0,                                   \
            alignment	: ['fill','bottom'],					\
            pathField: EditText                                 \
            {								                    \
                properties	: { readonly: true },	            \
                alignment	: ['fill','bottom'],				\
                characters : 40                                 \
            },													\
            sizeBoxSpacer    : Group                            \
            {                                                   \
                alignment	: ['right','bottom'],				\
                preferredSize        : [14,1]                   \
            }                                                   \
        }                                                       \
    }");

    scripts.id = "scripts";
	scripts.menuText = localize ("$$$/ESToolkit/Menu/Window/Scripts/Title=&Scripts");

    ///////////////////////////////////////////////////////////////////////////////
    //
    // shortcuts
    //
    scripts.targetDDL   = scripts.targetGroup.targets;
    scripts.engineDDL   = scripts.targetGroup.engines;
    scripts.pathField   = scripts.infogrp.pathField;

	scripts.currentFavorite = PrefUtils.getValue ('prefs.scripts.favorite', 'String');

    ///////////////////////////////////////////////////////////////////////////////
    //
    // flyout menu
    //
    var item = new MenuElement( 'command', '$$$/ESToolkit/Panes/Scripts/Flyout/Refresh=Refresh', "at the end of scripts/flyout", "scripts/flyout/refresh" );
    item.scripts = scripts;
    item.onSelect = function()
    {
        scripts.targetGroup.fillScripts();
    }

    item = new MenuElement( 'command', '$$$/ESToolkit/Panes/Scripts/Flyout/AddFav=Add Favorite...', "---at the end of scripts/flyout", "scripts/flyout/addfav" );
    item.onSelect = function()
    {
        var newItem = scripts.favorites.dialog();

        if( newItem )
        {
            newItem = scripts.favorites.add( newItem.name, newItem.path, false, newItem.filter, newItem.recursive );

            if( scripts.favorites )
            {
                //
                // if the "Favorites" target is selected then
                // force updating the engines popup
                //
                var sel = scripts.targetDDL.selection;
                scripts.targetDDL.selection = null;
                scripts.targetDDL.selection = sel;

                //
                // after that select the new added favorite
                //
				scripts.engineDDL.selection = null;
				
				for( var i=0; i<scripts.engineDDL.items.length; i++ )
				{
					if( newItem.equal( scripts.engineDDL.items[i].favorite ) )
					{
						scripts.engineDDL.selection = scripts.engineDDL.items[i];
						break;
					}
				}
				
                scripts.setEnabled( true );
            }
        }
    }

    item = new MenuElement( 'command', '$$$/ESToolkit/Panes/Scripts/Flyout/ModFav=Modify Favorite', "at the end of scripts/flyout", "scripts/flyout/modfav" );
    item.onDisplay = function()
    {
        this.enabled = false;

        if( scripts.engineDDL.selection && scripts.engineDDL.selection.favorite && !scripts.engineDDL.selection.favorite.isDefault )
            this.enabled = true;
    }
    item.onSelect = function()
    {
        if( scripts.favorites && scripts.engineDDL.selection.favorite && !scripts.engineDDL.selection.isDefault )
        {
            var fav = scripts.favorites.dialog( scripts.engineDDL.selection.favorite );
            
            if( fav )
            {
                scripts.favorites.replace( scripts.engineDDL.selection.favorite, fav );
                scripts.engineDDL.selection.text = fav.name;
                scripts.targetGroup.fillScripts();
            }
        }
    }    

    item = new MenuElement( 'command', '$$$/ESToolkit/Panes/Scripts/Flyout/RemFav=Remove Favorite', "at the end of scripts/flyout", "scripts/flyout/remfav" );
    item.onDisplay = function()
    {
        this.enabled = false;

        if( scripts.engineDDL.selection && scripts.engineDDL.selection.favorite && !scripts.engineDDL.selection.favorite.isDefault )
            this.enabled = true;
    }
    item.onSelect = function()
    {
        if( scripts.favorites && scripts.engineDDL.selection.favorite && !scripts.engineDDL.selection.isDefault )
        {
            scripts.favorites.remove( scripts.engineDDL.selection.favorite );
            
            if( scripts.targetDDL.selection.favorites )
            {
                //
                // if the "Favorites" target is selected then 
                // force updating the engines popup
                //
                var sel = scripts.targetDDL.selection;
                scripts.targetDDL.selection = null;
                scripts.targetDDL.selection = sel;
                
                //
                // after that select the new added favorite
                //
                scripts.engineDDL.selection = null;
                scripts.engineDDL.selection = scripts.engineDDL.items.length-1;
            }
        }
    }    

    ///////////////////////////////////////////////////////////////////////////////
    //
    // UI handler
    //
    scripts.onResize =
    scripts.onResizing = function ()
    {
        this.layout.resize();
    }

	// The callback for the output list box is activated when the user
	// selects a different script. The code tries to find the document.
	// If found, it brings the document to the front. If not, it asks the
	// current debugger (who filled in the list) to fetch the script.

	scripts.output.onDoubleClick = function()
	{
		if (this.selection && this.selection.text.length)
		{
			if (this.selection.type == "item")
			{
				var info = this.selection.info;
				
				if( info )
				{
					var docCount    = documents.length;
					var target      = '';
					var engine      = '';
					var scriptID    = info.scriptID;
					var doc         = Document.find( scriptID );
				    
					if( this.parent.targetGroup.targets.selection )
						target = this.parent.targetGroup.targets.selection.target;
					
					if( this.parent.targetGroup.engines.selection )
					{
						engine = this.parent.targetGroup.engines.selection.text;
					
					    //
					    // check for invalid favorite
					    //	
						if( !this.parent.targetGroup.validateFavorite( this.parent.targetGroup.engines.selection.favorite ) )
						    return;
					}
				        
					if( !doc )
						this.parent.loadScript( scriptID, this.selection.text, target, engine, info.includePath );

					//
					// delayed activation of document (otherwise treeview item takes focus)
					//
					app.scheduleTask( 'var d=Document.find("'+scriptID+'");if(d)d.activate();', 1 );

					if( documents.length != docCount )
					{
						//
						// a new document were opened, set target&engine at document
						//
						targetMgr.setActive( target, engine );
					}					
				}
			}
			else
				this.selection.expanded = !this.selection.expanded;
		}
	}

    scripts.targetGroup.targets.onChange = function()
    {        
		this.window.setStatusText();

        if( this.window.blockTargetGroup <= 0 && this.selection )
		{
		    this.window.blockTargetGroup++;
		    this.awaitScriptList = false;
			this.window.setEnabled( false );
			
			if( this.selection.favorites )
			{
			    //
			    // fill script list with scripts of selected favorite
			    //
                this.parent.engines.removeAll();
		        
		        var i=0;
		        
		        for( i=0; i<this.window.favorites.length; i++ )
		        {
		            var favItem = this.window.favorites.items[i];
		            
		            item = this.parent.engines.add( 'item', favItem.name );
		            item.favorite = favItem;
		        }
				this.window.setCurrentFavorite();
	            this.parent.fillScripts();
		                
			    this.window.setEnabled( true );
			}
			else
			{
			    //
			    // TODO: find another solution, please!!
			    //
                if( !Debugger.doConnect( this.selection.target, false, 0, false, this.parent ) )
			    {
			        if( BridgeTalk.findInstance( this.selection.target, 'Connect' ) )
			        {
			            scripts.delayConnect = { target     : this.selection.target, 
			                                     doc        : false, 
			                                     dbgLevel   : 0, 
			                                     busyID     : false, 
			                                     clientObj  : this.parent };
                    }
                    else
                    {
                        this.selection = 0;
                        this.window.setEnabled( true );
                    }
			    }
			    else
			        delete scripts.delayConnect;
            }
            
            this.window.blockTargetGroup--;
		}
    }
    		
    scripts.targetGroup.engines.onChange = function()
    {
		this.window.setStatusText();

        if( this.window.blockTargetGroup <= 0 )
        {
            if( this.selection && this.parent.validateFavorite( this.selection.favorite ) )
			    this.parent.fillScripts();
		}
	}

    scripts.output.onChange = function()
    {
	    var pathStr = '';

        if( this.parent.targetGroup.engines.selection && 
            !this.parent.targetGroup.validateFavorite( this.parent.targetGroup.engines.selection.favorite ) )
            return;
            
		if( this.selection )
		{		
		    if( this.selection.favorite )
		        pathStr = this.selection.favorite.path;
		    else if( this.selection.info )
		        pathStr = this.selection.info.scriptID;
		    else if( this.selection.folder )
		        pathStr = this.selection.folder;
		    
		    var path = new File( pathStr );

		    if( path.exists )
		        pathStr = path.fsName;
		}
		        
		this.window.setStatusText();
	    this.window.pathField.textselection = pathStr;
    }
    
	scripts.output.onExpand = function(item)
	{
	    item.icon = '#FolderOpened';
	    
	    if( item.items.length == 0 && this.window.engineDDL.selection )
	    {
	        if( this.window.engineDDL.selection.favorite )
	        {
	            if( this.parent.targetGroup.validateFavorite( this.window.engineDDL.selection.favorite ) )
	                scripts.targetGroup.populateFavoritesList( item, item.folder, this.window.engineDDL.selection.favorite.filter, this.window.engineDDL.selection.favorite.recursive );
	        }
	        else
	            scripts.targetGroup.populateFavoritesList( item, item.folder, "*.js?", true );
	    }
	}

	scripts.output.onCollapse = function(item)
	{
	    item.icon = '#FolderClosed';
	}

    ///////////////////////////////////////////////////////////////////////////////
    //
    // notify handler
    //
    
    scripts.onNotify = function( reason, param01, param02, param03, param04 )
    {
        if( this.initialized )
        {
            switch( reason )
            {
                case 'getScriptSourceFor':
                {
                    var source      = arguments[1];
                    var target      = arguments[2];
                    var engine      = arguments[3];
                    var scriptID    = arguments[4];
                    var includePath = arguments[5];
                    
                    if( source )
                    {
                        var doc = Document.find( scriptID );
                        
                        if( !doc )
                        {
	                        // new doc: try to find the title in the list of scripts
	                        if( !scripts.title )
	                        {
		                        var info = scripts.info[scriptID];
		                        
		                        if( info )
			                        scripts.title = info.displayName;
		                        else
			                        // fallback: use the display name as title
			                        scripts.title = targetMgr.getTargetDisplayName( target );
	                        }
	                        
	                        var docWin = Document.create( scripts.title, source, scriptID );
                        	
	                        if( docWin )
	                            doc = docWin.document;
                        }
                        else
                        {
	                        // make sure that the text is displayed.
	                        doc.setText( source, false );
	                        breakpoints.update();
                        }
                        
                        // set target and engine
                        var info        = scripts.info[scriptID];
                        doc.target      = target;
                        doc.engine      = engine;
                        doc.status      = ( info ? info.status : "exec" );
                        doc.readOnly    = ( info ? info.readOnly : true );
                        doc.includePath = ( includePath ? includePath : '' );
                        
                        // To be on the safe side, mark the script received as read only
                        // if there is no script ID.
                        if (!scriptID.length)
	                        doc.readOnly = true;

                        app.toFront();
                        // this may be a reload of a doc
                        if (this.dbg && (!this.dbg.document || this.dbg.document.scriptID == doc.scriptID))
	                        this.dbg.setDocument (doc);
                        	
                        if( this.docTarget && engine )
							targetMgr.setActive( target, engine, doc );
                            
                        // reflect the script state etc
                        menus.debug.reflectState();
                    }
                    else
                    {
                        if (this.dbg)
                            this.dbg.stop();
                            
                        errorBox( '$$$/ESToolkit/Alerts/CannotLoadScript=Cannot load script from target %1!',
                                  targetMgr.getTargetDisplayName( target ) );
                    }
                }
                break;
                
                case 'getScriptListFor':
                {
                    if( this.awaitScriptList )
                    {
                        if( param01 )
                        {
                            // clear all lists
                            scripts.output.removeAll();
                            scripts.info = {};
                            
                            var scriptInfo = param01;
                            scriptInfo.sort();
                            
                            for( var i=0; i<scriptInfo.length; i++ )
                            {
								//
								// Disk files must start with "~" or "/" (see IDEBackend::getScripts())
                                //
								var icon = "#ScriptSource";
								var nodeType = "item";
								var isFolder = false;

								if (scriptInfo[i].scriptID[0] == '/' || scriptInfo[i].scriptID[0] == '~')
								{
									var tmp1 = File( scriptInfo[i].scriptID );
									var tmp2 = tmp1.resolve();
									tmp1 = ( tmp2 ? tmp2 : tmp1 );
									
									if (tmp1.exists)
									{
										isFolder = (tmp1 instanceof Folder);
										if (isFolder)
											icon = "#FolderClosed", nodeType = "node";
										else
											icon = "#ScriptFile";
									}
								}
								
								var item    = scripts.output.add( nodeType, scriptInfo[i].displayName );
								item.info   = scriptInfo[i];
								item.folder = isFolder ? Folder (scriptInfo[i].scriptID) : null;
								item.icon   = icon;
								scripts.info[item.info.scriptID] = item.info;
                            }
                        }
                        
                        scripts.window.blockTargetGroup--;
                        
                        this.awaitScriptList = false;
                    }
                }
                break;
                
                case 'destroyBT':
                {
                    if( this.delayConnect                   && 
                        this.delayConnect.target == param01  && 
                        param02 == 'Connect'                    )
                    {
                        if( Debugger.doConnect( this.delayConnect.target, this.delayConnect.doc, this.delayConnect.dbgLevel, this.delayConnect.busyID, this.delayConnect.clientObj ) )
                            delete this.delayConnect;
                    }
                }
                break;
                
			    case 'shutdown':
			    {
					prefs.scripts.favorite = this.currentFavorite;
				    this.output.removeAll();
				    this.targetGroup.targets.removeAll();
				    this.targetGroup.engines.removeAll();
				    globalBroadcaster.unregisterClient( this );
			    }
			    break;
    			
                case 'changeTargets':
                case 'addTarget':
                    this.fillTargets();
                    break;
    				
			    case 'targetDied':
			    {
				    if( this.targetGroup.targets.selection &&  param01.targetName == this.targetGroup.targets.selection.target )
					    this.targetGroup.targets.selection = 0;
			    }
			    break;
    			
			    case 'state':
			    {
			        // TODO: set icons for engines depending on debugger state
			    }
			    break;
			    
			    case 'newFavorites':
			    {
			        scripts.favorites = favorites;

			        if( scripts.targetDDL.items.length > 0 )
			            scripts.targetDDL.items[0].favorites = favorites;
			    
			        if( scripts.targetDDL.selection && scripts.targetDDL.selection == scripts.targetDDL.items[0] )
			        {
			            var oldSel = scripts.engineDDL.selection;
			            
			            scripts.engineDDL.removeAll();
			            
			            for( var i=0; i<favorites.length; i++ )
			            {
		                    item = scripts.engineDDL.add( 'item', favorites.items[i].name );
		                    item.favorite = favorites.items[i];
			            }
			            
			            if( oldSel )
			                scripts.engineDDL.selection = oldSel;
			            else
			                scripts.engineDDL.selection = 0;
        		
		                scripts.targetGroup.fillScripts();
			        }
			    }
			    break;
            }
        }
    }

    //-----------------------------------------------------------------------------
    // 
    // scripts.erase(...)
    // 
    // Purpose: empty list of scripts
    // 
    //-----------------------------------------------------------------------------

    scripts.erase = function()
    {
        scripts.output.removeAll();
    }

    //-----------------------------------------------------------------------------
    // 
    // scripts.deselect(...)
    // 
    // Purpose: remove selection in script list
    // 
    //-----------------------------------------------------------------------------

    scripts.deselect = function()
    {
	    this.output.selection = null;
    }

    //-----------------------------------------------------------------------------
    // 
    // scripts.setEnabled(...)
    // 
    // Purpose: set palettes enable state
    // 
    //-----------------------------------------------------------------------------

	scripts.setEnabled = function( state )
	{
		this.targetGroup.enabled = state;
		this.output.enabled = state;
	}
	
	//-----------------------------------------------------------------------------
	// 
	// scripts.fillTargets(...)
	// 
	// Purpose: fill targets DropDownList
	// 
	//-----------------------------------------------------------------------------
	
    scripts.fillTargets = function()
    {              
        //
        // remove entries
        //            
        this.window.targetDDL.removeAll();
        
        this.window.blockTargetGroup++;
        
        var item = this.window.targetDDL.add( 'item', localize('$$$/ESToolkit/ScriptFavorites/Title=Favorites') );
        item.favorites = this.favorites;
        
        //
        // fill targets
        //        
        var ownSpec = BridgeTalk.appName + '-' + BridgeTalk.appVersion + '-' + ( ( BridgeTalk.appLocale.length > 0 ) ? ( '-' + BridgeTalk.appLocale ) : '' );

        var targets = targetMgr.getTargets();

        for( var i=0; i<targets.length; i++ )
        {
            if( ownSpec.indexOf( targets[i].targetName ) < 0 )
            {
			    var text = targets[i].title;
                var item = this.window.targetDDL.add( 'item', text );
                item.target = targets[i].targetName;
            }
        }
        
        this.window.blockTargetGroup--;
        
        //
        // set selection
        //
		// This loads the Favorites
	    this.window.targetDDL.selection = 0;
		this.setCurrentFavorite();
    }

    //-----------------------------------------------------------------------------
    // 
    // scripts.targetGroup.populateFavoritesList(...)
    // 
    // Purpose: fill scripts list
    // 
    //-----------------------------------------------------------------------------

    scripts.targetGroup.populateFavoritesList = function( node, folder, filter, recursive )
    {
		var fileList = folder.getFiles( filter );

        if( recursive )
        {
            var subFolders = folder.getFiles();
            
            for( var i=0; i<subFolders.length; i++ )
            {
                var tmp = subFolders[i].resolve();
                
                tmp = ( tmp ? tmp : subFolders[i] );
                
				if( tmp instanceof Folder )
				{
					var item    = node.add( 'node', ( subFolders[i].displayName == '' ? subFolders[i].name : subFolders[i].displayName ) );
					item.icon   = '#FolderClosed';
					item.folder = tmp;
					item.info   = node.info;
				}
            }
        }
        
        for( var i=0; i<fileList.length; i++ )
        {
			var file = fileList[i];
			if (!(file instanceof File))
				continue;
			if (file.alias)
			{
				// #1461401: do not list aliases that are folders
				var file2 = file.resolve();
				if (file2 instanceof Folder)
					continue;
			}

            var item    = node.add( 'item', file.displayName );
            item.icon   = '#ScriptFile';
            item.info   = { 
                            displayName : file.displayName, 
                            scriptID    : file.absoluteURI,
			                status      : 'exec', 
			                readOnly    : ( file.readOnly == true ) ,
			                includePath : ''
                          };

            if( node.info && node.info.includePath )
                item.info.includePath = node.info.includePath;
            else
            {
                var tmp = File( item.info.scriptID );
                
                if( tmp.exists )
					item.info.includePath = tmp.parent ? tmp.parent.absoluteURI : "/";
    		}
    		
            scripts.info[fileList[i].absoluteURI] = item.info;
        }
    }
    
    scripts.fillScripts = function()
    {
        this.targetGroup.fillScripts();
    }
    
	scripts.targetGroup.fillScripts = function()
	{
	    this.window.setStatusText();
		this.window.setEnabled( false );
		
		var target = '';
		var engine = '';

		if( this.targets.selection && this.engines.selection )
		{
		    if( this.targets.selection.favorites )
		    {
		        //
		        // fill script list for favorites
		        //
		        var favorite = this.engines.selection.favorite;

		        if( favorite )
		        {
			        this.window.currentFavorite = favorite.name;
                    var folder = new Folder( favorite.path );
                    
                    scripts.erase();

                    if( this.validateFavorite( favorite ) )
                        this.populateFavoritesList( scripts.output, folder, favorite.filter, favorite.recursive );
		        }
		        
		        this.window.setEnabled( true );
		    }
		    else
		    {
		        //
		        // fill script list for target & engine
		        //
			    target = this.targets.selection.target;
			    engine = this.engines.selection.text;
			
		        if( !this.parent.requestingScripts && target.length > 0 && engine.length > 0 )            
		        {
			        this.parent.requestingScripts = true;
			        app.scheduleTask( 'scripts.getScriptsFor( "' + target + '","' + engine + '");scripts.requestingScripts=false;scripts.setEnabled(true);', 1, false );
		        }
		        else
			        this.window.setEnabled( true );
			}
		}
		else
		    this.window.setEnabled( true );
    }

    scripts.targetGroup.validateFavorite = function( favorite )
    {
        var ret = true;
        
        this.window.setStatusText();
        
        if( favorite && !Folder( favorite.path ).exists )
        {
            ret = false;
            addDelayedTask( this.window.erase );
            
            this.window.setStatusText( localize( '$$$/CT/ExtendScript/Errors/Err48=File or folder does not exist' ), true );
        }
        
        return ret;
    }
    
    scripts.setStatusText = function( text, error )
    {
        var winGfx = this.pathField.graphics; 
        
        if( error )
        {
            var redColorPen = winGfx.newPen (winGfx.PenType.SOLID_COLOR, [1, 0, 0], 1);
            winGfx.foregroundColor = redColorPen;
        }
        else
            winGfx.foregroundColor = null;
            
        if( !text )
            text = ' ';
            
        this.pathField.text = text;
    }
    
    //-----------------------------------------------------------------------------
    // 
    // scripts.getScriptsFor(...)
    // 
    // Purpose: get scripts for target&engine
    // 
    //-----------------------------------------------------------------------------

    scripts.getScriptsFor = function( targetName, engineName )
    {
        this.window.blockTargetGroup++;
        this.awaitScriptList = true;
        this.getScriptListFor( targetName, engineName, this );
	}
			
    //-----------------------------------------------------------------------------
    // 
    // scripts.getScriptListFor(...)
    // 
    // Purpose: [static] Request list of script for target&engine, notify client if received
    // 
    //-----------------------------------------------------------------------------

    scripts.getScriptListFor = function( targetName, engineName, clientObj )
    {
        var bt = BridgeTalk.create( targetName, "GetScripts" );
        bt.headers.Engine = engineName;
        bt.clientObj = clientObj;

        bt.onOwnError = function (bt)
        {
            if( this.clientObj )
            {
                var target = this.target.replace( '#estk', '' );
                this.clientObj.onNotify( 'getScriptListFor', null, target, this.engineName );
            }
        }

        bt.onOwnResult = function(bt)
        {
            var target = this.target.replace( '#estk', '' );

            // clear all lists
            var infoArray = [];
            var reply = bt.splitBody();

            for( var i=0; i<reply.length; i++ )
			{
				// if we have an empty line, this is the separator between scripts and additional info
				if( reply[i].length == 0 )
					break;
					
				// fill in what we have got
				var displayName = reply [i][0];
				var scriptID    = reply [i][1];
				var status		= reply [i][2];
				var readOnly	= reply [i][3];
				if (!status)
					status = "exec";
				// backwards compatibility
				if (status == "active")
					status = "exec";
				
				// do we have both?
				if( displayName.length && scriptID.length )
				{
					// Remove .LNK from a display name in case installers failed
					if( displayName.substr( displayName.length-4 ) == '.LNK' )
						displayName = displayName.substr( 0, displayName.length-4 );
					if( displayName.length <= 0 ) 
					    displayName = ' ';	// ScriptUI might run into breakpoint with 0-length strings
					
					info = {    displayName : displayName, 
					            scriptID    : scriptID,
								status      : status, 
								readOnly    : ( readOnly == true ),
								includePath : ''
						    };
						    
                    var tmp = File( info.scriptID );
                    
                    if( tmp.exists )
						info.includePath = tmp.parent ? tmp.parent.absoluteURI : "/";
                        
					infoArray.push( info );
				}
			}
			
			//
			// do we have extra info?
			//
			if (++i < reply.length && reply[i].length && reply [i][0].length)
			{
			    //
				// 1st extra line (V48+): the include path
				//
				var includePath = reply [i][0];

				for( var i=0; i<infoArray.length; i++ )
				    infoArray[i].includePath = includePath;
			}
		
            if( this.clientObj )
                this.clientObj.onNotify( 'getScriptListFor', infoArray, target, this.engineName );
		}
		
		return bt.safeSend();
	}

    //-----------------------------------------------------------------------------
    // 
    // scripts.getScriptSourceFor(...)
    // 
    // Purpose: return script source code
    // 
    //-----------------------------------------------------------------------------

	scripts.getScriptSourceFor = function( scriptID, title, target, engine, clientObj, includePath )
	{
		var ret = true;
		
		if (scriptID [0] == '(')
			clientObj.onNotify( 'getScriptSourceFor', null, target, engine, scriptID );
		else if (scriptID [0] == '/' || scriptID [0] == '~')
		{
			var file = new File( scriptID );
			var text = '';
			
			if( file.open( 'r' ) )
			{
				text = Document.safeRead (file);
				file.close();
			}
			
			if( text && text.length <= 0 )
				text = null;
		
			clientObj.onNotify( 'getScriptSourceFor', text, target, engine, scriptID, includePath );
		}
		else
		{
			var bt              = BridgeTalk.create( target, "GetScript", true );
			bt.headers.Engine   = engine;
			bt.headers.ScriptID = scriptID;
			// attach additional data for onResult()
			bt.engine           = engine;
			bt.title            = title;
			bt.dbg              = currentDebugger;	// in case we switched away before the reply comes in
			bt.docTarget        = target;
			bt.docEngine        = engine;
			bt.clientObj        = clientObj;
			bt.includePath      = includePath;

			bt.onOwnResult = function (bt)
			{
				var target   = bt.sender.replace ("#estk", "");
				var scriptID = this.headers.ScriptID;

				if( this.clientObj )
					this.clientObj.onNotify( 'getScriptSourceFor', bt.body, target, this.docEngine, scriptID, this.includePath );
			}
			bt.onOwnError = function (bt)
			{
				var target = bt.sender.replace ("#estk", "");
				var scriptID = this.headers.ScriptID;

				if( this.clientObj )
					this.clientObj.onNotify( 'getScriptSourceFor', null, target, this.docEngine, scriptID );
			}
			
			ret = bt.safeSend();
		}
		
		return ret;
	}

    //-----------------------------------------------------------------------------
    // 
    // scripts.loadFile(...)
    // 
    // Purpose: Load a script from file and bring that doc to the front.
    // 
    //-----------------------------------------------------------------------------

	scripts.loadFile = function (scriptID)
	{
		var doc;
		var file = new File (scriptID);
		var f2 = file.resolve();
		if (f2)
		{
			// this is an alias
			file = f2;
			scriptID = file.absoluteURI;
		}
		// Try to find an existing doc
		for (var i = 0; i < documents.length; i++)
		{
			doc = documents [i];
			if (doc.scriptID == scriptID)
			{
				// the doc is already present, so reload
				doc.reload();
				doc.activate();
				breakpoints.update();
				return doc;
			}
		}
		// not found: create a new document
		doc = Document.load (file);
		if (doc)
			doc.status = "exec";
		return doc;
	}

    //-----------------------------------------------------------------------------
    // 
    // scripts.loadScript(...)
    // 
    // Purpose: Get a script from the target app. 
    // 
    //-----------------------------------------------------------------------------

	scripts.loadScript = function( scriptID, title, target, engine, includePath )
	{
		if (scriptID [0] == '(')
			return;
		else if (scriptID [0] == '/' || scriptID [0] == '~')
		{
			this.loadFile (scriptID);
			return;
		}
		
		this.getScriptSourceFor( scriptID, title, target, engine, this, includePath );
	}

    //-----------------------------------------------------------------------------
    // 
    // scripts.storeScript(...)
    // 
    // Purpose: Store the script into the target if appropriate. Return true if a 
    //          PutScript operation was initiated.
    // 
    //-----------------------------------------------------------------------------

	scripts.storeScript = function (doc)
	{
		var scriptID = doc.scriptID;
		if (scriptID != '(' && scriptID != '/' && scriptID != '~')
		{
			var bt = BridgeTalk.create( currentDebugger.target, "PutScript", true );
			bt.headers.Engine = currentDebugger.engine;
			bt.headers.ScriptID = scriptID;
			bt.body = doc.text;
			bt.docTitle = doc.title;
			// use onResult - the result is debugger independent
			bt.onResult = function (bt)
			{
				var doc = documents.find (this.headers.ScriptID);
				if (doc)
					doc.setSaved();
				// the scripts pane may have changed due to the save operation
				scripts.fillScripts();
				this.destroy();
			}
			// use onError - the error is debugger independent
			bt.onError = function (bt)
			{
				errorBox (localize ("$$$/CT/ExtendScript/Errors/Err46=%1 is read only", this.docTitle));
				this.destroy();
			}
			bt.safeSend();
			return true;
		}
		else
			// traditional disk save
			return false;
	}    
    
    //-----------------------------------------------------------------------------
    // 
    // scripts.targetGroup.onConnected(...)
    // 
    // Purpose: handle debugger connect
    // 
    //-----------------------------------------------------------------------------
    
    scripts.targetGroup.onConnected = function( connected, target, engines, dbgLevel, doc )
    {    
        var currentTarget = '';
        
	    if( this.parent.targetGroup.targets.selection )
	        currentTarget = this.parent.targetGroup.targets.selection.target;

        if( currentTarget == '' || target == currentTarget )
        {
            if( connected )
            {
                this.engines.removeAll();
		        this.engines.selection = null;
		        
		        var targetObj = targetMgr.findTarget( target );
		        
		        if( targetObj )
		        {
		            var engines = targetObj.getEngines();
		            
                    var i=0;
                    
                    this.window.blockTargetGroup++;

                    for( i=0; i<engines.length; i++ )
                        this.engines.add( 'item', engines[i] );

                    if( i > 0 )
                        this.engines.selection = 0;
                    
                    this.window.blockTargetGroup--;
		        }
        		
		        this.fillScripts();
    		    
		        this.targets.oldSelection = this.targets.selection;
		    }
		    else
		    {
		        this.window.setEnabled( true );

		        if( !this.targets.oldSelection )
		            this.targets.oldSelection = 0;
    		        
                this.targets.selection = this.targets.oldSelection;		        
		    }
		}
    }

	scripts.setCurrentFavorite = function()
	{
		var items = this.engineDDL.items;
		// Preset to 0 (Default). This will then take care of the favorite not being found.
		// In that case, it always reverts to Default (also covers localization)
		var sel = 0;

		for (var i = 0; i < items.length; i++)
		{
			if (items[i].text == this.currentFavorite)
			{
				sel = i; break;
			}
		}
		this.engineDDL.selection = sel;
	}

    ///////////////////////////////////////////////////////////////////////////////
    //
    // initialize palette
    //

    //
    // register for broadcasts
    //
	globalBroadcaster.registerClient( scripts );
    targetMgr.registerClient( scripts );
    Debugger.registerClient( scripts );

    //
    // first fill favorites
    //
    if( !scripts.favorites )
        scripts.favorites = favorites;
    
	scripts.requestingScripts   = false;
    scripts.blockTargetGroup    = 0;		
	scripts.info                = {};

    scripts.show();
	panes.push(scripts);
	
	scripts.initialized         = true;
}

