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



import com.sun.star.uno.Type;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.registry.XRegistryKey;
import com.sun.star.lang.XTypeProvider;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.XSingleServiceFactory;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.lang.XSingleComponentFactory;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lib.uno.helper.Factory;
import com.sun.star.comp.loader.FactoryHelper;
import com.sun.star.awt.XDialog;
import com.sun.star.awt.XDialogProvider2;
import com.sun.star.awt.XDialogEventHandler;
import com.sun.star.awt.XControl;
import com.sun.star.awt.XControlModel;
import com.sun.star.awt.XControlContainer;
import com.sun.star.beans.XPropertySet;
import com.sun.star.frame.XModel;
import com.sun.star.frame.XFrame;

import com.sun.star.awt.XToolkit;
import com.sun.star.awt.XWindowPeer;
import com.sun.star.awt.XMessageBox;
import com.sun.star.awt.WindowAttribute;
import com.sun.star.awt.WindowClass;
import com.sun.star.awt.WindowDescriptor;
import com.sun.star.awt.Rectangle;

import com.sun.star.test.XTestDialogHandler;

// DialogComponent implements all necessary interfaces self, this is only
// for demonstration. More convenient is to use the implementation WeakBase or
// ComponentBase, see implementation of TestComponentA.
public class DialogComponent {

	// public static class _DialogComponent extends WeakBase
	public static class _DialogComponent
		implements XTypeProvider, XServiceInfo, XTestDialogHandler, XDialogEventHandler {

		static final String __serviceName= "com.sun.star.test.TestDialogHandler";

		static byte[] _implementationId;
		private XComponentContext m_xCmpCtx;

		private XFrame m_xFrame;
		private XToolkit m_xToolkit;

		public _DialogComponent(XComponentContext context) {
			m_xCmpCtx= context;

			try {
				// Create the toolkit to have access to it later
				m_xToolkit = (XToolkit) UnoRuntime.queryInterface(
					XToolkit.class,
					m_xCmpCtx.getServiceManager().createInstanceWithContext("com.sun.star.awt.Toolkit",
																			m_xCmpCtx));
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}

		// XTestDialogHandler
		public String createDialog( String DialogURL, XModel xModel, XFrame xFrame ) {
			m_xFrame = xFrame;

			try {
				XMultiComponentFactory xMCF = m_xCmpCtx.getServiceManager();
				Object obj;

				// If valid we must pass the XModel when creating a DialogProvider object
				if( xModel != null ) {
					Object[] args = new Object[1];
					args[0] = xModel;

					obj = xMCF.createInstanceWithArgumentsAndContext(
						"com.sun.star.awt.DialogProvider2", args, m_xCmpCtx );
				}
				else {
					obj = xMCF.createInstanceWithContext(
						"com.sun.star.awt.DialogProvider2", m_xCmpCtx );
				}

				XDialogProvider2 xDialogProvider = (XDialogProvider2)
					UnoRuntime.queryInterface( XDialogProvider2.class, obj );

				XDialog xDialog = xDialogProvider.createDialogWithHandler( DialogURL, this );
				if( xDialog != null )
					xDialog.execute();
			}
			catch (Exception e) {
				e.printStackTrace();
			}
			return "Created dialog \"" + DialogURL + "\"";
		}

		public void copyText( XDialog xDialog, Object aEventObject ) {
			XControlContainer xControlContainer = (XControlContainer)UnoRuntime.queryInterface(
				XControlContainer.class, xDialog );
			String aTextPropertyStr = "Text";
			String aText = "";
			XControl xTextField1Control = xControlContainer.getControl( "TextField1" );
			XControlModel xControlModel1 = xTextField1Control.getModel();
			XPropertySet xPropertySet1 = (XPropertySet)UnoRuntime.queryInterface(
				XPropertySet.class, xControlModel1 );
			try
			{
				aText = (String)xPropertySet1.getPropertyValue( aTextPropertyStr );
			}
			catch (Exception e) {
				e.printStackTrace();
			}

			XControl xTextField2Control = xControlContainer.getControl( "TextField2" );
			XControlModel xControlModel2 = xTextField2Control.getModel();
			XPropertySet xPropertySet2 = (XPropertySet)UnoRuntime.queryInterface(
				XPropertySet.class, xControlModel2 );
			try
			{
				xPropertySet2.setPropertyValue( aTextPropertyStr, aText );
			}
			catch (Exception e) {
				e.printStackTrace();
			}

			showMessageBox( "DialogComponent", "copyText() called" );
		}

		public void handleEvent() {
			showMessageBox( "DialogComponent", "handleEvent() called" );
		}

		public void handleEventWithArguments( XDialog xDialog, Object aEventObject ) {
			showMessageBox( "DialogComponent", "handleEventWithArguments() called\n\n" +
				"Event Object = " + aEventObject );
		}

		private final String aHandlerMethod1 = "doit1";
		private final String aHandlerMethod2 = "doit2";
		private final String aHandlerMethod3 = "doit3";

		//XDialogEventHandler
		public boolean callHandlerMethod( /*IN*/XDialog xDialog, /*IN*/Object EventObject, /*IN*/String MethodName ) {
			if ( MethodName.equals( aHandlerMethod1 ) )
			{
				showMessageBox( "DialogComponent", "callHandlerMethod() handled \"" + aHandlerMethod1 + "\"" );
				return true;
			}
			else if ( MethodName.equals( aHandlerMethod2 ) )
			{
				showMessageBox( "DialogComponent", "callHandlerMethod() handled \"" + aHandlerMethod2 + "\"" );
				return true;
			}
			else if ( MethodName.equals( aHandlerMethod3 ) )
			{
				showMessageBox( "DialogComponent", "callHandlerMethod() handled \"" + aHandlerMethod3 + "\"" );
				return true;
			}
			return false;
		}

		public String[] getSupportedMethodNames() {
			String[] retValue= new String[3];
			retValue[0]= aHandlerMethod1;
			retValue[1]= aHandlerMethod2;
			retValue[2]= aHandlerMethod3;
			return retValue;
		}


		//XTypeProvider
		public com.sun.star.uno.Type[] getTypes(  ) {
			Type[] retValue= new Type[4];
			retValue[0]= new Type( XServiceInfo.class);
			retValue[1]= new Type( XTypeProvider.class);
			retValue[2]= new Type( XTestDialogHandler.class);
			retValue[3]= new Type( XDialogEventHandler.class);
			return retValue;
		}
		//XTypeProvider
		synchronized public byte[] getImplementationId(  ) {
			if (_implementationId == null) {
				_implementationId= new byte[16];
				int hash = hashCode();
				_implementationId[0] = (byte)(hash & 0xff);
				_implementationId[1] = (byte)((hash >>> 8) & 0xff);
				_implementationId[2] = (byte)((hash >>> 16) & 0xff);
				_implementationId[3] = (byte)((hash >>>24) & 0xff);
			}
			return _implementationId;
		}



		/** This method is a simple helper function to used in the
		 * static component initialisation functions as well as in
		 * getSupportedServiceNames.
		 */
		public static String[] getServiceNames() {
			String[] sSupportedServiceNames = { __serviceName };
			return sSupportedServiceNames;
		}

		//XServiceInfo
		public String[] getSupportedServiceNames() {
			return getServiceNames();
		}

		//XServiceInfo
		public boolean supportsService( String sServiceName ) {
			return sServiceName.equals( __serviceName );
		}

		//XServiceInfo
		public String getImplementationName() {
			// return DialogComponent.class.getName();
			return _DialogComponent.class.getName();
		}

		public void showMessageBox(String sTitle, String sMessage) {
			try {
				if ( null != m_xFrame && null != m_xToolkit ) {

					// describe window properties.
					WindowDescriptor aDescriptor = new WindowDescriptor();
					aDescriptor.Type              = WindowClass.MODALTOP;
					aDescriptor.WindowServiceName = new String( "infobox" );
					aDescriptor.ParentIndex       = -1;
					aDescriptor.Parent            = (XWindowPeer)UnoRuntime.queryInterface(
						XWindowPeer.class, m_xFrame.getContainerWindow());
					aDescriptor.Bounds            = new Rectangle(0,0,300,200);
					aDescriptor.WindowAttributes  = WindowAttribute.BORDER |
						WindowAttribute.MOVEABLE |
						WindowAttribute.CLOSEABLE;

					XWindowPeer xPeer = m_xToolkit.createWindow( aDescriptor );
					if ( null != xPeer ) {
						XMessageBox xMsgBox = (XMessageBox)UnoRuntime.queryInterface(
							XMessageBox.class, xPeer);
						if ( null != xMsgBox )
						{
							xMsgBox.setCaptionText( sTitle );
							xMsgBox.setMessageText( sMessage );
							xMsgBox.execute();
						}
					}
				}
			} catch ( com.sun.star.uno.Exception e) {
				// do your error handling
			}
		}
	}

    /**
     * Gives a factory for creating the service.
     * This method is called by the <code>JavaLoader</code>
     * <p>
     * @return  returns a <code>XSingleComponentFactory</code> for creating
     *          the component
     * @param   sImplName the name of the implementation for which a
     *          service is desired
     * @see     com.sun.star.comp.loader.JavaLoader
     */
    public static XSingleComponentFactory __getComponentFactory(String sImplName)
    {
        XSingleComponentFactory xFactory = null;

        if ( sImplName.equals( _DialogComponent.class.getName() ) )
            xFactory = Factory.createComponentFactory(_DialogComponent.class,
                                             _DialogComponent.getServiceNames());

        return xFactory;
    }

    /**
     * Writes the service information into the given registry key.
     * This method is called by the <code>JavaLoader</code>
     * <p>
     * @return  returns true if the operation succeeded
     * @param   regKey the registryKey
     * @see     com.sun.star.comp.loader.JavaLoader
     */
    // This method not longer necessary since OOo 3.4 where the component registration
    // was changed to passive component registration. For more details see
    // https://wiki.openoffice.org/wiki/Passive_Component_Registration

//    public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) {
//         return Factory.writeRegistryServiceInfo(_DialogComponent.class.getName(),
//                                                 _DialogComponent.getServiceNames(),
//                                                 regKey);
//    }
}
