/**************************************************************
 * 
 * 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_svx.hxx"

#include "svx/DescriptionGenerator.hxx"
#include <com/sun/star/beans/PropertyState.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/XShapes.hpp>
#include <com/sun/star/drawing/XShapeDescriptor.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/style/XStyle.hpp>
#include <comphelper/processfactory.hxx>
#include <vos/mutex.hxx>
#include <vcl/svapp.hxx>

#include <com/sun/star/uno/Exception.hpp>

// Includes for string resources.
#ifndef _SVX_ACCESSIBILITY_HRC
#include "accessibility.hrc"
#endif
#include "svx/svdstr.hrc"
#include <svx/dialmgr.hxx>
#include <tools/string.hxx>

#include <svx/xdef.hxx>
#include "svx/unoapi.hxx"
#include "accessibility.hrc"
#include "DGColorNameLookUp.hxx"

using namespace ::rtl;
using namespace ::com::sun::star;


void SvxUnogetInternalNameForItem( const sal_Int16 nWhich, const rtl::OUString& rApiName, String& rInternalName ) throw();

namespace accessibility {


DescriptionGenerator::DescriptionGenerator (
    const uno::Reference<drawing::XShape>& xShape)
    : mxShape (xShape),
      mxSet (mxShape, uno::UNO_QUERY),
      mbIsFirstProperty (true)
{
}




DescriptionGenerator::~DescriptionGenerator (void)
{
}




void DescriptionGenerator::Initialize (sal_Int32 nResourceId)
{
    // Get the string from the resource for the specified id.
    OUString sPrefix;
    {
        ::vos::OGuard aGuard (::Application::GetSolarMutex());
        sPrefix = OUString (SVX_RESSTR (nResourceId));
    }

    // Forward the call with the resulting string.
    Initialize (sPrefix);
}




void DescriptionGenerator::Initialize (::rtl::OUString sPrefix)
{
    msDescription = sPrefix;
    if (mxSet.is())
    {
        {
            ::vos::OGuard aGuard (::Application::GetSolarMutex());

            msDescription.append (sal_Unicode (' '));
            msDescription.append (OUString (SVX_RESSTR(RID_SVXSTR_A11Y_WITH)));
            msDescription.append (sal_Unicode (' '));

            msDescription.append (OUString (SVX_RESSTR (RID_SVXSTR_A11Y_STYLE)));
            msDescription.append (sal_Unicode ('='));
        }

        try
        {
            if (mxSet.is())
            {
                uno::Any aValue = mxSet->getPropertyValue (OUString::createFromAscii ("Style"));
                uno::Reference<container::XNamed> xStyle (aValue, uno::UNO_QUERY);
                if (xStyle.is())
                    msDescription.append (xStyle->getName());
            }
            else
                msDescription.append (
                    OUString::createFromAscii("<no style>"));
        }
        catch (::com::sun::star::beans::UnknownPropertyException)
        {
            msDescription.append (
                OUString::createFromAscii("<unknown>"));
        }
    }
}




::rtl::OUString DescriptionGenerator::operator() (void)
{
    msDescription.append (sal_Unicode ('.'));
    return msDescription.makeStringAndClear();
}




void DescriptionGenerator::AddProperty (
    const OUString& sPropertyName,
    PropertyType aType,
    const sal_Int32 nLocalizedNameId,
    long nWhichId)
{
    OUString sLocalizedName;
    {
        ::vos::OGuard aGuard (::Application::GetSolarMutex());
        sLocalizedName = SVX_RESSTR (nLocalizedNameId);
    }
    AddProperty (sPropertyName, aType, sLocalizedName, nWhichId);
}




void DescriptionGenerator::AddProperty (const OUString& sPropertyName,
    PropertyType aType, const OUString& sLocalizedName, long nWhichId)
{
    uno::Reference<beans::XPropertyState> xState (mxShape, uno::UNO_QUERY);
    if (xState.is()
        && xState->getPropertyState(sPropertyName)!=beans::PropertyState_DEFAULT_VALUE)
        if (mxSet.is())
        {
            // Append a seperator from previous Properties.
            if ( ! mbIsFirstProperty)
                msDescription.append (sal_Unicode (','));
            else
            {
                ::vos::OGuard aGuard (::Application::GetSolarMutex());

                msDescription.append (sal_Unicode (' '));
                msDescription.append (OUString (SVX_RESSTR(RID_SVXSTR_A11Y_AND)));
                msDescription.append (sal_Unicode (' '));
                mbIsFirstProperty = false;
            }

            // Delegate to type specific property handling.
            switch (aType)
            {
                case COLOR:
                    AddColor (sPropertyName, sLocalizedName);
                    break;
                case INTEGER:
                    AddInteger (sPropertyName, sLocalizedName);
                    break;
                case STRING:
                    AddString (sPropertyName, sLocalizedName, nWhichId);
                    break;
                case FILL_STYLE:
                    AddFillStyle (sPropertyName, sLocalizedName);
                    break;
            }
        }
}




void DescriptionGenerator::AppendString (const ::rtl::OUString& sString)
{
    msDescription.append (sString);
}




void DescriptionGenerator::AddLineProperties (void)
{
    AddProperty (OUString::createFromAscii ("LineColor"),
        DescriptionGenerator::COLOR,
        SIP_XA_LINECOLOR);
    AddProperty (OUString::createFromAscii ("LineDashName"),
        DescriptionGenerator::STRING,
        SIP_XA_LINEDASH,
        XATTR_LINEDASH);
    AddProperty (OUString::createFromAscii ("LineWidth"),
        DescriptionGenerator::INTEGER,
        SIP_XA_LINEWIDTH);
}




/** The fill style is described by the property "FillStyle".  Depending on
    its value a hatch-, gradient-, or bitmap name is appended.
*/
void DescriptionGenerator::AddFillProperties (void)
{
    AddProperty (OUString::createFromAscii ("FillStyle"),
        DescriptionGenerator::FILL_STYLE,
        SIP_XA_FILLSTYLE);
}




void DescriptionGenerator::Add3DProperties (void)
{
    AddProperty (OUString::createFromAscii ("D3DMaterialColor"),
        DescriptionGenerator::COLOR,
        RID_SVXSTR_A11Y_3D_MATERIAL_COLOR);
    AddLineProperties ();
    AddFillProperties ();
}




void DescriptionGenerator::AddTextProperties (void)
{
    AddProperty (OUString::createFromAscii ("CharColor"),
        DescriptionGenerator::COLOR);
    AddFillProperties ();
}




/** Search for the given color in the global color table.  If found append
    its name to the description.  Otherwise append its RGB tuple.
*/
void DescriptionGenerator::AddColor (const OUString& sPropertyName,
    const OUString& sLocalizedName)
{
    msDescription.append (sLocalizedName);
    msDescription.append (sal_Unicode('='));

    try
    {

        long nValue(0);
        if (mxSet.is())
        {
            uno::Any aValue = mxSet->getPropertyValue (sPropertyName);
            aValue >>= nValue;
        }

        msDescription.append (DGColorNameLookUp::Instance().LookUpColor (nValue));
    }
    catch (::com::sun::star::beans::UnknownPropertyException)
    {
        msDescription.append (
            OUString::createFromAscii("<unknown>"));
    }
}




void DescriptionGenerator::AddUnknown (const OUString& /*sPropertyName*/,
    const OUString& sLocalizedName)
{
    //        uno::Any aValue = mxSet->getPropertyValue (sPropertyName);
    msDescription.append (sLocalizedName);
}




void DescriptionGenerator::AddInteger (const OUString& sPropertyName,
    const OUString& sLocalizedName)
{
    msDescription.append (sLocalizedName);
    msDescription.append (sal_Unicode('='));

    try
    {
        if (mxSet.is())
        {
            uno::Any aValue = mxSet->getPropertyValue (sPropertyName);
            long nValue = 0;
            aValue >>= nValue;
            msDescription.append (nValue);
        }
    }
    catch (::com::sun::star::beans::UnknownPropertyException)
    {
        msDescription.append (
            OUString::createFromAscii("<unknown>"));
    }
}




void DescriptionGenerator::AddString (const OUString& sPropertyName,
    const OUString& sLocalizedName, long nWhichId)
{
    msDescription.append (sLocalizedName);
    msDescription.append (sal_Unicode('='));

    try
    {
        if (mxSet.is())
        {
            uno::Any aValue = mxSet->getPropertyValue (sPropertyName);
            OUString sValue;
            aValue >>= sValue;

            if (nWhichId >= 0)
            {
                ::vos::OGuard aGuard (::Application::GetSolarMutex());
                String sLocalizedValue;
                SvxUnogetInternalNameForItem (sal::static_int_cast<sal_Int16>(nWhichId), 
                                              sValue, sLocalizedValue);
                msDescription.append (sLocalizedValue);
            }
            else
                msDescription.append (sValue);
        }
    }
    catch (::com::sun::star::beans::UnknownPropertyException)
    {
        msDescription.append (
            OUString::createFromAscii("<unknown>"));
    }
}




void DescriptionGenerator::AddFillStyle (const OUString& sPropertyName,
    const OUString& sLocalizedName)
{
    msDescription.append (sLocalizedName);
    msDescription.append (sal_Unicode('='));

    try
    {
        if (mxSet.is())
        {
            uno::Any aValue = mxSet->getPropertyValue (sPropertyName);
            drawing::FillStyle aFillStyle;
            aValue >>= aFillStyle;

            // Get the fill style name from the resource.
            OUString sFillStyleName;
            {
                ::vos::OGuard aGuard (::Application::GetSolarMutex());
                switch (aFillStyle)
                {
                    case drawing::FillStyle_NONE:
                        sFillStyleName = SVX_RESSTR(RID_SVXSTR_A11Y_FILLSTYLE_NONE);
                        break;
                    case drawing::FillStyle_SOLID:
                        sFillStyleName = SVX_RESSTR(RID_SVXSTR_A11Y_FILLSTYLE_SOLID);
                        break;
                    case drawing::FillStyle_GRADIENT:
                        sFillStyleName = SVX_RESSTR(RID_SVXSTR_A11Y_FILLSTYLE_GRADIENT);
                        break;
                    case drawing::FillStyle_HATCH:
                        sFillStyleName = SVX_RESSTR(RID_SVXSTR_A11Y_FILLSTYLE_HATCH);
                        break;
                    case drawing::FillStyle_BITMAP:
                        sFillStyleName = SVX_RESSTR(RID_SVXSTR_A11Y_FILLSTYLE_BITMAP);
                        break;
                    case drawing::FillStyle_MAKE_FIXED_SIZE:
                        break;
                }
            }
            msDescription.append (sFillStyleName);

            // Append the appropriate properties.
            switch (aFillStyle)
            {
                case drawing::FillStyle_NONE:
                    break;
                case drawing::FillStyle_SOLID:
                    AddProperty (OUString::createFromAscii ("FillColor"),
                        COLOR,
                        SIP_XA_FILLCOLOR);
                    break;
                case drawing::FillStyle_GRADIENT:
                    AddProperty (OUString::createFromAscii ("FillGradientName"),
                        STRING,
                        SIP_XA_FILLGRADIENT,
                        XATTR_FILLGRADIENT);
                    break;
                case drawing::FillStyle_HATCH:
                    AddProperty (OUString::createFromAscii ("FillColor"),
                        COLOR,
                        SIP_XA_FILLCOLOR);
                    AddProperty (OUString::createFromAscii ("FillHatchName"),
                        STRING,
                        SIP_XA_FILLHATCH,
                        XATTR_FILLHATCH);
                    break;
                case drawing::FillStyle_BITMAP:
                    AddProperty (OUString::createFromAscii ("FillBitmapName"),
                        STRING,
                        SIP_XA_FILLBITMAP,
                        XATTR_FILLBITMAP);
                    break;
                case drawing::FillStyle_MAKE_FIXED_SIZE:
                    break;
            }
        }
    }
    catch (::com::sun::star::beans::UnknownPropertyException)
    {
        msDescription.append (
            OUString::createFromAscii("<unknown>"));
    }
}




void DescriptionGenerator::AddPropertyNames (void)
{
    if (mxSet.is())
    {
        uno::Reference<beans::XPropertySetInfo> xInfo (mxSet->getPropertySetInfo());
        if (xInfo.is())
        {
            uno::Sequence<beans::Property> aPropertyList (xInfo->getProperties ());
            for (int i=0; i<aPropertyList.getLength(); i++)
            {
                msDescription.append (aPropertyList[i].Name);
                msDescription.append (sal_Unicode(','));
            }
        }
    }
}


} // end of namespace accessibility
