/*
 * 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.
 */
package org.apache.felix.cm.integration;


import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

import org.apache.felix.cm.integration.helper.BaseTestActivator;
import org.apache.felix.cm.integration.helper.ManagedServiceTestActivator;
import org.apache.felix.cm.integration.helper.UpdateThreadSignalTask;
import org.junit.After;
import org.junit.Before;

import javax.inject.Inject;

import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.OptionUtils;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.ops4j.pax.exam.junit.ProbeBuilder;
import org.ops4j.pax.tinybundles.core.TinyBundles;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.util.tracker.ServiceTracker;

import static org.ops4j.pax.exam.CoreOptions.*;


public abstract class ConfigurationTestBase
{

    // the name of the system property providing the bundle file to be installed and tested
    protected static final String BUNDLE_JAR_SYS_PROP = "project.bundle.file";

    // the default bundle jar file name
    protected static final String BUNDLE_JAR_DEFAULT = "target/configadmin.jar";

    // the JVM option to set to enable remote debugging
    protected static final String DEBUG_VM_OPTION = "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=30303";

    // the actual JVM option set, extensions may implement a static
    // initializer overwriting this value to have the configuration()
    // method include it when starting the OSGi framework JVM
    protected static String paxRunnerVmOption = null;

    @Inject
    protected BundleContext bundleContext;

    protected Bundle bundle;

    protected ServiceTracker configAdminTracker;

    private Set<String> configurations = new HashSet<String>();

    protected static final String PROP_NAME = "theValue";
    protected static final Dictionary<String, String> theConfig;

    static
    {
        theConfig = new Hashtable<String, String>();
        theConfig.put( PROP_NAME, PROP_NAME );
    }


    @org.ops4j.pax.exam.junit.Configuration
    public static Option[] configuration()
    {
        final String bundleFileName = System.getProperty( BUNDLE_JAR_SYS_PROP, BUNDLE_JAR_DEFAULT );
        final File bundleFile = new File( bundleFileName );
        if ( !bundleFile.canRead() )
        {
            throw new IllegalArgumentException( "Cannot read from bundle file " + bundleFileName + " specified in the "
                + BUNDLE_JAR_SYS_PROP + " system property" );
        }

        final Option[] base = options(
                workingDirectory("target/paxexam/"),
                cleanCaches(true),
                junitBundles(),
                mavenBundle("org.ops4j.pax.tinybundles", "tinybundles", "1.0.0"),
                bundle(bundleFile.toURI().toString())
        );
        final Option option = ( paxRunnerVmOption != null ) ? vmOption( paxRunnerVmOption ) : null;
        return OptionUtils.combine( base, option );
    }


    @Before
    public void setUp()
    {
        configAdminTracker = new ServiceTracker( bundleContext, ConfigurationAdmin.class.getName(), null );
        configAdminTracker.open();
    }


    @After
    public void tearDown() throws BundleException
    {
        if ( bundle != null )
        {
            bundle.uninstall();
        }

        for ( String pid : configurations )
        {
            deleteConfig( pid );
        }

        configAdminTracker.close();
        configAdminTracker = null;
    }


    protected Bundle installBundle( final String pid ) throws BundleException
    {
        return installBundle( pid, ManagedServiceTestActivator.class );
    }


    protected Bundle installBundle( final String pid, final Class<?> activatorClass ) throws BundleException
    {
        return installBundle( pid, activatorClass, activatorClass.getName() );
    }


    @ProbeBuilder
    public TestProbeBuilder buildProbe( TestProbeBuilder builder ) {
        return builder.setHeader(Constants.EXPORT_PACKAGE, "org.apache.felix.cm.integration.helper");
    }

    protected Bundle installBundle( final String pid, final Class<?> activatorClass, final String location )
        throws BundleException
    {
        final String activatorClassName = activatorClass.getName();
        final InputStream bundleStream = TinyBundles.bundle()
                .set(Constants.BUNDLE_SYMBOLICNAME, activatorClassName)
                .set( Constants.BUNDLE_VERSION, "0.0.11" )
                .set( Constants.IMPORT_PACKAGE, "org.apache.felix.cm.integration.helper" )
                .set( Constants.BUNDLE_ACTIVATOR, activatorClassName )
                .set( BaseTestActivator.HEADER_PID, pid )
                .build( TinyBundles.withBnd() );

        try
        {
            return bundleContext.installBundle( location, bundleStream );
        }
        finally
        {
            try
            {
                bundleStream.close();
            }
            catch ( IOException ioe )
            {
            }
        }
    }


    protected void delay()
    {
        Object ca = configAdminTracker.getService();
        if ( ca != null )
        {
            try
            {

                Field caf = ca.getClass().getDeclaredField( "configurationManager" );
                caf.setAccessible( true );
                Object cm = caf.get( ca );

                Field cmf = cm.getClass().getDeclaredField( "updateThread" );
                cmf.setAccessible( true );
                Object ut = cmf.get( cm );

                Method utm = ut.getClass().getDeclaredMethod( "schedule" );
                utm.setAccessible( true );

                UpdateThreadSignalTask signalTask = new UpdateThreadSignalTask();
                utm.invoke( ut, signalTask );
                signalTask.waitSignal();

                return;
            }
            catch ( AssertionFailedError afe )
            {
                throw afe;
            }
            catch ( Throwable t )
            {
                // ignore any problem and revert to timed delay (might log this)
            }
        }

        // no configadmin or failure while setting up task
        try
        {
            Thread.sleep( 300 );
        }
        catch ( InterruptedException ie )
        {
            // dont care
        }
    }


    protected Bundle getCmBundle()
    {
        final ServiceReference caref = configAdminTracker.getServiceReference();
        return ( caref == null ) ? null : caref.getBundle();
    }


    protected ConfigurationAdmin getConfigurationAdmin()
    {
        ConfigurationAdmin ca = ( ConfigurationAdmin ) configAdminTracker.getService();
        if ( ca == null )
        {
            TestCase.fail( "Missing ConfigurationAdmin service" );
        }
        return ca;
    }


    protected Configuration configure( final String pid )
    {
        return configure( pid, null, true );
    }


    protected Configuration configure( final String pid, final String location, final boolean withProps )
    {
        final ConfigurationAdmin ca = getConfigurationAdmin();
        try
        {
            final Configuration config = ca.getConfiguration( pid, location );
            if ( withProps )
            {
                config.update( theConfig );
            }
            return config;
        }
        catch ( IOException ioe )
        {
            TestCase.fail( "Failed updating configuration " + pid + ": " + ioe.toString() );
            return null; // keep the compiler quiet
        }
    }


    protected Configuration createFactoryConfiguration( final String factoryPid )
    {
        return createFactoryConfiguration( factoryPid, null, true );
    }


    protected Configuration createFactoryConfiguration( final String factoryPid, final String location,
        final boolean withProps )
    {
        final ConfigurationAdmin ca = getConfigurationAdmin();
        try
        {
            final Configuration config = ca.createFactoryConfiguration( factoryPid, location );
            if ( withProps )
            {
                config.update( theConfig );
            }
            return config;
        }
        catch ( IOException ioe )
        {
            TestCase.fail( "Failed updating factory configuration " + factoryPid + ": " + ioe.toString() );
            return null; // keep the compiler quiet
        }
    }


    protected Configuration getConfiguration( final String pid )
    {
        final ConfigurationAdmin ca = getConfigurationAdmin();
        try
        {
            final String filter = "(" + Constants.SERVICE_PID + "=" + pid + ")";
            final Configuration[] configs = ca.listConfigurations( filter );
            if ( configs != null && configs.length > 0 )
            {
                return configs[0];
            }
        }
        catch ( InvalidSyntaxException ise )
        {
            // unexpected
        }
        catch ( IOException ioe )
        {
            TestCase.fail( "Failed listing configurations " + pid + ": " + ioe.toString() );
        }

        TestCase.fail( "No Configuration " + pid + " found" );
        return null;
    }


    protected void deleteConfig( final String pid )
    {
        final ConfigurationAdmin ca = getConfigurationAdmin();
        try
        {
            configurations.remove( pid );
            final Configuration config = ca.getConfiguration( pid );
            config.delete();
        }
        catch ( IOException ioe )
        {
            TestCase.fail( "Failed deleting configuration " + pid + ": " + ioe.toString() );
        }
    }


    protected void deleteFactoryConfigurations( String factoryPid )
    {
        ConfigurationAdmin ca = getConfigurationAdmin();
        try
        {
            final String filter = "(service.factoryPid=" + factoryPid + ")";
            Configuration[] configs = ca.listConfigurations( filter );
            if ( configs != null )
            {
                for ( Configuration configuration : configs )
                {
                    configurations.remove( configuration.getPid() );
                    configuration.delete();
                }
            }
        }
        catch ( InvalidSyntaxException ise )
        {
            // unexpected
        }
        catch ( IOException ioe )
        {
            TestCase.fail( "Failed deleting configurations " + factoryPid + ": " + ioe.toString() );
        }
    }
}
