/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_idl.hxx"

#include <stdlib.h>
#include <stdio.h>
#include <database.hxx>
#include <globals.hxx>
#include <command.hxx>
#include <tools/fsys.hxx>
#include <tools/string.hxx>

#define BR 0x8000
sal_Bool FileMove_Impl( const String & rFile1, const String & rFile2, sal_Bool bImmerVerschieben )
{
	//printf( "Move from %s to %s\n", rFile2.GetStr(), rFile1.GetStr() );
	sal_uLong nC1 = 0;
	sal_uLong nC2 = 1;
	if( !bImmerVerschieben )
	{
		SvFileStream aOutStm1( rFile1, STREAM_STD_READ );
		SvFileStream aOutStm2( rFile2, STREAM_STD_READ );
		if( aOutStm1.GetError() == SVSTREAM_OK )
		{
			sal_uInt8 * pBuf1 = new sal_uInt8[ BR ];
			sal_uInt8 * pBuf2 = new sal_uInt8[ BR ];
			nC1 = aOutStm1.Read( pBuf1, BR );
			nC2 = aOutStm2.Read( pBuf2, BR );
			while( nC1 == nC2 )
			{
				if( memcmp( pBuf1, pBuf2, nC1 ) )
				{
					nC1++;
					break;
				}
				else
				{
					if( 0x8000 != nC1 )
						break;
					nC1 = aOutStm1.Read( pBuf1, BR );
					nC2 = aOutStm2.Read( pBuf2, BR );
				}
			}
			delete[] pBuf1;
			delete[] pBuf2;
		}
	}
	DirEntry aF2( rFile2 );
	if( nC1 != nC2 )
	{// es hat sich etwas geaendert
		DirEntry aF1( rFile1 );
		aF1.Kill();
		// Datei verschieben
		if( aF2.MoveTo( aF1 ) )
		{
			// Beide Dateien loeschen
			aF1.Kill();
			aF2.Kill();
			return sal_False;
		}
/*
		else
		{
			printf( "%s to %s moved\n",
					 rFile2.GetStr(), rFile1.GetStr() );
		}
*/
		return sal_True;
	}
	return 0 == aF2.Kill();
}

/*************************************************************************
|*	  main()
|*
|*	  Beschreibung
*************************************************************************/
#if defined( UNX ) || (defined( PM2 ) && defined( CSET )) || defined (WTC) || defined (MTW) || defined (__MINGW32__) || defined( OS2 )
int main ( int argc, char ** argv)
{
#else
int cdecl main ( int argc, char ** argv)
{
#endif

/*
    pStr = ::ResponseFile( &aCmdLine, argv, argc );
	if( pStr )
	{
		printf( "Cannot open response file <%s>\n", pStr );
		return( 1 );
	};
*/

    String aTmpListFile;
    String aTmpSlotMapFile;
    String aTmpSfxItemFile;
    String aTmpDataBaseFile;
    String aTmpCallingFile;
    String aTmpSrcFile;
    String aTmpCxxFile;
    String aTmpHxxFile;
    String aTmpHelpIdFile;
    String aTmpCSVFile;
    String aTmpDocuFile;

	SvCommand aCommand( argc, argv );

    if( aCommand.nVerbosity != 0 )
        printf( "StarView Interface Definition Language (IDL) Compiler 3.0\n" );

	Init();
	SvIdlWorkingBase * pDataBase = new SvIdlWorkingBase(aCommand);

	int nExit = 0;
	if( aCommand.aExportFile.Len() )
	{
		DirEntry aDE( aCommand.aExportFile );
		pDataBase->SetExportFile( aDE.GetName() );
	}

	if( ReadIdl( pDataBase, aCommand ) )
	{
		if( nExit == 0 && aCommand.aDocuFile.Len() )
		{
			DirEntry aDE( aCommand.aDocuFile );
			aDE.ToAbs();
			aTmpDocuFile = aDE.GetPath().TempName().GetFull();
			SvFileStream aOutStm( aTmpDocuFile, STREAM_READWRITE | STREAM_TRUNC );
			if( !pDataBase->WriteDocumentation( aOutStm ) )
			{
				nExit = -1;
				ByteString aStr = "cannot write documentation file: ";
                aStr += ByteString( aCommand.aDocuFile, RTL_TEXTENCODING_UTF8 );
                fprintf( stderr, "%s\n", aStr.GetBuffer() );
			}
		}
		if( nExit == 0 && aCommand.aListFile.Len() )
		{
			DirEntry aDE( aCommand.aListFile );
			aDE.ToAbs();
			aTmpListFile = aDE.GetPath().TempName().GetFull();
			SvFileStream aOutStm( aTmpListFile, STREAM_READWRITE | STREAM_TRUNC );
			if( !pDataBase->WriteSvIdl( aOutStm ) )
			{
				nExit = -1;
				ByteString aStr = "cannot write list file: ";
                aStr += ByteString( aCommand.aListFile, RTL_TEXTENCODING_UTF8 );
                fprintf( stderr, "%s\n", aStr.GetBuffer() );
			}
		}
		if( nExit == 0 && aCommand.aSlotMapFile.Len() )
		{
			DirEntry aDE( aCommand.aSlotMapFile );
			aDE.ToAbs();
			aTmpSlotMapFile = aDE.GetPath().TempName().GetFull();
			SvFileStream aOutStm( aTmpSlotMapFile, STREAM_READWRITE | STREAM_TRUNC );
			if( !pDataBase->WriteSfx( aOutStm ) )
			{
				nExit = -1;
				ByteString aStr = "cannot write slotmap file: ";
                aStr += ByteString( aCommand.aSlotMapFile, RTL_TEXTENCODING_UTF8 );
                fprintf( stderr, "%s\n", aStr.GetBuffer() );
			}
		}
		if( nExit == 0 && aCommand.aHelpIdFile.Len() )
		{
			DirEntry aDE( aCommand.aHelpIdFile );
			aDE.ToAbs();
			aTmpHelpIdFile = aDE.GetPath().TempName().GetFull();
			SvFileStream aStm( aTmpHelpIdFile, STREAM_READWRITE | STREAM_TRUNC );
			if (!pDataBase->WriteHelpIds( aStm ) )
			{
				nExit = -1;
				ByteString aStr = "cannot write help ID file: ";
                aStr += ByteString( aCommand.aHelpIdFile, RTL_TEXTENCODING_UTF8 );
                fprintf( stderr, "%s\n", aStr.GetBuffer() );
			}
		}
		if( nExit == 0 && aCommand.aCSVFile.Len() )
		{
			DirEntry aDE( aCommand.aCSVFile );
			aDE.ToAbs();
			aTmpCSVFile = aDE.GetPath().TempName().GetFull();
			SvFileStream aStm( aTmpCSVFile, STREAM_READWRITE | STREAM_TRUNC );
			if (!pDataBase->WriteCSV( aStm ) )
			{
				nExit = -1;
				ByteString aStr = "cannot write CSV file: ";
                aStr += ByteString( aCommand.aCSVFile, RTL_TEXTENCODING_UTF8 );
                fprintf( stderr, "%s\n", aStr.GetBuffer() );
			}
		}
		if( nExit == 0 && aCommand.aSfxItemFile.Len() )
		{
			DirEntry aDE( aCommand.aSfxItemFile );
			aDE.ToAbs();
			aTmpSfxItemFile = aDE.GetPath().TempName().GetFull();
			SvFileStream aOutStm( aTmpSfxItemFile, STREAM_READWRITE | STREAM_TRUNC );
			if( !pDataBase->WriteSfxItem( aOutStm ) )
			{
				nExit = -1;
				ByteString aStr = "cannot write item file: ";
                aStr += ByteString( aCommand.aSfxItemFile, RTL_TEXTENCODING_UTF8 );
                fprintf( stderr, "%s\n", aStr.GetBuffer() );
			}
		}
		if( nExit == 0 && aCommand.aDataBaseFile.Len() )
		{
			DirEntry aDE( aCommand.aDataBaseFile );
			aDE.ToAbs();
			aTmpDataBaseFile = aDE.GetPath().TempName().GetFull();
			SvFileStream aOutStm( aTmpDataBaseFile, STREAM_READWRITE | STREAM_TRUNC );
			pDataBase->Save( aOutStm, aCommand.nFlags );
			if( aOutStm.GetError() != SVSTREAM_OK )
			{
				nExit = -1;
				ByteString aStr = "cannot write database file: ";
                aStr += ByteString( aCommand.aDataBaseFile, RTL_TEXTENCODING_UTF8 );
                fprintf( stderr, "%s\n", aStr.GetBuffer() );
			}
		}
/*
		if( nExit == 0 && aCommand.aCallingFile.Len() )
		{
			DirEntry aDE( aCommand.aCallingFile );
			aDE.ToAbs();
			aTmpCallingFile = aDE.GetPath().TempName().GetFull();
			SvFileStream aOutStm( aTmpCallingFile, STREAM_READWRITE | STREAM_TRUNC );
			pDataBase->WriteSbx( aOutStm );
			//pDataBase->Save( aOutStm, aCommand.nFlags | IDL_WRITE_CALLING );
			if( aOutStm.GetError() != SVSTREAM_OK )
			{
				nExit = -1;
				ByteString aStr = "cannot write calling file: ";
				aStr += aCommand.aCallingFile;
				fprintf( stderr, "%s\n", aStr.GetStr() );
			}
		}
		if( nExit == 0 && aCommand.aCxxFile.Len() )
		{
			DirEntry aDE( aCommand.aCxxFile );
			aDE.ToAbs();
			aTmpCxxFile = aDE.GetPath().TempName().GetFull();
			SvFileStream aOutStm( aTmpCxxFile, STREAM_READWRITE | STREAM_TRUNC );

			aOutStm << "#pragma hdrstop" << endl;
			aOutStm << "#include <";
			if( aCommand.aHxxFile.Len() )
                aOutStm << DirEntry(aCommand.aHxxFile).GetName().GetBuffer();
			else
			{
				DirEntry aDE( aCommand.aCxxFile );
				aDE.SetExtension( "hxx" );
                aOutStm << aDE.GetName().GetBuffer);
			}
			aOutStm << '>' << endl;
			if( !pDataBase->WriteCxx( aOutStm ) )
			{
				nExit = -1;
				ByteString aStr = "cannot write cxx file: ";
                aStr += ByteString( aCommand.aCxxFile, RTL_TEXTENCODING_UTF8 );
                fprintf( stderr, "%s\n", aStr.GetBuffer() );
			}
		}
		if( nExit == 0 && aCommand.aHxxFile.Len() )
		{
			DirEntry aDE( aCommand.aHxxFile );
			aDE.ToAbs();
			aTmpHxxFile = aDE.GetPath().TempName().GetFull();
			SvFileStream aOutStm( aTmpHxxFile, STREAM_READWRITE | STREAM_TRUNC );

			aOutStm << "#include <somisc.hxx>" << endl;
			if( !pDataBase->WriteHxx( aOutStm ) )
			{
				nExit = -1;
				ByteString aStr = "cannot write cxx file: ";
                aStr += ByteString( aCommand.aHxxFile, RTL_TEXTENCODING_UTF8 );
                fprintf( stderr, "%s\n", aStr.GetBuffer() );
			}
		}
 */
	}
	else
		nExit = -1;

	if( nExit == 0 )
	{
		sal_Bool bErr = sal_False;
		sal_Bool bDoMove = aCommand.aTargetFile.Len() == 0;
		String aErrFile, aErrFile2;
		if( !bErr && aCommand.aListFile.Len() )
		{
			bErr |= !FileMove_Impl( aCommand.aListFile, aTmpListFile, bDoMove );
			if( bErr ) {
				aErrFile = aCommand.aListFile;
				aErrFile2 = aTmpListFile;
			}
		}
		if( !bErr && aCommand.aSlotMapFile.Len() )
		{
			bErr |= !FileMove_Impl( aCommand.aSlotMapFile, aTmpSlotMapFile, bDoMove );
			if( bErr ) {
				aErrFile = aCommand.aSlotMapFile;
				aErrFile2 = aTmpSlotMapFile;
			}
		}
		if( !bErr && aCommand.aSfxItemFile.Len() )
		{
			bErr |= !FileMove_Impl( aCommand.aSfxItemFile, aTmpSfxItemFile, bDoMove );
			if( bErr ) {
				aErrFile = aCommand.aSfxItemFile;
				aErrFile2 = aTmpSfxItemFile;
			}
		}
		if( !bErr && aCommand.aDataBaseFile.Len() )
		{
			bErr |= !FileMove_Impl( aCommand.aDataBaseFile, aTmpDataBaseFile, bDoMove );
			if( bErr ) {
				aErrFile = aCommand.aDataBaseFile;
				aErrFile2 = aTmpDataBaseFile;
			}
		}
		if( !bErr && aCommand.aCallingFile.Len() )
		{
			bErr |= !FileMove_Impl( aCommand.aCallingFile, aTmpCallingFile, bDoMove );
			if( bErr ) {
				aErrFile = aCommand.aCallingFile;
				aErrFile2 = aTmpCallingFile;
			}
		}
		if( !bErr && aCommand.aCxxFile.Len() )
		{
			bErr |= !FileMove_Impl( aCommand.aCxxFile, aTmpCxxFile, bDoMove );
			if( bErr ) {
				aErrFile = aCommand.aCxxFile;
				aErrFile2 = aTmpCxxFile;
			}
		}
		if( !bErr && aCommand.aHxxFile.Len() )
		{
			bErr |= !FileMove_Impl( aCommand.aHxxFile, aTmpHxxFile, bDoMove );
			if( bErr ) {
				aErrFile = aCommand.aHxxFile;
				aErrFile2 = aTmpHxxFile;
			}
		}
		if( !bErr && aCommand.aHelpIdFile.Len() )
		{
			bErr |= !FileMove_Impl( aCommand.aHelpIdFile, aTmpHelpIdFile, bDoMove );
			if( bErr ) {
				aErrFile = aCommand.aHelpIdFile;
				aErrFile2 = aTmpHelpIdFile;
			}
		}
		if( !bErr && aCommand.aCSVFile.Len() )
		{
			bErr |= !FileMove_Impl( aCommand.aCSVFile, aTmpCSVFile, bDoMove );
			if( bErr ) {
				aErrFile = aCommand.aCSVFile;
				aErrFile2 = aTmpCSVFile;
			}
		}
		if( !bErr && aCommand.aDocuFile.Len() )
		{
			bErr |= !FileMove_Impl( aCommand.aDocuFile, aTmpDocuFile, bDoMove );
			if( bErr ) {
				aErrFile = aCommand.aDocuFile;
				aErrFile2 = aTmpDocuFile;
			}
		}

		if( bErr )
		{
			nExit = -1;
			ByteString aStr = "cannot move file from: ";
            aStr += ByteString( aErrFile2, RTL_TEXTENCODING_UTF8 );
            aStr += "\n              to file: ";
            aStr += ByteString( aErrFile, RTL_TEXTENCODING_UTF8 );
            fprintf( stderr, "%s\n", aStr.GetBuffer() );
		}
		else
		{
			if( aCommand.aTargetFile.Len() )
			{
#ifdef ICC
				DirEntry aT(aCommand.aTargetFile);
				aT.Kill();
#endif
				// Datei stempeln, da idl korrekt durchlaufen wurde
				SvFileStream aOutStm( aCommand.aTargetFile,
								STREAM_READWRITE | STREAM_TRUNC );
			}
		}
	}

	if( nExit != 0 )
	{
		if( aCommand.aListFile.Len() )
			DirEntry( aTmpListFile ).Kill();
		if( aCommand.aSlotMapFile.Len() )
			DirEntry( aTmpSlotMapFile ).Kill();
		if( aCommand.aSfxItemFile.Len() )
			DirEntry( aTmpSfxItemFile ).Kill();
		if( aCommand.aDataBaseFile.Len() )
			DirEntry( aTmpDataBaseFile ).Kill();
		if( aCommand.aCallingFile.Len() )
			DirEntry( aTmpCallingFile ).Kill();
		if( aCommand.aCxxFile.Len() )
			DirEntry( aTmpCxxFile ).Kill();
		if( aCommand.aHxxFile.Len() )
			DirEntry( aTmpHxxFile ).Kill();
	}

	delete pDataBase;
	DeInit();
	if( nExit != 0 )
		fprintf( stderr, "svidl terminated with errors\n" );
	return nExit;
}

