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



#ifndef SC_FORMULARESULT_HXX
#define SC_FORMULARESULT_HXX

#include "token.hxx"


/** Store a variable formula cell result, balancing between runtime performance
    and memory consumption. */
class ScFormulaResult
{
    typedef unsigned char Multiline;
    static const Multiline MULTILINE_UNKNOWN = 0;
    static const Multiline MULTILINE_FALSE   = 1;
    static const Multiline MULTILINE_TRUE    = 2;

    union
    {
        double          mfValue;    // double result direct for performance and memory consumption
        const formula::FormulaToken*  mpToken;    // if not, result token obtained from interpreter
    };
    sal_uInt16              mnError;    // error code
    bool                mbToken :1; // whether content of union is a token
    bool                mbEmpty :1; // empty cell result
    bool                mbEmptyDisplayedAsString :1;    // only if mbEmpty
    Multiline           meMultiline :2; // result is multiline

    /** Reset mnError, mbEmpty and mbEmptyDisplayedAsString to their defaults
        prior to assigning other types */
    inline  void                ResetToDefaults();

    /** If token is of formula::svError set error code and decrement RefCount.
        If token is of formula::svEmptyCell set mbEmpty and mbEmptyAsString and
        decrement RefCount.
        If token is of formula::svDouble set mfValue and decrement RefCount.
        Else assign token to mpToken. NULL is valid => svUnknown.
        Other member variables are set accordingly.
        @precondition: Token MUST had been IncRef'ed prior to this call!
        @precondition: An already existing different mpToken MUST had been
        DecRef'ed prior to this call, p will be assigned to mpToken if not
        resolved.
        ATTENTION! Token may get deleted in this call! */
    inline  void                ResolveToken( const formula::FormulaToken * p );

public:
                                /** Effectively type svUnknown. */
                                ScFormulaResult()
                                    : mpToken(NULL), mnError(0), mbToken(true),
                                    mbEmpty(false), mbEmptyDisplayedAsString(false),
                                    meMultiline(MULTILINE_UNKNOWN) {}

                                ScFormulaResult( const ScFormulaResult & r )
                                    : mnError( r.mnError), mbToken( r.mbToken),
                                    mbEmpty( r.mbEmpty),
                                    mbEmptyDisplayedAsString( r.mbEmptyDisplayedAsString),
                                    meMultiline( r.meMultiline)
                                {
                                    if (mbToken)
                                    {
                                        mpToken = r.mpToken;
                                        if (mpToken)
                                        {
                                            // Since matrix dimension and
                                            // results are assigned to a matrix
                                            // cell formula token we have to
                                            // clone that instead of sharing it.
                                            const ScMatrixFormulaCellToken* pMatFormula =
                                                r.GetMatrixFormulaCellToken();
                                            if (pMatFormula)
                                                mpToken = new ScMatrixFormulaCellToken( *pMatFormula);
                                            mpToken->IncRef();
                                        }
                                    }
                                    else
                                        mfValue = r.mfValue;
                                }

    /** Same comments as for SetToken() apply! */
    explicit                    ScFormulaResult( const formula::FormulaToken* p )
                                    : mnError(0), mbToken(false),
                                    mbEmpty(false), mbEmptyDisplayedAsString(false),
                                    meMultiline(MULTILINE_UNKNOWN)
                                {
                                    SetToken( p);
                                }

                                ~ScFormulaResult()
                                {
                                    if (mbToken && mpToken)
                                        mpToken->DecRef();
                                }

    /** Well, guess what ... */
    inline  ScFormulaResult &   operator=( const ScFormulaResult & r );

    /** Assignment as in operator=() but without return */
    inline  void                Assign( const ScFormulaResult & r );

    /** Sets a direct double if token type is formula::svDouble, or mbEmpty if
        formula::svEmptyCell, else token. If p is NULL, that is set as well, effectively
        resulting in GetType()==svUnknown. If the already existing result is
        ScMatrixFormulaCellToken, the upper left ist set to token.

        ATTENTION! formula::FormulaToken had to be allocated using 'new' and if of type
        formula::svDouble and no RefCount was set may not be used after this call
        because it was deleted after decrement! */
    inline  void                SetToken( const formula::FormulaToken* p );

    /** May be NULL if SetToken() did so, also if type formula::svDouble or formula::svError! */
    inline  formula::FormulaConstTokenRef     GetToken() const;

    /** Return upper left token if formula::svMatrixCell, else return GetToken().
        May be NULL if SetToken() did so, also if type formula::svDouble or formula::svError! */
    inline  formula::FormulaConstTokenRef     GetCellResultToken() const;

    /** Return type of result, including formula::svError, formula::svEmptyCell, formula::svDouble and
        formula::svMatrixCell. */
    inline  formula::StackVar            GetType() const;

    /** If type is formula::svMatrixCell return the type of upper left element, else
        GetType() */
    inline  formula::StackVar            GetCellResultType() const;

    /** If type is formula::svEmptyCell (including matrix upper left) and should be
        displayed as empty string */
    inline  bool                IsEmptyDisplayedAsString() const;

    /** Test for cell result type formula::svDouble, including upper left if
        formula::svMatrixCell. Also included is formula::svError for legacy, because previously
        an error result was treated like a numeric value at some places in
        ScFormulaCell. Also included is formula::svEmptyCell as a reference to an empty
        cell usually is treated as numeric 0. Use GetCellResultType() for
        details instead. */
    inline  bool                IsValue() const;

    /** Determines whether or not the result is a string containing more than 
        one paragraph */
    inline  bool                IsMultiline() const;

    /** Get error code if set or GetCellResultType() is formula::svError or svUnknown,
        else 0. */
    inline  sal_uInt16              GetResultError() const;

    /** Set error code, don't touch token or double. */
    inline  void                SetResultError( sal_uInt16 nErr );

    /** Set direct double. Shouldn't be used externally except in
        ScFormulaCell for rounded CalcAsShown or SetErrCode(). If
        ScMatrixFormulaCellToken the token isn't replaced but upper left result
        is modified instead, but only if it was of type formula::svDouble before or not
        set at all. */
    inline  void                SetDouble( double f );

    /** Return value if type formula::svDouble or formula::svHybridCell or formula::svMatrixCell and upper
        left formula::svDouble, else 0.0 */
    inline  double              GetDouble() const;

    /** Return string if type formula::svString or formula::svHybridCell or formula::svMatrixCell and
        upper left formula::svString, else empty string. */
    inline  const String &      GetString() const;

    /** Return matrix if type formula::svMatrixCell and ScMatrix present, else NULL. */
    inline  ScConstMatrixRef    GetMatrix() const;

    /** Return formula string if type formula::svHybridCell, else empty string. */
    inline  const String &      GetHybridFormula() const;

    /** Should only be used by import filters, best in the order
        SetHybridDouble(), SetHybridString(), or only SetHybridString() for
        formula string to be compiled later. */
    inline  void                SetHybridDouble( double f );

    /** Should only be used by import filters, best in the order
        SetHybridDouble(), SetHybridString()/SetHybridFormula(), or only
        SetHybridFormula() for formula string to be compiled later. */
    inline  void                SetHybridString( const String & rStr );

    /** Should only be used by import filters, best in the order
        SetHybridDouble(), SetHybridString()/SetHybridFormula(), or only
        SetHybridFormula() for formula string to be compiled later. */
    inline  void                SetHybridFormula( const String & rFormula );

    /** Get the const ScMatrixFormulaCellToken* if token is of that type, else
        NULL. */
    inline const ScMatrixFormulaCellToken* GetMatrixFormulaCellToken() const;

    /** Get the ScMatrixFormulaCellToken* if token is of that type, else NULL.
        Shouldn't be used externally except by ScFormulaCell::SetMatColsRows(). */
    inline ScMatrixFormulaCellToken* GetMatrixFormulaCellTokenNonConst();
};


inline void ScFormulaResult::ResetToDefaults()
{
    mnError = 0;
    mbEmpty = false;
    mbEmptyDisplayedAsString = false;
    meMultiline = MULTILINE_UNKNOWN;
}


inline void ScFormulaResult::ResolveToken( const formula::FormulaToken * p )
{
    ResetToDefaults();
    if (!p)
    {
        mpToken = p;
        mbToken = true;
    }
    else
    {
        switch (p->GetType())
        {
            case formula::svError:
                mnError = p->GetError();
                p->DecRef();
                mbToken = false;
                // set in case mnError is 0 now, which shouldn't happen but ...
                mfValue = 0.0;
                meMultiline = MULTILINE_FALSE;
                break;
            case formula::svEmptyCell:
                mbEmpty = true;
                mbEmptyDisplayedAsString = static_cast<const ScEmptyCellToken*>(p)->IsDisplayedAsString();
                p->DecRef();
                mbToken = false;
                meMultiline = MULTILINE_FALSE;
                break;
            case formula::svDouble:
                mfValue = p->GetDouble();
                p->DecRef();
                mbToken = false;
                meMultiline = MULTILINE_FALSE;
                break;
            default:
                mpToken = p;
                mbToken = true;
        }
    }
}


inline ScFormulaResult & ScFormulaResult::operator=( const ScFormulaResult & r )
{
    Assign( r);
    return *this;
}


inline void ScFormulaResult::Assign( const ScFormulaResult & r )
{
    if (this == &r)
        return;
    if (r.mbEmpty)
    {
        if (mbToken && mpToken)
            mpToken->DecRef();
        mbToken = false;
        mbEmpty = true;
        mbEmptyDisplayedAsString = r.mbEmptyDisplayedAsString;
        meMultiline = r.meMultiline;
    }
    else if (r.mbToken)
    {
        // Matrix formula cell token must be cloned, see copy-ctor.
        const ScMatrixFormulaCellToken* pMatFormula =
            r.GetMatrixFormulaCellToken();
        if (pMatFormula)
            SetToken( new ScMatrixFormulaCellToken( *pMatFormula));
        else
            SetToken( r.mpToken);
    }
    else
        SetDouble( r.mfValue);
    // If there was an error there will be an error, no matter what Set...()
    // methods did.
    mnError = r.mnError;
}


inline void ScFormulaResult::SetToken( const formula::FormulaToken* p )
{
    ResetToDefaults();
    if (p)
        p->IncRef();
    // Handle a result obtained from the interpreter to be assigned to a matrix
    // formula cell's ScMatrixFormulaCellToken.
    ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
    if (pMatFormula)
    {
        const ScMatrixCellResultToken* pMatResult =
            (p && p->GetType() == formula::svMatrixCell ?
             dynamic_cast<const ScMatrixCellResultToken*>(p) : NULL);
        if (pMatResult)
        {
            const ScMatrixFormulaCellToken* pNewMatFormula = 
                dynamic_cast<const ScMatrixFormulaCellToken*>(pMatResult);
            if (pNewMatFormula)
            {
                DBG_ERRORFILE( "ScFormulaResult::SetToken: pNewMatFormula and pMatFormula, overriding matrix formula dimension; intended?");
                pMatFormula->SetMatColsRows( pNewMatFormula->GetMatCols(),
                        pNewMatFormula->GetMatRows());
            }
            pMatFormula->Assign( *pMatResult);
            p->DecRef();
        }
        else if (p)
        {
            // This may be the result of some constant expression like
            // {="string"} that doesn't result in a matrix but still would
            // display the result in all cells of this matrix formula.
            pMatFormula->Assign( *p);
            p->DecRef();
        }
        else
        {
            // NULL result? Well, if you say so ...
            pMatFormula->ResetResult();
        }
    }
    else
    {
        if (mbToken && mpToken)
            mpToken->DecRef();
        ResolveToken( p);
    }
}


inline void ScFormulaResult::SetDouble( double f )
{
    ResetToDefaults();
    // Handle a result obtained from the interpreter to be assigned to a matrix
    // formula cell's ScMatrixFormulaCellToken.
    ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
    if (pMatFormula)
        pMatFormula->SetUpperLeftDouble( f);
    else
    {
        if (mbToken && mpToken)
            mpToken->DecRef();
        mfValue = f;
        mbToken = false;
        meMultiline = MULTILINE_FALSE;
    }
}


inline formula::StackVar ScFormulaResult::GetType() const
{
    // Order is significant.
    if (mnError)
        return formula::svError;
    if (mbEmpty)
        return formula::svEmptyCell;
    if (!mbToken)
        return formula::svDouble;
    if (mpToken)
        return mpToken->GetType();
    return formula::svUnknown;
}


inline formula::StackVar ScFormulaResult::GetCellResultType() const
{
    formula::StackVar sv = GetType();
    if (sv == formula::svMatrixCell)
        // don't need to test for mpToken here, GetType() already did it
        sv = static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftType();
    return sv;
}


inline bool ScFormulaResult::IsEmptyDisplayedAsString() const
{
    if (mbEmpty)
        return mbEmptyDisplayedAsString;
    if (GetType() == formula::svMatrixCell)
    {
        // don't need to test for mpToken here, GetType() already did it
        const ScEmptyCellToken* p = dynamic_cast<const ScEmptyCellToken*>(
                static_cast<const ScMatrixCellResultToken*>(
                    mpToken)->GetUpperLeftToken().operator->());
        if (p)
            return p->IsDisplayedAsString();
    }
    return false;
}


inline bool ScFormulaResult::IsValue() const
{
    formula::StackVar sv = GetCellResultType();
    return sv == formula::svDouble || sv == formula::svError || sv == formula::svEmptyCell;
}

inline bool ScFormulaResult::IsMultiline() const
{
    if (meMultiline == MULTILINE_UNKNOWN)
    {
        const String& rStr = GetString();
        if (rStr.Len() && rStr.Search( _LF ) != STRING_NOTFOUND)
            const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_TRUE;
        else
            const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_FALSE;
    }
    return meMultiline == MULTILINE_TRUE;
}


inline sal_uInt16 ScFormulaResult::GetResultError() const
{
    if (mnError)
        return mnError;
    formula::StackVar sv = GetCellResultType();
    if (sv == formula::svError)
    {
        if (GetType() == formula::svMatrixCell)
            // don't need to test for mpToken here, GetType() already did it
            return static_cast<const ScMatrixCellResultToken*>(mpToken)->
                GetUpperLeftToken()->GetError();
        if (mpToken)
            return mpToken->GetError();
    }
    return 0;
}


inline void ScFormulaResult::SetResultError( sal_uInt16 nErr )
{
    mnError = nErr;
}


inline formula::FormulaConstTokenRef ScFormulaResult::GetToken() const
{
    if (mbToken)
        return mpToken;
    return NULL;
}


inline formula::FormulaConstTokenRef ScFormulaResult::GetCellResultToken() const
{
    if (GetType() == formula::svMatrixCell)
        // don't need to test for mpToken here, GetType() already did it
        return static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftToken();
    return GetToken();
}


inline double ScFormulaResult::GetDouble() const
{
    if (mbToken)
    {
        // Should really not be of type formula::svDouble here.
        if (mpToken)
        {
            switch (mpToken->GetType())
            {
                case formula::svHybridCell:
                    return mpToken->GetDouble();
                case formula::svMatrixCell:
                    {
                        const ScMatrixCellResultToken* p =
                            static_cast<const ScMatrixCellResultToken*>(mpToken);
                        if (p->GetUpperLeftType() == formula::svDouble)
                            return p->GetUpperLeftToken()->GetDouble();
                    }
                    break;
                default:
                    ;   // nothing
            }
        }
        return 0.0;
    }
    if (mbEmpty)
        return 0.0;
    return mfValue;
}


inline const String & ScFormulaResult::GetString() const
{
    if (mbToken && mpToken)
    {
        switch (mpToken->GetType())
        {
            case formula::svString:
            case formula::svHybridCell:
                return mpToken->GetString();
            case formula::svMatrixCell:
                {
                    const ScMatrixCellResultToken* p =
                        static_cast<const ScMatrixCellResultToken*>(mpToken);
                    if (p->GetUpperLeftType() == formula::svString)
                        return p->GetUpperLeftToken()->GetString();
                }
                break;
            default:
                ;   // nothing
        }
    }
    return EMPTY_STRING;
}


inline ScConstMatrixRef ScFormulaResult::GetMatrix() const
{
    if (GetType() == formula::svMatrixCell)
        return static_cast<const ScToken*>(mpToken)->GetMatrix();
    return NULL;
}


inline const String & ScFormulaResult::GetHybridFormula() const
{
    if (GetType() == formula::svHybridCell)
    {
        const ScHybridCellToken* p = dynamic_cast<const ScHybridCellToken*>(mpToken);
        if (p)
            return p->GetFormula();
    }
    return EMPTY_STRING;
}


inline void ScFormulaResult::SetHybridDouble( double f )
{
    ResetToDefaults();
    if (mbToken && mpToken)
    {
        String aString( GetString());
        String aFormula( GetHybridFormula());
        mpToken->DecRef();
        mpToken = new ScHybridCellToken( f, aString, aFormula);
        mpToken->IncRef();
    }
    else
    {
        mfValue = f;
        mbToken = false;
        meMultiline = MULTILINE_FALSE;
    }
}


inline void ScFormulaResult::SetHybridString( const String & rStr )
{
    // Obtain values before changing anything.
    double f = GetDouble();
    String aFormula( GetHybridFormula());
    ResetToDefaults();
    if (mbToken && mpToken)
        mpToken->DecRef();
    mpToken = new ScHybridCellToken( f, rStr, aFormula);
    mpToken->IncRef();
    mbToken = true;
}


inline void ScFormulaResult::SetHybridFormula( const String & rFormula )
{
    // Obtain values before changing anything.
    double f = GetDouble();
    String aStr( GetString());
    ResetToDefaults();
    if (mbToken && mpToken)
        mpToken->DecRef();
    mpToken = new ScHybridCellToken( f, aStr, rFormula);
    mpToken->IncRef();
    mbToken = true;
}


inline const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() const
{
    return (GetType() == formula::svMatrixCell ?
            dynamic_cast<const ScMatrixFormulaCellToken*>(mpToken) : NULL);
}


inline ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellTokenNonConst()
{
    return const_cast<ScMatrixFormulaCellToken*>( GetMatrixFormulaCellToken());
}


#endif // SC_FORMULARESULT_HXX
