/*
 * 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.scr.integration.components.felix3680_2;


import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.runtime.ServiceComponentRuntime;
import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
import org.osgi.service.log.LogService;


public class Main implements Runnable
{
    private static final int LATCH_TIMEOUT = 10000;
    private volatile ComponentContext m_ctx;
    private volatile AtomicInteger m_counter = new AtomicInteger();
    private volatile CountDownLatch m_enabledLatch;
    private volatile CountDownLatch m_disabledLatch;
    private volatile LogService m_logService;
    private ServiceComponentRuntime m_scr;
    private final Executor m_exec = Executors.newFixedThreadPool( 12 );
    private volatile BundleContext m_bctx;
    volatile ConcurrentHashMap<Class, ServiceRegistration> m_registrations = new ConcurrentHashMap<Class, ServiceRegistration>();
    volatile Exception _bindStackTrace;

    private volatile boolean running = true;


    /**
     * Helper used to randomly enable or disable a list of components.
     */
    class RegistrationHelper
    {
        public void registerBCDEFGHIJK( Executor exec )
        {
            enableOrDisable( true );
        }


        public void unregisterBCDEFGHIJK( Executor exec )
        {
            enableOrDisable( false );
        }


        private void enableOrDisable( final boolean enable )
        {
            if ( enable )
            {
                register( B.class );
                register( C.class );
                register( D.class );
                register( E.class );
                register( F.class );
                register( G.class );
                register( H.class );
                register( I.class );
                register( J.class );
                register( K.class );
            }
            else
            {
                unregister( B.class );
                unregister( C.class );
                unregister( D.class );
                unregister( E.class );
                unregister( F.class );
                unregister( G.class );
                unregister( H.class );
                unregister( I.class );
                unregister( J.class );
                unregister( K.class );
            }
        }


        private void register( final Class clazz )
        {
            m_exec.execute( new Runnable()
            {
                public void run()
                {
                    try
                    {
                        Object instance = clazz.newInstance();
                        m_registrations.put( clazz, m_bctx.registerService( clazz.getName(), instance, null ) );
                        m_enabledLatch.countDown();
                    }
                    catch ( Throwable e )
                    {
                        m_logService.log( LogService.LOG_ERROR, "error while enabling " + clazz, e );
                    }
                }
            } );
        }


        private void unregister( final Class clazz )
        {
            m_exec.execute( new Runnable()
            {
                public void run()
                {
                    try
                    {
                        ServiceRegistration sr = m_registrations.remove( clazz );
                        sr.unregister();
                        m_disabledLatch.countDown();
                    }
                    catch ( Throwable e )
                    {
                        m_logService.log( LogService.LOG_ERROR, "error while enabling " + clazz, e );
                    }
                }
            } );
        }
    }


    void bindSCR( ServiceComponentRuntime scr )
    {
        m_scr = scr;
    }


    void bindLogService( LogService logService )
    {
        m_logService = logService;
    }


    void bindA( ServiceReference sr )
    {
        Exception trace = new Exception( "bindA (" + Thread.currentThread() + ")" );
        if ( _bindStackTrace != null )
        {
            m_logService.log( LogService.LOG_ERROR, "Already bound A from stacktrace:", _bindStackTrace );
            m_logService.log( LogService.LOG_ERROR, "Current stacktrace is:", trace );
            return;
        }

        _bindStackTrace = trace;

        A a = ( A ) m_ctx.locateService( "a", sr );
        if ( a == null )
        {
            throw new IllegalStateException( "bindA: bundleContext.getService returned null" );
        }
        if ( m_counter.incrementAndGet() != 1 )
        {
            throw new IllegalStateException( "bindA: invalid counter value: " + m_counter );
        }
        m_enabledLatch.countDown();
    }


    void unbindA( A a )
    {
        if ( m_counter.decrementAndGet() != 0 )
        {
            throw new IllegalStateException( "unbindA: invalid counter value: " + m_counter );
        }
        _bindStackTrace = null;
        m_disabledLatch.countDown();
    }


    void start( ComponentContext ctx )
    {
        m_ctx = ctx;
        m_bctx = ctx.getBundleContext();
        m_ctx.getBundleContext().registerService( Executor.class.getName(), m_exec, null );
        new Thread( this ).start();
    }

    void stop() throws InterruptedException
    {
        synchronized ( this )
        {
            running = false;
        }
        if (m_enabledLatch != null) 
        {
            m_enabledLatch.await( 1, TimeUnit.MILLISECONDS );
        }
        if (m_disabledLatch != null) 
        {
            m_disabledLatch.await( 1, TimeUnit.MILLISECONDS );
        }
    }


    public void run()
    {
        int loop = 0;
        while ( iterate() )
        {
            

            RegistrationHelper registry = new RegistrationHelper();
            registry.registerBCDEFGHIJK( m_exec );

            try
            {
                if ( !m_enabledLatch.await( LATCH_TIMEOUT, TimeUnit.MILLISECONDS ) )
                {
                    System.out.println( "Did not get A injected timely ... see logs.txt" );
                    m_logService.log( LogService.LOG_ERROR, "enableLatch TIMEOUT" );
                    m_logService.log(LogService.LOG_ERROR, dumpThreads());
                    dumpA();
                    System.exit( 1 );
                }
            }
            catch ( InterruptedException e )
            {
            }

            registry.unregisterBCDEFGHIJK( m_exec );
            try
            {
                if ( !m_disabledLatch.await( LATCH_TIMEOUT, TimeUnit.MILLISECONDS ) )
                {
                    System.out.println( "Could not disable components timely ... see logs.txt" );
                    m_logService.log( LogService.LOG_ERROR, "disableLatch TIMEOUT" );
                    m_logService.log(LogService.LOG_ERROR, dumpThreads());
                    dumpA();
                    System.exit( 1 );
                }
            }
            catch ( InterruptedException e )
            {
            }

            ++loop;
            if ( loop % 100 == 0 )
            {
                m_logService.log( LogService.LOG_INFO, "Performed " + loop + " tests." );
            }
        }
    }


    private synchronized boolean iterate()
    {
        if ( running )
        {
            m_enabledLatch = new CountDownLatch( 11 ); // 10 for registrations of B,C,D,E,F,G,H,I,J,K + 1 for Main.bindA
            m_disabledLatch = new CountDownLatch( 11 ); // 10 for unregistrations of B,C,D,E,F,G,H,I,J,K + 1 for Main.unbindA
        }
        return running;
    }

    private String dumpThreads()
    {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        StringBuffer b = new StringBuffer( "Thread dump\n" );
        ThreadInfo[] infos = threadMXBean.dumpAllThreads( threadMXBean.isObjectMonitorUsageSupported(), threadMXBean.isSynchronizerUsageSupported() );
        for ( int i = 0; i < infos.length; i++ )
        {
            ThreadInfo ti = infos[i];
            b.append( "\n\nThreadId: " ).append( ti.getThreadId() ).append( " : name: " ).append( ti.getThreadName() ).append( " State: " ).append( ti.getThreadState() );
            b.append( "\n  LockInfo: " ).append( ti.getLockInfo() ).append( " LockOwnerId: " ).append( ti.getLockOwnerId() ).append( " LockOwnerName: ").append( ti.getLockOwnerName() );
            StackTraceElement[] stackTrace = ti.getStackTrace();
            for (int j = 0; j < stackTrace.length; j++ )
            {
                b.append( "\n  " ).append( stackTrace[j] );
            }
        }
        return b.toString();
    }

    private void dumpA()
    {
        ComponentDescriptionDTO c = m_scr
            .getComponentDescriptionDTO(m_bctx.getBundle(), "org.apache.felix.scr.integration.components.felix3680_2.A" );
        m_logService.log( LogService.LOG_WARNING, "State of " + c.name + " enabled:" + m_scr.isComponentEnabled(c) + "\n" );
    }


}
