/**************************************************************
 * 
 * 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_lingucomponent.hxx"
#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>

#include <com/sun/star/linguistic2/SpellFailure.hpp>
#include <cppuhelper/factory.hxx>	// helper for factories
#include <com/sun/star/registry/XRegistryKey.hpp>
#include <tools/debug.hxx>
#include <unotools/processfactory.hxx>
#include <osl/mutex.hxx>

#include <macspellimp.hxx>

#include <linguistic/spelldta.hxx>
#include <unotools/pathoptions.hxx>
#include <unotools/useroptions.hxx>
#include <osl/file.hxx>
#include <rtl/ustrbuf.hxx>


using namespace utl;
using namespace osl;
using namespace rtl;
using namespace com::sun::star;
using namespace com::sun::star::beans;
using namespace com::sun::star::lang;
using namespace com::sun::star::uno;
using namespace com::sun::star::linguistic2;
using namespace linguistic;

MacSpellChecker::MacSpellChecker() :
	aEvtListeners	( GetLinguMutex() )
{
	aDEncs = NULL;
	aDLocs = NULL;
	aDNames = NULL;
	bDisposing = sal_False;
	pPropHelper = NULL;
    numdict = 0;
    NSApplicationLoad();
	NSAutoreleasePool* pool	= [[NSAutoreleasePool alloc] init];
    macSpell = [NSSpellChecker sharedSpellChecker];
    macTag = [NSSpellChecker uniqueSpellDocumentTag];
    [pool release];
}


MacSpellChecker::~MacSpellChecker()
{
  numdict = 0;
  if (aDEncs) delete[] aDEncs;
  aDEncs = NULL;
  if (aDLocs) delete[] aDLocs;
  aDLocs = NULL;
  if (aDNames) delete[] aDNames;
  aDNames = NULL;
  if (pPropHelper)
	 pPropHelper->RemoveAsPropListener();
}


PropertyHelper_Spell & MacSpellChecker::GetPropHelper_Impl()
{
	if (!pPropHelper)
	{
		Reference< XPropertySet	>	xPropSet( GetLinguProperties(), UNO_QUERY );

		pPropHelper	= new PropertyHelper_Spell( (XSpellChecker *) this, xPropSet );
		xPropHelper = pPropHelper;
		pPropHelper->AddAsPropListener();	//! after a reference is established
	}
	return *pPropHelper;
}


Sequence< Locale > SAL_CALL MacSpellChecker::getLocales()
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

        // this routine should return the locales supported by the installed
        // dictionaries.  So here we need to parse both the user edited
        // dictionary list and the shared dictionary list
        // to see what dictionaries the admin/user has installed

        int numusr;          // number of user dictionary entries
        int numshr;          // number of shared dictionary entries
        // dictentry * spdict;  // shared dict entry pointer
        // dictentry * updict;  // user dict entry pointer
        SvtPathOptions aPathOpt;
		rtl_TextEncoding aEnc = RTL_TEXTENCODING_UTF8;

    	std::vector<objc_object *> postspdict;
        std::vector<objc_object *> postupdict;
    	//std::vector<dictentry *> postspdict;
        //std::vector<dictentry *> postupdict;


	if (!numdict) {

        // invoke a dictionary manager to get the user dictionary list
        // TODO How on Mac OS X?

        // invoke a second  dictionary manager to get the shared dictionary list
        NSArray *aLocales = [NSLocale availableLocaleIdentifiers];

        //Test for existence of the dictionaries
        for (unsigned int i = 0; i < [aLocales count]; i++)
        {
            if( [macSpell setLanguage:[aLocales objectAtIndex:i] ] )
            {
                postspdict.push_back( [ aLocales objectAtIndex:i ] );
            }
        }

	    numusr = postupdict.size();
        numshr = postspdict.size();

        // we really should merge these and remove duplicates but since
        // users can name their dictionaries anything they want it would
        // be impossible to know if a real duplication exists unless we
        // add some unique key to each myspell dictionary
        numdict = numshr + numusr;

        if (numdict) {
            aDLocs = new Locale [numdict];
            aDEncs  = new rtl_TextEncoding [numdict];
            aDNames = new OUString [numdict];
            aSuppLocales.realloc(numdict);
            Locale * pLocale = aSuppLocales.getArray();
            int numlocs = 0;
            int newloc;
            int i,j;
            int k = 0;

            //first add the user dictionaries
            //TODO for MAC?

            // now add the shared dictionaries
            for (i = 0; i < numshr; i++) {
                NSDictionary *aLocDict = [ NSLocale componentsFromLocaleIdentifier:postspdict[i] ];
                NSString* aLang = [ aLocDict objectForKey:NSLocaleLanguageCode ];
                NSString* aCountry = [ aLocDict objectForKey:NSLocaleCountryCode ];
                OUString lang([aLang cStringUsingEncoding: NSUTF8StringEncoding], [aLang length], aEnc);
                OUString country([ aCountry cStringUsingEncoding: NSUTF8StringEncoding], [aCountry length], aEnc);
                Locale nLoc( lang, country, OUString() );
                newloc = 1;
                //eliminate duplicates (is this needed for MacOS?)
                for (j = 0; j < numlocs; j++) {
                    if (nLoc == pLocale[j]) newloc = 0;
                }
                if (newloc) {
                    pLocale[numlocs] = nLoc;
                    numlocs++;
                }
                aDLocs[k] = nLoc;
                //pointer to Hunspell dictionary - not needed for MAC
                //aDicts[k] = NULL;
                aDEncs[k] = 0;
                // Dictionary file names not valid for Mac Spell
                //aDNames[k] = aPathOpt.GetLinguisticPath() + A2OU("/ooo/") + A2OU(postspdict[i]->filename);
                k++;
            }

            aSuppLocales.realloc(numlocs);

        } else {
            /* no dictionary.lst found so register no dictionaries */
            numdict = 0;
            //aDicts = NULL;
                aDEncs  = NULL;
                aDLocs = NULL;
                aDNames = NULL;
	            aSuppLocales.realloc(0);
            }

            /* de-allocation of memory is handled inside the DictMgr */
            // updict = NULL;
            // spdict = NULL;

        }

	return aSuppLocales;
}



sal_Bool SAL_CALL MacSpellChecker::hasLocale(const Locale& rLocale)
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

	sal_Bool bRes = sal_False;
	if (!aSuppLocales.getLength())
		getLocales();

	sal_Int32 nLen = aSuppLocales.getLength();
	for (sal_Int32 i = 0;  i < nLen;  ++i)
	{
		const Locale *pLocale = aSuppLocales.getConstArray();
		if (rLocale == pLocale[i])
		{
			bRes = sal_True;
			break;
		}
	}
	return bRes;
}


sal_Int16 MacSpellChecker::GetSpellFailure( const OUString &rWord, const Locale &rLocale )
{
    rtl_TextEncoding aEnc;

	// initialize a myspell object for each dictionary once
        // (note: mutex is held higher up in isValid)


	sal_Int16 nRes = -1;

        // first handle smart quotes both single and double
	OUStringBuffer rBuf(rWord);
        sal_Int32 n = rBuf.getLength();
        sal_Unicode c;
	for (sal_Int32 ix=0; ix < n; ix++) {
	    c = rBuf.charAt(ix);
            if ((c == 0x201C) || (c == 0x201D)) rBuf.setCharAt(ix,(sal_Unicode)0x0022);
            if ((c == 0x2018) || (c == 0x2019)) rBuf.setCharAt(ix,(sal_Unicode)0x0027);
        }
        OUString nWord(rBuf.makeStringAndClear());

	if (n)
	{
        aEnc = 0;
		NSAutoreleasePool* pool	= [[NSAutoreleasePool alloc] init];
        NSString* aNSStr = [[NSString alloc] initWithCharacters: nWord.getStr() length: nWord.getLength()];
        NSString* aLang = [[NSString alloc] initWithCharacters: rLocale.Language.getStr() length: rLocale.Language.getLength()];
        if(rLocale.Country.getLength()>0)
        {
            NSString* aCountry = [[NSString alloc] initWithCharacters: rLocale.Country.getStr() length: rLocale.Country.getLength()];
            NSString* aTag = @"_";
            NSString* aTaggedCountry = [aTag stringByAppendingString:aCountry];
            [aLang autorelease];
            aLang = [aLang  stringByAppendingString:aTaggedCountry];
        }

        int aCount;
        NSRange range = [macSpell checkSpellingOfString:aNSStr startingAt:0 language:aLang wrap:sal_False inSpellDocumentWithTag:macTag wordCount:&aCount];
		int rVal = 0;
		if(range.length>0)
		{
			rVal = -1;
		}
		else
		{
			rVal = 1;
		}
        [pool release];
        if (rVal != 1)
        {
            nRes = SpellFailure::SPELLING_ERROR;
        } else {
            return -1;
        }
    }
	return nRes;
}



sal_Bool SAL_CALL
	MacSpellChecker::isValid( const OUString& rWord, const Locale& rLocale,
			const PropertyValues& rProperties )
		throw(IllegalArgumentException, RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

 	if (rLocale == Locale()  ||  !rWord.getLength())
		return sal_True;

	if (!hasLocale( rLocale ))
#ifdef LINGU_EXCEPTIONS
		throw( IllegalArgumentException() );
#else
		return sal_True;
#endif

	// Get property values to be used.
	// These are be the default values set in the SN_LINGU_PROPERTIES
	// PropertySet which are overridden by the supplied ones from the
	// last argument.
	// You'll probably like to use a simplier solution than the provided
	// one using the PropertyHelper_Spell.

	PropertyHelper_Spell &rHelper = GetPropHelper();
	rHelper.SetTmpPropVals( rProperties );

	sal_Int16 nFailure = GetSpellFailure( rWord, rLocale );
	if (nFailure != -1)
	{
		sal_Int16 nLang = LocaleToLanguage( rLocale );
		// postprocess result for errors that should be ignored
		if (   (!rHelper.IsSpellUpperCase()  && IsUpper( rWord, nLang ))
			|| (!rHelper.IsSpellWithDigits() && HasDigits( rWord ))
			|| (!rHelper.IsSpellCapitalization()
				&&  nFailure == SpellFailure::CAPTION_ERROR)
		)
			nFailure = -1;
	}

	return (nFailure == -1);
}


Reference< XSpellAlternatives >
	MacSpellChecker::GetProposals( const OUString &rWord, const Locale &rLocale )
{
	// Retrieves the return values for the 'spell' function call in case
	// of a misspelled word.
	// Especially it may give a list of suggested (correct) words:

	Reference< XSpellAlternatives > xRes;
        // note: mutex is held by higher up by spell which covers both

    sal_Int16 nLang = LocaleToLanguage( rLocale );
	int count;
	Sequence< OUString > aStr( 0 );

        // first handle smart quotes (single and double)
	OUStringBuffer rBuf(rWord);
        sal_Int32 n = rBuf.getLength();
        sal_Unicode c;
	for (sal_Int32 ix=0; ix < n; ix++) {
	     c = rBuf.charAt(ix);
             if ((c == 0x201C) || (c == 0x201D)) rBuf.setCharAt(ix,(sal_Unicode)0x0022);
             if ((c == 0x2018) || (c == 0x2019)) rBuf.setCharAt(ix,(sal_Unicode)0x0027);
        }
        OUString nWord(rBuf.makeStringAndClear());

	if (n)
	{
		NSAutoreleasePool* pool	= [[NSAutoreleasePool alloc] init];
        NSString* aNSStr = [[NSString alloc] initWithCharacters: nWord.getStr() length: nWord.getLength()];
        NSString* aLang = [[NSString alloc] initWithCharacters: rLocale.Language.getStr() length: rLocale.Language.getLength() ];
        if(rLocale.Country.getLength()>0)
        {
            NSString* aCountry = [[NSString alloc] initWithCharacters: rLocale.Country.getStr() length: rLocale.Country.getLength() ];
            NSString* aTag = @"_";
            NSString* aTaggedCountry = [aTag stringByAppendingString:aCountry];
            [aLang autorelease];
            aLang = [aLang  stringByAppendingString:aTaggedCountry];
        }
        [macSpell setLanguage:aLang];
        NSArray *guesses = [macSpell guessesForWord:aNSStr];
        count = [guesses count];
        if (count)
        {
           aStr.realloc( count );
           OUString *pStr = aStr.getArray();
               for (int ii=0; ii < count; ii++)
               {
                  // if needed add: if (suglst[ii] == NULL) continue;
                  NSString* guess = [guesses objectAtIndex:ii];
                  OUString cvtwrd((const sal_Unicode*)[guess cStringUsingEncoding:NSUnicodeStringEncoding], (sal_Int32)[guess length]);
                  pStr[ii] = cvtwrd;
               }
        }
       [pool release];
	}

            // now return an empty alternative for no suggestions or the list of alternatives if some found
	    SpellAlternatives *pAlt = new SpellAlternatives;
            String aTmp(rWord);
	    pAlt->SetWordLanguage( aTmp, nLang );
	    pAlt->SetFailureType( SpellFailure::SPELLING_ERROR );
	    pAlt->SetAlternatives( aStr );
	    xRes = pAlt;
        return xRes;

}




Reference< XSpellAlternatives > SAL_CALL
	MacSpellChecker::spell( const OUString& rWord, const Locale& rLocale,
			const PropertyValues& rProperties )
		throw(IllegalArgumentException, RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

 	if (rLocale == Locale()  ||  !rWord.getLength())
		return NULL;

	if (!hasLocale( rLocale ))
#ifdef LINGU_EXCEPTIONS
		throw( IllegalArgumentException() );
#else
		return NULL;
#endif

	Reference< XSpellAlternatives > xAlt;
	if (!isValid( rWord, rLocale, rProperties ))
	{
		xAlt =  GetProposals( rWord, rLocale );
	}
	return xAlt;
}


Reference< XInterface > SAL_CALL MacSpellChecker_CreateInstance(
            const Reference< XMultiServiceFactory > & /*rSMgr*/ )
		throw(Exception)
{

	Reference< XInterface > xService = (cppu::OWeakObject*) new MacSpellChecker;
	return xService;
}


sal_Bool SAL_CALL
	MacSpellChecker::addLinguServiceEventListener(
			const Reference< XLinguServiceEventListener >& rxLstnr )
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

	sal_Bool bRes = sal_False;
	if (!bDisposing && rxLstnr.is())
	{
		bRes = GetPropHelper().addLinguServiceEventListener( rxLstnr );
	}
	return bRes;
}


sal_Bool SAL_CALL
	MacSpellChecker::removeLinguServiceEventListener(
			const Reference< XLinguServiceEventListener >& rxLstnr )
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

	sal_Bool bRes = sal_False;
	if (!bDisposing && rxLstnr.is())
	{
		DBG_ASSERT( xPropHelper.is(), "xPropHelper non existent" );
		bRes = GetPropHelper().removeLinguServiceEventListener( rxLstnr );
	}
	return bRes;
}


OUString SAL_CALL
    MacSpellChecker::getServiceDisplayName( const Locale& /*rLocale*/ )
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );
	return A2OU( "Mac OS X Spell Checker" );
}


void SAL_CALL
	MacSpellChecker::initialize( const Sequence< Any >& rArguments )
		throw(Exception, RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

	if (!pPropHelper)
	{
		sal_Int32 nLen = rArguments.getLength();
		if (2 == nLen)
		{
			Reference< XPropertySet	>	xPropSet;
			rArguments.getConstArray()[0] >>= xPropSet;
			//rArguments.getConstArray()[1] >>= xDicList;

			//! Pointer allows for access of the non-UNO functions.
			//! And the reference to the UNO-functions while increasing
			//! the ref-count and will implicitly free the memory
			//! when the object is not longer used.
			pPropHelper = new PropertyHelper_Spell( (XSpellChecker *) this, xPropSet );
			xPropHelper = pPropHelper;
			pPropHelper->AddAsPropListener();	//! after a reference is established
		}
		else
			DBG_ERROR( "wrong number of arguments in sequence" );

	}
}


void SAL_CALL
	MacSpellChecker::dispose()
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

	if (!bDisposing)
	{
		bDisposing = sal_True;
		EventObject	aEvtObj( (XSpellChecker *) this );
		aEvtListeners.disposeAndClear( aEvtObj );
	}
}


void SAL_CALL
	MacSpellChecker::addEventListener( const Reference< XEventListener >& rxListener )
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

	if (!bDisposing && rxListener.is())
		aEvtListeners.addInterface( rxListener );
}


void SAL_CALL
	MacSpellChecker::removeEventListener( const Reference< XEventListener >& rxListener )
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

	if (!bDisposing && rxListener.is())
		aEvtListeners.removeInterface( rxListener );
}


///////////////////////////////////////////////////////////////////////////
// Service specific part
//

OUString SAL_CALL MacSpellChecker::getImplementationName()
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

	return getImplementationName_Static();
}


sal_Bool SAL_CALL MacSpellChecker::supportsService( const OUString& ServiceName )
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

	Sequence< OUString > aSNL = getSupportedServiceNames();
	const OUString * pArray = aSNL.getConstArray();
	for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
		if( pArray[i] == ServiceName )
			return sal_True;
	return sal_False;
}


Sequence< OUString > SAL_CALL MacSpellChecker::getSupportedServiceNames()
		throw(RuntimeException)
{
	MutexGuard	aGuard( GetLinguMutex() );

	return getSupportedServiceNames_Static();
}


Sequence< OUString > MacSpellChecker::getSupportedServiceNames_Static()
		throw()
{
	MutexGuard	aGuard( GetLinguMutex() );

	Sequence< OUString > aSNS( 1 );	// auch mehr als 1 Service moeglich
	aSNS.getArray()[0] = A2OU( SN_SPELLCHECKER );
	return aSNS;
}

void * SAL_CALL MacSpellChecker_getFactory( const sal_Char * pImplName,
			XMultiServiceFactory * pServiceManager, void *  )
{
	void * pRet = 0;
	if ( !MacSpellChecker::getImplementationName_Static().compareToAscii( pImplName ) )
	{
		Reference< XSingleServiceFactory > xFactory =
			cppu::createOneInstanceFactory(
				pServiceManager,
				MacSpellChecker::getImplementationName_Static(),
				MacSpellChecker_CreateInstance,
				MacSpellChecker::getSupportedServiceNames_Static());
		// acquire, because we return an interface pointer instead of a reference
		xFactory->acquire();
		pRet = xFactory.get();
	}
	return pRet;
}


///////////////////////////////////////////////////////////////////////////
