//
// Copyright 1997 Nicholas J. Irias.  All rights reserved.
//
//

// Cmd_Get.cpp

#include "stdafx.h"
#include "p4win.h"
#include "cmd_get.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


IMPLEMENT_DYNCREATE(CCmd_Get, CP4Command)


CCmd_Get::CCmd_Get(CGuiClient *client) : CP4Command(client)
{
	m_ReplyMsg= WM_P4GET;
	m_TaskName= _T("Sync");
	m_OutputRows= m_AddCount= 0;
	m_bIntegAfterSync = FALSE;
	m_bOpenAfterSync = FALSE;
	m_bOpeningForEdit = FALSE;
	m_RevHistWnd = 0;
	m_RevReq = 0;
}

BOOL CCmd_Get::Run(CStringList *files, BOOL whatIf, BOOL bRefresh )
{
	ASSERT(!files || !files->IsEmpty());

	m_Warnings.RemoveAll();
	m_OutputRows= 0;

	m_WhatIf= whatIf;

	// Set the base of arg list
	ClearArgs();
	m_BaseArgs=AddArg(_T("sync"));
	
	if(whatIf)
		m_BaseArgs=AddArg(_T("-n"));
	if ( bRefresh )
		m_BaseArgs = AddArg( _T("-f") );
	
	if (files)
	{
		m_posStrListIn=files->GetHeadPosition();
		m_pStrListIn=files;  
		
		// Put the first few files into the arg list
		NextListArgs();
	}
		
	return CP4Command::Run();
}

void CCmd_Get::OnOutputInfo(char level, LPCTSTR data, LPCTSTR msg)
{
	CString prefix;

	m_OutputRows++;

	if(m_WhatIf)
		prefix = LoadStringResource(IDS_SYNC_PREVIEW);
	
	
    // When getting an open file at an earlier rev, the message is as follows:
    // I'm still not certain why you would want to do the get, but it IS
    // possible.  The server resonse looks like one of the following:
    // //xxxx/a/cow/spion/swine/q.txt#1 - is opened at a later revision - not changed
    // //xxxx/a/cow/spion/swine/q.txt#2 - is opened
    if(StrStr(data,_T(" - is opened")) &&
       !StrStr(data,_T(" - is opened for edit and can't be ")) &&
       !StrStr(data,_T(" - is opened for add and can't be ")) &&
       !StrStr(data,_T(" - is opened for delete and can't be ")) &&
       !StrStr(data,_T(" - is opened at a later revision - not changed")) )
   	{
		TheApp()->StatusAdd(prefix+msg);
		m_GetList.AddHead(data);
	}
	else if(StrStr(data, _T(" - updating")))
	{
		TheApp()->StatusAdd(prefix+msg);
		m_GetList.AddHead(data);
	}
	else if(StrStr(data, _T(" - added as")))
	{
		TheApp()->StatusAdd(prefix+msg);
		m_GetList.AddHead(data);
		m_AddCount++;
	}
    else if(StrStr(data, _T(" - refreshing")))
    {
		TheApp()->StatusAdd(msg);
        m_GetList.AddHead(data);
    }
	else if(StrStr(data, _T(" - deleted as")))
	{
		TheApp()->StatusAdd(prefix+msg);
		m_RemoveList.AddHead(data);
	}
	else
	{
		// Must be some sort of warning, so add it to the warning 
		// summary
		m_Warnings.Add( msg );
		CP4Command::OnOutputInfo(level, data, msg);
	}
}


void CCmd_Get::OnOutputError(char level, LPCTSTR errBuf, LPCTSTR errMsg)
{
	CString txt(errBuf);
	CString msg(errMsg);

	if (( txt.Find( _T("Perforce password") ) > -1 ) 
	 || ( txt.Find( _T("please login") ) > -1 ))
	{
		SET_PWD_ERROR(TRUE);
        TheApp()->StatusAdd( msg, SV_WARNING );
		m_ErrorTxt= LoadStringResource(IDS_OPERATION_CANNOT_COMPLETED_BECAUSE_BAD_PASSWORD);
        m_FatalError=TRUE;
		return;
	}

	m_OutputRows++;

	if(txt.Find(/*F or f*/_T("ile(s) up-to-date"))>=0)
		TheApp()->StatusAdd(msg);  // Not really an error
	else if ((IsRunIntegAfterSync()) && (txt.Find(_T("no such file"))>=0))
		;										// Not really an error if sync for integ
	else if(txt.Find(_T("Can't clobber writeable file")) >=0 ||
	   txt.Find(_T("can't create directory for")) >=0 ||
	   txt.Find(_T("filename, directory name, or volume label syntax is incorrect")) >=0 )
	{
		// Must be some sort of warning, so add it to the warning 
		// summary
		m_Warnings.Add( msg );
		TheApp()->StatusAdd(msg, SV_WARNING);  // Not really an error
		RemoveLastFromGetList();
	}
	else
	{
		// Must be some sort of warning, so add it to the warning 
		// summary
		m_Warnings.Add( msg );
		TheApp()->StatusAdd(msg, SV_WARNING);
	}
}

int CCmd_Get::ReiterateWarnings()
{
	int i;

	if( (i = m_Warnings.GetSize()) > 0 )
	{
		TheApp()->StatusAdd(_T("SYNC OPERATION WARNING SUMMARY:"), SV_WARNSUMMARY);

		for( int i=0; i < m_Warnings.GetSize(); i++ )
		{
			TheApp()->StatusAdd( m_Warnings.GetAt( i ), SV_WARNING );
		}
	
		CString summary;
		summary.Format(_T("Total of %d warnings reported"), m_Warnings.GetSize());
		TheApp()->StatusAdd( summary, SV_WARNSUMMARY );
	}
	else
	{
		TheApp()->StatusAdd(_T("Sync completed with no warnings or errors"), SV_COMPLETION);
	}
	return(i);
}


// A wacky kludge:
// If a get fails due to noclobber flag, the server will first 
// indicate a successfull get, and then recant this later when it
// sees the error, so we need to a way to remove the last item 
// from the get list
void CCmd_Get::RemoveLastFromGetList()
{
	ASSERT(!m_GetList.IsEmpty());

	if(!m_GetList.IsEmpty())
		m_GetList.RemoveHead();
}