/**************************************************************
 * 
 * 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_accessibility.hxx"
#include <accessibility/standard/vclxaccessiblebox.hxx>
#include <accessibility/standard/vclxaccessibletextfield.hxx>
#include <accessibility/standard/vclxaccessibleedit.hxx>
#include <accessibility/standard/vclxaccessiblelist.hxx>
#include <accessibility/helper/listboxhelper.hxx>

#include <unotools/accessiblestatesethelper.hxx>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <vcl/svapp.hxx>
#include <vcl/combobox.hxx>
#include <vcl/lstbox.hxx>
#include <accessibility/helper/accresmgr.hxx>
#include <accessibility/helper/accessiblestrings.hrc>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::accessibility;

VCLXAccessibleBox::VCLXAccessibleBox (VCLXWindow* pVCLWindow, BoxType aType, bool bIsDropDownBox)
    : VCLXAccessibleComponent (pVCLWindow),
      m_aBoxType (aType),
      m_bIsDropDownBox (bIsDropDownBox),
      m_nIndexInParent (DEFAULT_INDEX_IN_PARENT)
{
    // Set up the flags that indicate which children this object has.
    m_bHasListChild = true;

    // A text field is not present for non drop down list boxes.
    if ((m_aBoxType==LISTBOX) && ! m_bIsDropDownBox)
        m_bHasTextChild = false;
    else
        m_bHasTextChild = true;
}

VCLXAccessibleBox::~VCLXAccessibleBox (void)
{
}

void VCLXAccessibleBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
{
   	uno::Any aOldValue, aNewValue;
    uno::Reference<XAccessible> xAcc;

	switch ( rVclWindowEvent.GetId() )
	{
        case VCLEVENT_WINDOW_SHOW:
        case VCLEVENT_WINDOW_HIDE:
        {
            Window* pChildWindow = (Window *) rVclWindowEvent.GetData();
            // Just compare to the combo box text field.  All other children
            // are identical to this object in which case this object will
            // be removed in a short time.
            if (m_aBoxType==COMBOBOX)
            {
                ComboBox* pComboBox = static_cast<ComboBox*>(GetWindow());
                if ( ( pComboBox != NULL ) && ( pChildWindow != NULL ) )
                    if (pChildWindow == pComboBox->GetSubEdit())
                    {
                        if (rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW)
                        {
                            // Instantiate text field.
                            getAccessibleChild (0);
                            aNewValue <<= m_xText;
                        }
                        else
                        {
                            // Release text field.
                            aOldValue <<= m_xText;
                            m_xText = NULL;
                        }
                        // Tell the listeners about the new/removed child.
                        NotifyAccessibleEvent (
                            AccessibleEventId::CHILD,
                            aOldValue, aNewValue);
                    }

            }
        }
        break;

        default:
            VCLXAccessibleComponent::ProcessWindowChildEvent (rVclWindowEvent);
	}
}

void VCLXAccessibleBox::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent)
{
	switch ( rVclWindowEvent.GetId() )
	{
		case VCLEVENT_DROPDOWN_SELECT:
		case VCLEVENT_LISTBOX_SELECT:
		case VCLEVENT_LISTBOX_FOCUSITEMCHANGED:

		{
	            // Forward the call to the list child.
	            VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
	            if ( pList == NULL )
			{
				getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
				pList = static_cast<VCLXAccessibleList*>(m_xList.get());
			}
			if ( pList != NULL )
			{
				pList->ProcessWindowEvent (rVclWindowEvent, m_bIsDropDownBox);
				if(m_bIsDropDownBox)
				{
					NotifyAccessibleEvent(AccessibleEventId::VALUE_CHANGED, Any(), Any());
					Any aOldValue;
					Any aNewValue;
					aOldValue <<= AccessibleStateType::INDETERMINATE;
					NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue);

				}
			}
			break;
		}	
		case VCLEVENT_DROPDOWN_OPEN:
		{
	             VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
	             if ( pList == NULL )
			{
				getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
				pList = static_cast<VCLXAccessibleList*>(m_xList.get());
			}
			if ( pList != NULL )
			{
				pList->ProcessWindowEvent (rVclWindowEvent);
				pList->HandleDropOpen();
			}
			break;
		}
		case VCLEVENT_DROPDOWN_CLOSE:
		{
	             VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
	             if ( pList == NULL )
			{
				getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
				pList = static_cast<VCLXAccessibleList*>(m_xList.get());
			}
			if ( pList != NULL )
			{
				pList->ProcessWindowEvent (rVclWindowEvent);
			}
			Window* pWindow = GetWindow();
			if( pWindow && (pWindow->HasFocus() || pWindow->HasChildPathFocus()) )
			{
				Any aOldValue, aNewValue;
				aNewValue <<= AccessibleStateType::FOCUSED;
				NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );	
			}
			break;
		}
		case VCLEVENT_COMBOBOX_SELECT:
		{
	             VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
	             if (pList != NULL && m_xText.is())
	             {
		                Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
		                if ( xText.is() )
				{
					::rtl::OUString sText = xText->getSelectedText();
					if ( sText.isEmpty() )
						sText = xText->getText();
		                    pList->UpdateSelection_Acc (sText, m_bIsDropDownBox);
					//if(m_bIsDropDownBox && !pList->IsInDropDown())
					if (m_bIsDropDownBox || ( !m_bIsDropDownBox && m_aBoxType==COMBOBOX))
						NotifyAccessibleEvent(AccessibleEventId::VALUE_CHANGED, Any(), Any());

						Any aOldValue;
						Any aNewValue;
						aOldValue <<= AccessibleStateType::INDETERMINATE;
						NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue);

				}
	            	}			
			break;
		}
		//case VCLEVENT_DROPDOWN_OPEN:
		//case VCLEVENT_DROPDOWN_CLOSE:
		case VCLEVENT_LISTBOX_DOUBLECLICK:
		case VCLEVENT_LISTBOX_SCROLLED:
		//case VCLEVENT_LISTBOX_SELECT:
        case VCLEVENT_LISTBOX_ITEMADDED:
        case VCLEVENT_LISTBOX_ITEMREMOVED:
        case VCLEVENT_COMBOBOX_ITEMADDED:
        case VCLEVENT_COMBOBOX_ITEMREMOVED:
		case VCLEVENT_COMBOBOX_SCROLLED:
        {
            // Forward the call to the list child.
            VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
            if ( pList == NULL )
			{
				getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
				pList = static_cast<VCLXAccessibleList*>(m_xList.get());
			}
			if ( pList != NULL )
				pList->ProcessWindowEvent (rVclWindowEvent);
            break;
        }

		//case VCLEVENT_COMBOBOX_SELECT:
        case VCLEVENT_COMBOBOX_DESELECT:
        {
            // Selection is handled by VCLXAccessibleList which operates on
            // the same VCL object as this box does.  In case of the
            // combobox, however, we have to help the list with providing
            // the text of the currently selected item.
            VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
            if (pList != NULL && m_xText.is())
            {
                Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
                if ( xText.is() )
				{
					::rtl::OUString sText = xText->getSelectedText();
					if ( sText.isEmpty() )
						sText = xText->getText();
                    pList->UpdateSelection (sText);
				}
            }
			break;
        }

		case VCLEVENT_EDIT_MODIFY:
        case VCLEVENT_EDIT_SELECTIONCHANGED:
	 // case VCLEVENT_EDIT_CARETCHANGED:
            // Modify/Selection events are handled by the combo box instead of
            // directly by the edit field (Why?).  Therefore, delegate this
            // call to the edit field.
            if (m_aBoxType==COMBOBOX)
            {
                if (m_xText.is())
                {
                    Reference<XAccessibleContext> xContext = m_xText->getAccessibleContext();
                    VCLXAccessibleEdit* pEdit = static_cast<VCLXAccessibleEdit*>(xContext.get());
                    if (pEdit != NULL)
                        pEdit->ProcessWindowEvent (rVclWindowEvent);
                }
            }
            break;
		/*
		// MT: Not sending VCLEVENT_LISTBOX_STATEUPDATE, see comment in ListBox::SelectEntryPos
		case VCLEVENT_LISTBOX_STATEUPDATE:
		{
			// Need to update the INDETERMINATE state sometimes
			if (m_bIsDropDownBox && m_aBoxType==LISTBOX)
			{
				sal_Int32 nSelectedEntryCount = 0;
				ListBox* pListBox = static_cast< ListBox* >( GetWindow() );
				if (pListBox != NULL && pListBox->GetEntryCount() > 0)
				{
	        		nSelectedEntryCount = pListBox->GetSelectEntryCount();
					Any aOldValue;
					Any aNewValue;
					if ( nSelectedEntryCount == 0)
						aNewValue <<= AccessibleStateType::INDETERMINATE;
					else
						aOldValue <<= AccessibleStateType::INDETERMINATE;
					NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue);
				}
			}
			break;
		}
		*/
		default:
			VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
	}
}

IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleBox, VCLXAccessibleComponent, VCLXAccessibleBox_BASE)
IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleBox, VCLXAccessibleComponent, VCLXAccessibleBox_BASE)

//=====  XAccessible  =========================================================

Reference< XAccessibleContext > SAL_CALL VCLXAccessibleBox::getAccessibleContext(  )
	throw (RuntimeException)
{
	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

	return this;
}

//=====  XAccessibleContext  ==================================================

sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleChildCount (void)
    throw (RuntimeException)
{
	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    // Usually a box has a text field and a list of items as its children.
    // Non drop down list boxes have no text field.  Additionally check
    // whether the object is valid.
    sal_Int32 nCount = 0;
    if (IsValid())
        nCount += (m_bHasTextChild?1:0) + (m_bHasListChild?1:0);
    else
    {
        // Object not valid anymore.  Release references to children.
        m_bHasTextChild = false;
        m_xText = NULL;
        m_bHasListChild = false;
        m_xList = NULL;
    }

    return nCount;
}

Reference<XAccessible> SAL_CALL VCLXAccessibleBox::getAccessibleChild (sal_Int32 i)
    throw (IndexOutOfBoundsException, RuntimeException)
{
	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

	if (i<0 || i>=getAccessibleChildCount())
		throw IndexOutOfBoundsException();

	Reference< XAccessible > xChild;
    if (IsValid())
    {
        if (i==1 || ! m_bHasTextChild)
        {
            // List.
            if ( ! m_xList.is())
            {
                VCLXAccessibleList* pList = new VCLXAccessibleList ( GetVCLXWindow(),
					(m_aBoxType == LISTBOX ? VCLXAccessibleList::LISTBOX : VCLXAccessibleList::COMBOBOX),
																	this);
                pList->SetIndexInParent (i);
                m_xList = pList;
            }
            xChild = m_xList;
        }
        else
        {
            // Text Field.
            if ( ! m_xText.is())
            {
                if (m_aBoxType==COMBOBOX)
                {
                    ComboBox* pComboBox = static_cast<ComboBox*>(GetWindow());
                    if (pComboBox!=NULL && pComboBox->GetSubEdit()!=NULL)
					//Set the edit's acc name the same as parent
					{
						pComboBox->GetSubEdit()->SetAccessibleName(getAccessibleName());
                        m_xText = pComboBox->GetSubEdit()->GetAccessible();
					}
                }
                else if (m_bIsDropDownBox)
                    m_xText = new VCLXAccessibleTextField (GetVCLXWindow(),this);
            }
            xChild = m_xText;
        }
    }

    return xChild;
}

sal_Int16 SAL_CALL VCLXAccessibleBox::getAccessibleRole (void) throw (RuntimeException)
{
	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    // Return the role <const>COMBO_BOX</const> for both VCL combo boxes and
    // VCL list boxes in DropDown-Mode else <const>PANEL</const>.
	// This way the Java bridge has not to handle both independently.
    //return m_bIsDropDownBox ? AccessibleRole::COMBO_BOX : AccessibleRole::PANEL;
	if (m_bIsDropDownBox || (!m_bIsDropDownBox && m_aBoxType == COMBOBOX ))
		return AccessibleRole::COMBO_BOX;
	else
		return AccessibleRole::PANEL;
}

sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleIndexInParent (void)
    throw (::com::sun::star::uno::RuntimeException)
{
    if (m_nIndexInParent != DEFAULT_INDEX_IN_PARENT)
        return m_nIndexInParent;
    else
        return VCLXAccessibleComponent::getAccessibleIndexInParent();
}

//=====  XAccessibleAction  ===================================================

sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleActionCount (void)
    throw (RuntimeException)
{
	::osl::Guard< ::osl::Mutex> aGuard (GetMutex());

    // There is one action for drop down boxes (toggle popup) and none for
    // the other boxes.
	return m_bIsDropDownBox ? 1 : 0;
}

sal_Bool SAL_CALL VCLXAccessibleBox::doAccessibleAction (sal_Int32 nIndex)
    throw (IndexOutOfBoundsException, RuntimeException)
{
	sal_Bool bNotify = sal_False;

	{
		vos::OGuard aSolarGuard( Application::GetSolarMutex() );
		::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

        if (nIndex<0 || nIndex>=getAccessibleActionCount())
            throw ::com::sun::star::lang::IndexOutOfBoundsException();

		if (m_aBoxType == COMBOBOX)
        {
            ComboBox* pComboBox = static_cast< ComboBox* >( GetWindow() );
            if (pComboBox != NULL)
            {
                pComboBox->ToggleDropDown();
                bNotify = sal_True;
            }
        }
        else if (m_aBoxType == LISTBOX)
        {
            ListBox* pListBox = static_cast< ListBox* >( GetWindow() );
            if (pListBox != NULL)
            {
                pListBox->ToggleDropDown();
                bNotify = sal_True;
            }
        }
    }

	if (bNotify)
		NotifyAccessibleEvent (AccessibleEventId::ACTION_CHANGED, Any(), Any());

	return bNotify;
}

::rtl::OUString SAL_CALL VCLXAccessibleBox::getAccessibleActionDescription (sal_Int32 nIndex)
    throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
    if (nIndex<0 || nIndex>=getAccessibleActionCount())
        throw ::com::sun::star::lang::IndexOutOfBoundsException();

	return m_bIsDropDownBox ? TK_RES_STRING( RID_STR_ACC_ACTION_TOGGLEPOPUP) : ::rtl::OUString();
}

Reference< XAccessibleKeyBinding > VCLXAccessibleBox::getAccessibleActionKeyBinding( sal_Int32 nIndex )
	throw (IndexOutOfBoundsException, RuntimeException)
{
	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

	Reference< XAccessibleKeyBinding > xRet;

    if (nIndex<0 || nIndex>=getAccessibleActionCount())
        throw ::com::sun::star::lang::IndexOutOfBoundsException();

	// ... which key?
	return xRet;
}

//=====  XComponent  ==========================================================

void SAL_CALL VCLXAccessibleBox::disposing (void)
{
	VCLXAccessibleComponent::disposing();
}

// =====  XAccessibleValue  ===============================================
Any VCLXAccessibleBox::getCurrentValue( )
    throw( RuntimeException )
{
	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

	Any aAny;
	if( m_xList.is() && m_xText.is())
	{
		// VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
		Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
		if ( xText.is() )
		{
			::rtl::OUString sText = xText->getText();
			aAny <<= sText;
		}
	}
	if (m_aBoxType == LISTBOX && m_bIsDropDownBox  && m_xList.is() )
	{

		VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
		if(pList->IsInDropDown())
		{
			if(pList->getSelectedAccessibleChildCount()>0)
			{
				Reference<XAccessibleContext> xName (pList->getSelectedAccessibleChild((sal_Int32)(0)), UNO_QUERY);
				if(xName.is())
				{
					aAny <<= xName->getAccessibleName();
				}
			}
		}
	}
	 
    return aAny;
}

sal_Bool VCLXAccessibleBox::setCurrentValue( const Any& aNumber ) 
    throw( RuntimeException )
{
	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
	
    ::rtl::OUString  fValue;
    sal_Bool bValid = (aNumber >>= fValue);
    if( bValid )
    {

    }
    return bValid;

}

Any VCLXAccessibleBox::getMaximumValue( ) 
    throw( RuntimeException )
{
    Any aAny;
    return aAny;
}

Any VCLXAccessibleBox::getMinimumValue(  ) 
    throw( RuntimeException )
{
    Any aAny;
    return aAny;
}

// Set the INDETERMINATE state when there is no selected item for combobox
void VCLXAccessibleBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
{
	VCLXAccessibleComponent::FillAccessibleStateSet(rStateSet);
	if (m_aBoxType == COMBOBOX )
	{
		::rtl::OUString sText;
		sal_Int32 nEntryCount = 0;
		ComboBox* pComboBox = static_cast<ComboBox*>(GetWindow());
		if (pComboBox != NULL)
		{
			Edit* pSubEdit = pComboBox->GetSubEdit();
			if ( pSubEdit)
				sText = pSubEdit->GetText();
			nEntryCount = pComboBox->GetEntryCount();
		}
		if ( sText.isEmpty() && nEntryCount > 0 )
			rStateSet.AddState(AccessibleStateType::INDETERMINATE);
	}
	else if (m_aBoxType == LISTBOX && m_bIsDropDownBox == true)
	{
		sal_Int32 nSelectedEntryCount = 0;
		ListBox* pListBox = static_cast< ListBox* >( GetWindow() );
		if (pListBox != NULL && pListBox->GetEntryCount() > 0)
		{
	        	nSelectedEntryCount = pListBox->GetSelectEntryCount();
			if ( nSelectedEntryCount == 0)
				rStateSet.AddState(AccessibleStateType::INDETERMINATE);
		}
	}
}
