/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



#include <ooo/vba/excel/XRange.hpp>
#include <com/sun/star/sheet/XCellRangeAddressable.hpp>
#include <com/sun/star/sheet/XSheetConditionalEntry.hpp>
#include <vector>
#include "vbaformatconditions.hxx"
#include "vbaformatcondition.hxx"
#include "vbaworkbook.hxx"
#include "vbastyles.hxx"
#include "vbaglobals.hxx"
using namespace ::ooo::vba;
using namespace ::com::sun::star;

typedef std::vector< beans::PropertyValue > VecPropValues;

static rtl::OUString OPERATOR( RTL_CONSTASCII_USTRINGPARAM("Operator") );
static rtl::OUString FORMULA1( RTL_CONSTASCII_USTRINGPARAM("Formula1") );
static rtl::OUString FORMULA2( RTL_CONSTASCII_USTRINGPARAM("Formula2") );
static rtl::OUString STYLENAME( RTL_CONSTASCII_USTRINGPARAM("StyleName") );
static rtl::OUString sStyleNamePrefix( RTL_CONSTASCII_USTRINGPARAM("Excel_CondFormat") );

ScVbaFormatConditions::ScVbaFormatConditions( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext > & xContext, const uno::Reference< sheet::XSheetConditionalEntries >& _xSheetConditionalEntries, const uno::Reference< frame::XModel >& /*xModel*/ ) : ScVbaFormatConditions_BASE( xParent, xContext, uno::Reference< container::XIndexAccess >( _xSheetConditionalEntries, uno::UNO_QUERY_THROW ) ), mxSheetConditionalEntries( _xSheetConditionalEntries )
{
	mxRangeParent.set( xParent, uno::UNO_QUERY_THROW );
    uno::Reference< excel::XApplication> xApp( Application(), uno::UNO_QUERY_THROW );
    mxStyles.set( xApp->getThisWorkbook()->Styles( uno::Any() ), uno::UNO_QUERY_THROW );
	uno::Reference< sheet::XCellRangeAddressable > xCellRange( mxRangeParent->getCellRange(), uno::UNO_QUERY_THROW );
	mxParentRangePropertySet.set( xCellRange, uno::UNO_QUERY_THROW );
	
	table::CellRangeAddress rangeAddress = xCellRange->getRangeAddress();
	maCellAddress = table::CellAddress( rangeAddress.Sheet, rangeAddress.StartColumn,  rangeAddress.StartRow );
}

void SAL_CALL 
ScVbaFormatConditions::Delete(  ) throw (script::BasicErrorException, uno::RuntimeException)
{
	try
	{
		ScVbaStyles* pStyles = static_cast< ScVbaStyles* >( mxStyles.get() );
		if ( !pStyles )
			DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString() );
		sal_Int32 nCount = mxSheetConditionalEntries->getCount();
		for (sal_Int32 i = nCount - 1; i >= 0; i--)
		{
			uno::Reference< sheet::XSheetConditionalEntry > xSheetConditionalEntry( mxSheetConditionalEntries->getByIndex(i), uno::UNO_QUERY_THROW );
			pStyles->Delete(xSheetConditionalEntry->getStyleName());
			mxSheetConditionalEntries->removeByIndex(i);           
		}
		notifyRange();
	}
	catch (uno::Exception& )
	{
		DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString());
	}
}

uno::Type SAL_CALL 
ScVbaFormatConditions::getElementType() throw (css::uno::RuntimeException)
{
	return excel::XFormatCondition::static_type(0);
}


uno::Any xSheetConditionToFormatCondition( const uno::Reference< XHelperInterface >& xRangeParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< excel::XStyles >& xStyles, const uno::Reference< excel::XFormatConditions >& xFormatConditions, const uno::Reference< beans::XPropertySet >& xRangeProps,  const uno::Any& aObject ) 
{
	uno::Reference< sheet::XSheetConditionalEntry > xSheetConditionalEntry;
	aObject >>= xSheetConditionalEntry;

	uno::Reference< excel::XStyle > xStyle( xStyles->Item( uno::makeAny( xSheetConditionalEntry->getStyleName() ), uno::Any() ), uno::UNO_QUERY_THROW );
	uno::Reference< excel::XFormatCondition > xCondition = new ScVbaFormatCondition( xRangeParent, xContext,  xSheetConditionalEntry, xStyle, xFormatConditions, xRangeProps ); 
	return uno::makeAny( xCondition );
}

uno::Any 
ScVbaFormatConditions::createCollectionObject(const uno::Any& aObject )
{
	return xSheetConditionToFormatCondition( uno::Reference< XHelperInterface >( mxRangeParent, uno::UNO_QUERY_THROW ), mxContext, mxStyles, this, mxParentRangePropertySet, aObject );
}

class EnumWrapper : public EnumerationHelper_BASE
{
        uno::Reference<container::XIndexAccess > m_xIndexAccess;
        uno::Reference<excel::XRange > m_xParentRange;
        uno::Reference<uno::XComponentContext > m_xContext;
        uno::Reference<excel::XStyles > m_xStyles;
        uno::Reference<excel::XFormatConditions > m_xParentCollection;
        uno::Reference<beans::XPropertySet > m_xProps;

        sal_Int32 nIndex;
public:
        EnumWrapper( const uno::Reference< container::XIndexAccess >& xIndexAccess, const uno::Reference<excel::XRange >& xRange, const uno::Reference<uno::XComponentContext >& xContext, const uno::Reference<excel::XStyles >& xStyles, const uno::Reference< excel::XFormatConditions >& xCollection, const uno::Reference<beans::XPropertySet >& xProps  ) : m_xIndexAccess( xIndexAccess ), m_xParentRange( xRange ), m_xContext( xContext ), m_xStyles( xStyles ), m_xParentCollection( xCollection ), m_xProps( xProps ), nIndex( 0 ) {}
        virtual ::sal_Bool SAL_CALL hasMoreElements(  ) throw (uno::RuntimeException)
        {
                return ( nIndex < m_xIndexAccess->getCount() );
        }

        virtual uno::Any SAL_CALL nextElement(  ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
        {
                if ( nIndex < m_xIndexAccess->getCount() )
                        return xSheetConditionToFormatCondition( uno::Reference< XHelperInterface >( m_xParentRange, uno::UNO_QUERY_THROW ), m_xContext, m_xStyles, m_xParentCollection, m_xProps, m_xIndexAccess->getByIndex( nIndex++ ) );
                throw container::NoSuchElementException();
        }
};

uno::Reference< excel::XFormatCondition > SAL_CALL 
ScVbaFormatConditions::Add( ::sal_Int32 _nType, const uno::Any& _aOperator, const uno::Any& _aFormula1, const uno::Any& _aFormula2 ) throw (script::BasicErrorException, uno::RuntimeException)
{
	return Add( _nType, _aOperator, _aFormula1, _aFormula2, uno::Reference< excel::XStyle >() );
}

uno::Reference< excel::XFormatCondition > 
ScVbaFormatConditions::Add( ::sal_Int32 _nType, const uno::Any& _aOperator, const uno::Any& _aFormula1, const uno::Any& _aFormula2, const css::uno::Reference< excel::XStyle >& _xStyle  ) throw (script::BasicErrorException, uno::RuntimeException)
{
	// #TODO
	// #FIXME 
	// This method will NOT handle r1c1 formulas [*]and only assumes that
	// the formulas are _xlA1 based ( need to hook into calc work ths should
	// address this )
	// [*] reason: getA1Formula method below is just a hook and just 
	// returns whats it gets ( e.g. doesn't convert anything )
	uno::Reference< excel::XStyle > xStyle( _xStyle );
	uno::Reference< excel::XFormatCondition > xFormatCondition;
	try
	{
		rtl::OUString sStyleName;
		if ( !xStyle.is() )
		{	
			sStyleName = getStyleName();
			xStyle = mxStyles->Add(sStyleName, uno::Any() );
		}
		else
		{
			sStyleName = xStyle->getName();
		}

		VecPropValues aPropertyValueVector;
		sheet::ConditionOperator aType = ScVbaFormatCondition::retrieveAPIType(_nType, uno::Reference< sheet::XSheetCondition >() );
		uno::Any aValue;

		if ( aType == sheet::ConditionOperator_FORMULA)
			aValue = uno::makeAny( sheet::ConditionOperator_FORMULA );
		else
			aValue = uno::makeAny( ScVbaFormatCondition::retrieveAPIOperator(_aOperator) );

		beans::PropertyValue aProperty( OPERATOR, 0, aValue, beans::PropertyState_DIRECT_VALUE );
		aPropertyValueVector.push_back( aProperty );

		if ( _aFormula1.hasValue() )
		{        
			beans::PropertyValue aProp( FORMULA1, 0, uno::makeAny( getA1Formula( _aFormula1 ) ), beans::PropertyState_DIRECT_VALUE );
			aPropertyValueVector.push_back( aProp );
		}
		if ( _aFormula2.hasValue() )
		{        
			beans::PropertyValue aProp( FORMULA2, 0, uno::makeAny( getA1Formula( _aFormula2 ) ), beans::PropertyState_DIRECT_VALUE );
			aPropertyValueVector.push_back( aProp );
		}
		aProperty.Name = STYLENAME;
		aProperty.Value = uno::makeAny( sStyleName );

		// convert vector to sequence
		uno::Sequence< beans::PropertyValue > aPropertyValueList(aPropertyValueVector.size());
		VecPropValues::iterator it = aPropertyValueVector.begin();
		VecPropValues::iterator it_end = aPropertyValueVector.end();
		for ( sal_Int32 index=0; it != it_end; ++it )
			aPropertyValueList[ index++ ] = *it;

		mxSheetConditionalEntries->addNew(aPropertyValueList);
		for (sal_Int32 i = mxSheetConditionalEntries->getCount()-1; i >= 0; i--)
		{
			uno::Reference< sheet::XSheetConditionalEntry > xSheetConditionalEntry( mxSheetConditionalEntries->getByIndex(i), uno::UNO_QUERY_THROW );
			if (xSheetConditionalEntry->getStyleName().equals(sStyleName))
			{
				xFormatCondition =  new ScVbaFormatCondition(uno::Reference< XHelperInterface >( mxRangeParent, uno::UNO_QUERY_THROW ), mxContext, xSheetConditionalEntry, xStyle, this, mxParentRangePropertySet);
				notifyRange();
				return xFormatCondition;
			}
		}
	}
	catch (uno::Exception& )
	{
	}
	DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString() );
	return xFormatCondition;
}


uno::Reference< container::XEnumeration > SAL_CALL 
ScVbaFormatConditions::createEnumeration() throw (uno::RuntimeException)
{
	return new EnumWrapper( m_xIndexAccess, mxRangeParent, mxContext, mxStyles, this, mxParentRangePropertySet  );
}


void 
ScVbaFormatConditions::notifyRange() throw ( script::BasicErrorException )
{
	try
	{
		mxParentRangePropertySet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ConditionalFormat")), uno::makeAny( mxSheetConditionalEntries ));
	}
	catch (uno::Exception& )
	{
		DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString());
	}
}

rtl::OUString 
ScVbaFormatConditions::getA1Formula(const css::uno::Any& _aFormula) throw ( script::BasicErrorException )
{
	// #TODO, #FIXME hook-in proper formula conversion detection & logic
	rtl::OUString sFormula;
	if ( !( _aFormula >>= sFormula ) )
		DebugHelper::exception(SbERR_BAD_PARAMETER, rtl::OUString() );
	return sFormula;
}

rtl::OUString 
ScVbaFormatConditions::getStyleName()
{
	ScVbaStyles* pStyles = static_cast< ScVbaStyles* >( mxStyles.get() );
	if ( !pStyles )
		DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString() );
	uno::Sequence< rtl::OUString > sCellStyleNames = pStyles->getStyleNames();
	return ContainerUtilities::getUniqueName(sCellStyleNames, sStyleNamePrefix, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_") ));
}

void 
ScVbaFormatConditions::removeFormatCondition( const rtl::OUString& _sStyleName, sal_Bool _bRemoveStyle) throw ( script::BasicErrorException )
{
	try
	{
		sal_Int32 nElems = mxSheetConditionalEntries->getCount();
		for (sal_Int32 i = 0; i < nElems; i++)
		{
			uno::Reference< sheet::XSheetConditionalEntry > xSheetConditionalEntry( mxSheetConditionalEntries->getByIndex(i), uno::UNO_QUERY_THROW );
			if (_sStyleName.equals(xSheetConditionalEntry->getStyleName()))
			{
				mxSheetConditionalEntries->removeByIndex(i);
				if (_bRemoveStyle)
				{
					ScVbaStyles* pStyles = static_cast< ScVbaStyles* >( mxStyles.get() );
					if ( !pStyles )
						DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString());
					pStyles->Delete( _sStyleName );
				}
				return;
			}
		}
	}
	catch (uno::Exception& )
	{
		DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString());
	}
}

rtl::OUString& 
ScVbaFormatConditions::getServiceImplName()
{
	static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaFormatConditions") );
	return sImplName;
}

uno::Sequence< rtl::OUString > 
ScVbaFormatConditions::getServiceNames()
{
	static uno::Sequence< rtl::OUString > aServiceNames;
	if ( aServiceNames.getLength() == 0 )
	{
		aServiceNames.realloc( 1 );
		aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.FormatConditions" ) );
	}
	return aServiceNames;
}

