﻿//------------------------------------------------------------------------------
//
// ADOBE SYSTEMS INCORPORATED
// Copyright 2000-2004 Adobe Systems Incorporated 
// All Rights Reserved
//
// NOTICE: Adobe permits you to use, modify, and distribute 
// this file in accordance with the terms of the Adobe license 
// agreement accompanying it. If you have received this file 
// from a source other than Adobe, then your use, modification, 
// or distribution of it requires the prior written permission 
// of Adobe.
//
//------------------------------------------------------------------------------

var PerforceApplicationPath = null;

//-----------------------------------------------------------------------------
// 
// Perforce(...)
// 
// Purpose: ctor
// 
//-----------------------------------------------------------------------------

function Perforce( serverURL, serverPort, clientSpec, userName, password )
{
	//
	// check parameters
	//
	if( arguments.length < 5 )
		throw( 'Bad argument list' );
		
	for( var i=0; i<5; i++ )
	{
		if( typeof( arguments[i] ) == 'undefined' || arguments[i] == null )
			throw( 'Bad argument list' );
	}
	
	//
	// get path for Perforce application
	//
	if( PerforceFindApp() == null )
		throw( 'Perforce application not found' );
	
	//
	// store values
	//
	this.serverURL	= serverURL.strippWS();
	this.serverPort	= serverPort.strippWS();
	this.clientSpec	= clientSpec.strippWS();
	this.userName	= userName.strippWS();
	this.password	= password.strippWS();
	
	this.p4App		= PerforceApplicationPath;
	
	var pos0 = this.serverURL.indexOf( '/' );
	
	if( pos0 >= 0 )
		this.serverURL = this.serverURL.slice( 0, pos0 );
		
	this.lastResult = null;
	
	//
	// create global parameter block
	//
	this.globalParam = '';
	
	if( this.clientSpec.length > 0 )
		this.globalParam = '-c' + this.clientSpec;

	this.globalParam += ' -p' + this.serverURL + ':' + this.serverPort + ' ' + '-u' + this.userName;
		
	if( this.password.length > 0 )
		this.globalParam  += ' -P' + this.password;
	
	this.localRoot = '';
	this.filemapping = new Array();
	
	if( this.client( '-o' ) )
	{
		if( this.lastResult.output.indexOf( 'Unicode clients require a unicode enabled server.' ) >= 0 )
		{
			this.globalParam += ' -Cutf8';
			this.client( '-o' )
		}
	
		var lines = this.lastResult.output.split( '\r' );
		
		//
		// get local root url from client spec
		//
		for( var i=0; i<lines.length; i++ )
		{
			// filter comment lines
			if( lines[i].toString().strippWS()[0] != '#' )
			{
				var pos0 = lines[i].toString().indexOf( 'Root:' );
				
				if( pos0 >= 0 )
				{
					var tmp = lines[i].toString().slice( 6 );
					var rootFile = new JSXFile( tmp.strippWS() );
					this.localRoot = rootFile.absurl;
					break;
				}
			}
		}

		//
		// file mapping ( server - local )
		//
		for( var i=0; i<lines.length; i++ )
		{
			// filter comment lines
			if( lines[i].toString().strippWS()[0] != '#' )
			{
				if( lines[i].toString().indexOf( 'View:' ) >= 0 )
				{
					for( var j=i+1; j<lines.length; j++ )
					{
						var entries = lines[j].toString().split( ' ' );
						
						if( entries.length >= 2 )
						{
							var map = new Object;
							map.serverURL = entries[0].toString().strippWS();
							map.localURL  = entries[1].toString().strippWS();
							
							var pos0 = map.serverURL.indexOf( '...' );
							
							if( pos0 >= 0 )
								map.serverURL = map.serverURL.slice( 0, pos0 );
								
							while( map.localURL[0] == '/' )
								map.localURL = map.localURL.slice( 1 );
								
							if( map.localURL.indexOf( this.clientSpec ) == 0 )
							{
								map.localURL = map.localURL.slice( this.clientSpec.length );
								map.localURL = this.localRoot + map.localURL;
							}

							var pos0 = map.localURL.indexOf( '...' );
							
							if( pos0 >= 0 )
								map.localURL = map.localURL.slice( 0, pos0 );
								
							this.filemapping.push( map );
						}
					}
					
					break;
				}
			}
		}
	}
	else
		throw( "No connection" );
		
	this.usermapp = new Array();
	
	if( this.users() )
	{
		var users = this.lastResult.output.split( '\r' );
		
		for( var i=0; i<users.length; i++ )
		{
			var user = new Object();
			var entry = users[i].split( ' ' );
			
			if( entry.length >= 3 )
			{
				user.name = entry[0].strippWS();
				user.mail = entry[1].strippWS();

				if( user.mail[0] == '<' )
					user.mail = user.mail.slice(1);
					
				if( user.mail[user.mail.length-1] = '>' )
					user.mail = user.mail.slice( 0, user.mail.length-1 );

				user.realname = entry[2].strippWS();

				if( user.realname[0] == '(' )
					user.realname = user.realname.slice(1);

				var index = 3;
				
				while( index < entry.length && user.realname[user.realname.length-1] != ')' )
				{
					user.realname += ' ' + entry[index].strippWS();
					index++;
				}
					
				if( user.realname[user.realname.length-1] == ')' )
					user.realname = user.realname.slice( 0, user.realname.length-1 );
					
				this.usermapp.push( user );
			}
		}
	}
		
	this.lastResult = null;
	this.lastCommand = '';		// for debugging issues
}

///////////////////////////////////////////////////////////////////////////////
//
// Perforce interface
//

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.sync(...)
// 
// Purpose: p4 sync - param url#revision
// 
//-----------------------------------------------------------------------------

Perforce.prototype.sync = function( url, revision, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		var revisionStr = '';
		
		if( typeof( param ) == 'string' )		paramStr = param + ' ';
		if( typeof( revision ) == 'string' && revision.length > 0 )	revisionStr = '#' + revision;
			
		var urlStr = this.mapp2Server( url );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' sync ' + paramStr + '"' + urlStr + revisionStr + '"';

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.edit(...)
// 
// Purpose: p4 edit -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.edit = function( url, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		var urlStr = this.mapp2Server( url, true );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' edit ' + paramStr + urlStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.lock(...)
// 
// Purpose: p4 lock -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.lock = function( url, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		var urlStr = this.mapp2Server( url, true );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' lock ' + paramStr + urlStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.unlock(...)
// 
// Purpose: p4 unlock -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.unlock = function( url, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		var urlStr = this.mapp2Server( url, true );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' unlock ' + paramStr + urlStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;

	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}
//-----------------------------------------------------------------------------
// 
// Perforce.prototype.resolve(...)
// 
// Purpose: p4 resolve -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.resolve = function( url, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		var urlStr = this.mapp2Server( url, true );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' resolve ' + paramStr + urlStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.submit(...)
// 
// Purpose: p4 submit -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.submit = function( url, comment, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		var commentStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
		if( typeof( comment ) == 'string' )	commentStr = comment;


		var urlStrSpec	= this.mapp2Server( url );
		var urlStr	= this.mapp2Server( url, true, false );
		var spec = this.createSpec( urlStrSpec, commentStr );

		this.lastCommand = this.p4App + ' ' + this.globalParam + ' submit -i ' + paramStr + urlStr;

		this.lastResult = command( this.lastCommand, spec, true );

		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.fstat(...)
// 
// Purpose: p4 fstat -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.fstat = function( url, param, folder )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		var folderAdd = folder;
		
		if( typeof( param ) == 'string' )			paramStr = param + ' ';
		if( typeof( folderAdd ) == 'undefined' )	folderAdd = false;
			
		var urlStr = this.mapp2Server( url, true );
		
		if( folderAdd )
		{
			urlStr = urlStr.slice( 0, urlStr.length-1 );
			urlStr += '*"';
		}
		
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' fstat ' + paramStr + urlStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.opened(...)
// 
// Purpose: p4 opened -param
// 
//-----------------------------------------------------------------------------

Perforce.prototype.opened = function( param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' opened ' + paramStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.revert(...)
// 
// Purpose: p4 revert -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.revert = function( url, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		var urlStr = this.mapp2Server( url, true );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' revert ' + paramStr + urlStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.add(...)
// 
// Purpose: p4 add -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.add = function( url, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		var urlStr = this.mapp2Server( url, true );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' add ' + paramStr + urlStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.remove(...)
// 
// Purpose: p4 delete -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.remove = function( url, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		var urlStr = this.mapp2Server( url, true );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' delete ' + paramStr + urlStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.integrate(...)
// 
// Purpose: p4 integrate -param urlFrom urlTo
// 
//-----------------------------------------------------------------------------

Perforce.prototype.integrate = function( urlFrom, urlTo, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		var urlFromStr	= this.mapp2Server( urlFrom, true );
		var urlToStr	= this.mapp2Server( urlTo, true );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' integrate ' + paramStr + urlFromStr + ' ' + urlToStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.dirs(...)
// 
// Purpose: p4 dirs -param url/*
// 
//-----------------------------------------------------------------------------

Perforce.prototype.dirs = function( url, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		var urlStr = this.mapp2Server( url );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' dirs ' + paramStr + '"' + urlStr + '*"';

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.filelog(...)
// 
// Purpose: p4 filelog -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.filelog = function( url, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		var urlStr = this.mapp2Server( url, true );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' filelog ' + paramStr + urlStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.print(...)
// 
// Purpose: p4 print -param url
// 
//-----------------------------------------------------------------------------

Perforce.prototype.print = function( url, revision, param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		var revisionStr = '';
		
		if( typeof( param ) == 'string' )		paramStr = param + ' ';
		if( typeof( revision ) == 'string' && revision.length > 0 )	revisionStr = '#' + revision;
			
		var urlStr = this.mapp2Server( url );
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' print ' + paramStr + '"' + urlStr + revisionStr + '"';

		this.lastResult = command( this.lastCommand );
	
		ret = ( this.lastResult.exit == 0 ) && ( this.lastResult.output.length > 0 );
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.client(...)
// 
// Purpose: p4 client -param
// 
//-----------------------------------------------------------------------------

Perforce.prototype.client = function( param )
{
	var ret = false;
	
	try
	{
		var paramStr = '';
		
		if( typeof( param ) == 'string' )	paramStr = param + ' ';
			
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' client ' + paramStr;

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.client(...)
// 
// Purpose: p4 client -param
// 
//-----------------------------------------------------------------------------

Perforce.prototype.clients = function()
{
	var ret = false;
	
	try
	{
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' clients';

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.users(...)
// 
// Purpose: p4 users
// 
//-----------------------------------------------------------------------------

Perforce.prototype.users = function()
{
	var ret = false;
	
	try
	{
		this.lastCommand = this.p4App + ' ' + this.globalParam + ' users';

		this.lastResult = command( this.lastCommand );
	
		ret =  this.lastResult.exit == 0;
	}
	catch( exp )
	{
		ret = false;
	}
	
	return ret;
}

///////////////////////////////////////////////////////////////////////////////
//
// utils

//

//-----------------------------------------------------------------------------
// 
// Perforce.prototype.createSpec(...)
// 
// Purpose: create specification for submit operation
// 
//-----------------------------------------------------------------------------
Perforce.prototype.createSpec = function( urlStr, commentStr )
{
	var specStr = '';
	
	var comment = commentStr;
	
	if( comment.length <= 0 )
		comment = 'No comment';
		
	specStr += 'Change:\tnew\n';
	specStr += 'Client:\t' + this.clientSpec + '\n';
	specStr += 'User:\t' + this.userName + '\n';
	specStr += 'Status:\tnew' + '\n';
	specStr += 'Description:' + '\n';
	specStr += '\t' + comment + '\n';
	specStr += 'Files:' + '\n';
	specStr += '\t' + urlStr + '\n';

	return specStr;
}


//-----------------------------------------------------------------------------
// 
// function(...)
// 
// Purpose: map server URL to local URL
// 
//-----------------------------------------------------------------------------
Perforce.prototype.mapp2Local = function( url )
{
	if( typeof( url ) != 'string' )
		throw( 'Bad argument list ' );

	var ret = url.strippWS();
	
	for( var i=0; i<this.filemapping.length; i++ )
	{
		ret = ret.replace( /file:\/\/\//ig, 'file://' );
		var map = this.filemapping[i].serverURL.replace( /file:\/\/\//ig, 'file://' );
		
		var pos0 = ret.indexOf( map );
		
		if( pos0 >= 0 )
		{
			ret = ret.slice( pos0 + map.length );
			ret = this.filemapping[i].localURL + ret;
		}
	}
	
	ret = ret.strippWS();
	
	return ret;
}


//-----------------------------------------------------------------------------
// 
// function(...)
// 
// Purpose: map local URL to server URL
// 
//-----------------------------------------------------------------------------
Perforce.prototype.mapp2Server = function( url, withBrackets, encode )
{

	if( typeof( url ) == 'undefined' || url == null )
		throw( 'Bad argument list ' );
		
	var addBrackets = withBrackets;
	
	if( typeof( addBrackets ) != 'boolean' )
		addBrackets = false;
		
	var decodeURL = encode;
	
	if( typeof( decodeURL ) != 'boolean' )
		decodeURL = true;
		
	var urlStr = url;
	if( typeof( urlStr ) != 'string' )
	{
		//
		// if not a string then it SHOULD be a JSXFile or JSXSiteReference
		//
		urlStr = urlStr.absurl;
	}

	urlStr = urlStr.replace( /file:\/\/\//ig, 'file://' );
	var tmp = urlStr.toLowerCase();

	for( var i=0; i<this.filemapping.length; i++ )
	{
		var map = this.filemapping[i].localURL.toLowerCase().replace( /file:\/\/\//ig, 'file://' );
		
		var pos0 = tmp.indexOf( map );
		
		if( pos0 >= 0 )
		{
			urlStr = urlStr.slice( pos0 + map.length );
			urlStr = this.filemapping[i].serverURL + urlStr;
			break;
		}
	}

	urlStr = urlStr.strippWS();
	
	if( decodeURL )
		urlStr = decodeURI( urlStr );
		
	if( addBrackets && urlStr.length > 0 )
		urlStr = '"' + urlStr +	 '"';
		
	return urlStr;
}

//-----------------------------------------------------------------------------
// 
// function PerforceFindApp(...)
// 
// Purpose: [global] find Perforce application file
// 
//-----------------------------------------------------------------------------

function PerforceFindApp()
{
	if( PerforceApplicationPath == null )
	{
		if( typeof( prefs.PerforceApplicationPath ) == 'string' )
		{
			PerforceApplicationPath = prefs.PerforceApplicationPath;
		}
		else
		{
			var mac = ( app.osVersion.indexOf( 'Macintosh' ) >= 0 );
			var del, ext;
			
			if( mac )
			{
				del = ':';
				ext = '';
			}
			else
			{
				del = ';';
				ext = '.exe';
			}
				
			var envPATH = $.getenv( 'PATH' );
			var path = envPATH.split( del );
			
			for( var i=0; i<path.length; i++ )
			{
				var pathFile = new JSXFile( path[i].toString() )
				
				if( pathFile.exists )
				{
					var p4File = new JSXFile( pathFile.absurl + '/p4' + ext );
					
					if( p4File.exists )
					{
						if( mac && !settings.sdk.posix )
						{
							PerforceApplicationPath = p4File.absurl;
							var pos0 = PerforceApplicationPath.indexOf( 'file:' );
							
							if( pos0 >= 0 )
								PerforceApplicationPath = PerforceApplicationPath.slice( pos0 + 5 );
								
							while( PerforceApplicationPath[0] = '/' )
								PerforceApplicationPath = PerforceApplicationPath.slice( 1 );
						}
						else
							PerforceApplicationPath = p4File.abspath;
							
						prefs.PerforceApplicationPath = PerforceApplicationPath;
						
						break;
					}
				}
			}
		}
	}	
	
	return PerforceApplicationPath;
}