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


import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.felix.das.util.DriverLoader;
import org.apache.felix.das.util.DriverMatcher;
import org.apache.felix.das.util.Util;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.device.Constants;
import org.osgi.service.device.Device;
import org.osgi.service.device.Driver;
import org.osgi.service.device.DriverLocator;
import org.osgi.service.device.DriverSelector;
import org.osgi.service.device.Match;
import org.osgi.service.log.LogService;


/**
 * This class represents the Apache Felix implementation of the device access specification.
 * It is based on version 1.1 of the spec.
 * 
 * 
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class DeviceManager implements Log
{

    private final long DEFAULT_TIMEOUT_SEC = 1;

    // the logger
    private volatile LogService m_log;

    // the bundle context
    private final BundleContext m_context;

    // the driver selector
    private volatile DriverSelector m_selector;

    // the driver locators
    private List<DriverLocator> m_locators;

    // the devices
    private Map<ServiceReference, Object> m_devices;

    // the drivers
    private Map<ServiceReference, DriverAttributes> m_drivers;

    // performs all the background actions
    private ExecutorService m_worker;

    // used to add delayed actions
    private ScheduledExecutorService m_delayed;

    //the devices filter
    private Filter m_deviceImplFilter;

    //the drivers filter
    private Filter m_driverImplFilter;


    /**
     * Public constructor. Used by the Activator in this <code>Bundle</code>
     * to instantiate one instance.
     * 
     * @param context the <code>BundleContext</code>
     */
    public DeviceManager( BundleContext context )
    {
        m_context = context;
    }


    public void debug( String message )
    {
        m_log.log( LogService.LOG_DEBUG, message );
    }


    public void info( String message )
    {
        m_log.log( LogService.LOG_INFO, message );
    }


    public void warning( String message )
    {
        m_log.log( LogService.LOG_WARNING, message );
    }


    public void error( String message, Throwable e )
    {
        System.err.println( message );
        if ( e != null )
        {
            e.printStackTrace();
        }
        m_log.log( LogService.LOG_ERROR, message, e );
    }


    // dependency manager methods
    @SuppressWarnings("unused")
    private void init() throws InvalidSyntaxException
    {
        m_locators = Collections.synchronizedList( new ArrayList<DriverLocator>() );
        m_worker = Executors.newSingleThreadExecutor( new NamedThreadFactory( "Apache Felix Device Manager" ) );
        m_delayed = Executors.newScheduledThreadPool( 1, new NamedThreadFactory(
            "Apache Felix Device Manager - delayed" ) );
        m_deviceImplFilter = Util.createFilter( "(%s=%s)", new Object[]
            { org.osgi.framework.Constants.OBJECTCLASS, Device.class.getName() } );
        m_driverImplFilter = Util.createFilter( "(%s=%s)", new Object[]
            { org.osgi.framework.Constants.OBJECTCLASS, Driver.class.getName() } );
    }


    @SuppressWarnings("unused")
    private void start()
    {
        m_drivers = new HashMap<ServiceReference, DriverAttributes>();
        m_devices = new HashMap<ServiceReference, Object>();
        submit( new WaitForStartFramework() );
    }


    public void stop()
    {
        // nothing to do ?
    }


    public void destroy()
    {
        m_worker.shutdownNow();
        m_delayed.shutdownNow();
    }


    // callback methods

    public void selectorAdded( DriverSelector selector )
    {
        m_selector = selector;
        debug( "driver selector appeared" );
    }


    public void selectorRemoved( DriverSelector selector )
    {
        m_selector = null;
        debug( "driver selector lost" );
    }
    
    public void locatorAdded( DriverLocator locator )
    {
        m_locators.add( locator );
        debug( "driver locator appeared" );
    }


    public void locatorRemoved( DriverLocator locator )
    {
        m_locators.remove( locator );
        debug( "driver locator lost" );
    }


    public void driverAdded( ServiceReference ref, Object obj )
    {
        final Driver driver = Driver.class.cast( obj );
        m_drivers.put( ref, new DriverAttributes( ref, driver ) );

        debug( "driver appeared: " + Util.showDriver( ref ) );
        
        //immediately check for idle devices
        submit( new CheckForIdleDevices() );
    }

    public void driverModified( ServiceReference ref, Object obj )
    {
        final Driver driver = Driver.class.cast( obj );
        
        debug( "driver modified: " + Util.showDriver( ref ) );
        m_drivers.remove( ref );
        m_drivers.put( ref , new DriverAttributes( ref, driver ) );

        // check if devices have become idle
        // after some time
        schedule( new CheckForIdleDevices() );
    }

    public void driverRemoved( ServiceReference ref )
    {
        debug( "driver lost: " + Util.showDriver( ref ) );
        m_drivers.remove( ref );

        // check if devices have become idle
        // after some time
        schedule( new CheckForIdleDevices() );

    }


    public void deviceAdded( ServiceReference ref, Object device )
    {
        m_devices.put( ref, device );
        debug( "device appeared: " + Util.showDevice( ref ) );
        submit( new DriverAttachAlgorithm( ref, device ) );
    }


    public void deviceModified( ServiceReference ref, Object device )
    {
        debug( "device modified: " + Util.showDevice( ref ) );
        // nothing further to do ?
        // DeviceAttributes da = m_devices.get(ref);
        // submit(new DriverAttachAlgorithm(da));
    }


    public void deviceRemoved( ServiceReference ref )
    {
        debug( "device removed: " + Util.showDevice( ref ) );
        m_devices.remove( ref );
        // nothing further to do ?
        // the services that use this
        // device should track it.
    }


    /**
     * perform this task as soon as possible.
     * 
     * @param task
     *            the task
     */
    private void submit( Callable<Object> task )
    {
        m_worker.submit( new LoggedCall( task ) );
    }


    /**
     * perform this task after the default delay.
     * 
     * @param task
     *            the task
     */
    private void schedule( Callable<Object> task )
    {
        m_delayed.schedule( new DelayedCall( task ), DEFAULT_TIMEOUT_SEC, TimeUnit.SECONDS );
    }

    // worker callables

    /**
     * Callable used to start the DeviceManager. It either waits (blocking the
     * worker thread) for the framework to start, or if it has already started,
     * returns immediately, freeing up the worker thread.
     * 
     * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
     */
    private class WaitForStartFramework implements Callable<Object>, FrameworkListener
    {

        private final CountDownLatch m_latch = new CountDownLatch( 1 );


        public Object call() throws Exception
        {
            boolean addedAsListener = false;
            if ( m_context.getBundle( 0 ).getState() == Bundle.ACTIVE )
            {
                m_latch.countDown();
                debug( "Starting Device Manager immediately" );
            }
            else
            {
                m_context.addFrameworkListener( this );
                addedAsListener = true;
                debug( "Waiting for framework to start" );
            }

            m_latch.await();
            for ( Map.Entry<ServiceReference, Object> entry : m_devices.entrySet() )
            {
                submit( new DriverAttachAlgorithm( entry.getKey(), entry.getValue() ) );
            }
            // cleanup
            if ( addedAsListener )
            {
                m_context.removeFrameworkListener( this );
            }
            return null;
        }


        // FrameworkListener method
        public void frameworkEvent( FrameworkEvent event )
        {
            switch ( event.getType() )
            {
                case FrameworkEvent.STARTED:
                    debug( "Framework has started" );
                    m_latch.countDown();
                    break;
            }
        }


        @Override
        public String toString()
        {
            return getClass().getSimpleName();
        }
    }

    private class LoggedCall implements Callable<Object>
    {

        private final Callable<Object> m_call;


        public LoggedCall( Callable<Object> call )
        {
            m_call = call;
        }


        private String getName()
        {
            return m_call.getClass().getSimpleName();
        }


        public Object call() throws Exception
        {

            try
            {
                return m_call.call();
            }
            catch ( Exception e )
            {
                error( "call failed: " + getName(), e );
                throw e;
            }
            catch ( Throwable e )
            {
                error( "call failed: " + getName(), e );
                throw new RuntimeException( e );
            }
        }

    }

    private class DelayedCall implements Callable<Object>
    {

        private final Callable<Object> m_call;


        public DelayedCall( Callable<Object> call )
        {
            m_call = call;
        }


        private String getName()
        {
            return m_call.getClass().getSimpleName();
        }


        public Object call() throws Exception
        {
            info( "Delayed call: " + getName() );
            return m_worker.submit( m_call );
        }
    }

    /**
     * Checks for Idle devices, and attaches them
     * 
     * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
     */
    private class CheckForIdleDevices implements Callable<Object>
    {

        public Object call() throws Exception
        {
            debug( "START - check for idle devices" );
            for ( ServiceReference ref : getIdleDevices() )
            {
                info( "IDLE: " + ref.getBundle().getSymbolicName() );
                submit( new DriverAttachAlgorithm( ref, m_devices.get( ref ) ) );
            }

            submit( new IdleDriverUninstallAlgorithm() );
            debug( "STOP - check for idle devices" );
            return null;
        }


        /**
         * get a list of all idle devices.
         * 
         * @return
         */
        private List<ServiceReference> getIdleDevices()
        {
            List<ServiceReference> list = new ArrayList<ServiceReference>();

            for ( ServiceReference ref : m_devices.keySet() )
            {
                info( "checking if idle: " + ref.getBundle().getSymbolicName() );

                final Bundle[] usingBundles = ref.getUsingBundles();
                for ( Bundle bundle : usingBundles )
                {
                    if ( isDriverBundle( bundle ) )
                    {
                        info( "used by driver: " + bundle.getSymbolicName() );
                        debug( "not idle: " + ref.getBundle().getSymbolicName() );
                        break;
                    }
                    
                    list.add( ref );

                }
            }
            return list;
        }
    }


    private boolean isDriverBundle( Bundle bundle )
    {
        ServiceReference[] refs = bundle.getRegisteredServices();
        
        if (refs == null) {
            return false;
        }
        
        for ( ServiceReference ref : refs )
        {
            if ( m_driverImplFilter.match( ref ) )
            {
                return true;
            }
        }
        return false;
    }

    /**
     * 
     * Used to uninstall unused drivers
     * 
     * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
     */
    private class IdleDriverUninstallAlgorithm implements Callable<Object>
    {

        public Object call() throws Exception
        {

            info( "cleaning driver cache" );
            for ( DriverAttributes da : m_drivers.values() )
            {
                // just call the tryUninstall; the da itself
                // will know if it should really uninstall the driver.
                try 
                { 
                	da.tryUninstall(); 
                }
                catch (Exception e) 
                {
                	debug(da.getDriverId() + " uninstall failed");
                }
            }

            return null;
        }
    }

    private class DriverAttachAlgorithm implements Callable<Object>
    {

        private final ServiceReference m_ref;

        private final Device m_device;

        private List<DriverAttributes> m_included;

        private List<DriverAttributes> m_excluded;

        private final DriverLoader m_driverLoader;

        private DriverAttributes m_finalDriver;


        public DriverAttachAlgorithm( ServiceReference ref, Object obj )
        {
            m_ref = ref;
            if ( m_deviceImplFilter.match( ref ) )
            {
                m_device = Device.class.cast( obj );
            }
            else
            {
                m_device = null;
            }

            m_driverLoader = new DriverLoader( DeviceManager.this, m_context );
        }


        @SuppressWarnings("all")
        private Dictionary createDictionary( ServiceReference ref )
        {
            final Properties p = new Properties();

            for ( String key : ref.getPropertyKeys() )
            {
                p.put( key, ref.getProperty( key ) );
            }
            return p;
        }


        @SuppressWarnings("all")
        public Object call() throws Exception
        {
            info( "finding suitable driver for: " + Util.showDevice( m_ref ) );

            final Dictionary dict = createDictionary( m_ref );

            // first create a copy of all the drivers that are already there.
            // during the process, drivers will be added, but also excluded.
            m_included = new ArrayList<DriverAttributes>( m_drivers.values() );
            m_excluded = new ArrayList<DriverAttributes>();

            // first find matching driver bundles
            // if there are no driver locators
            // we'll have to do with the drivers that were
            // added 'manually'
            Set<String> driverIds = m_driverLoader.findDrivers( m_locators, dict );

            // remove the driverIds that are already available
            for ( DriverAttributes da : m_drivers.values() )
            {
                driverIds.remove( da.getDriverId() );
            }
            driverIds.removeAll( m_drivers.keySet() );
            try
            {
            	debug("entering attach phase for " + Util.showDevice( m_ref ) );
                return driverAttachment( dict, driverIds.toArray( new String[0] ) );
            }
            finally
            {
                // unload loaded drivers
                // that were unnecessarily loaded
                m_driverLoader.unload( m_finalDriver );
            }
        }


        @SuppressWarnings("all")
        private Object driverAttachment( Dictionary dict, String[] driverIds ) throws Exception
        {
            m_finalDriver = null;

            // remove the excluded drivers
            m_included.removeAll( m_excluded );

            // now load the drivers
            List<ServiceReference> driverRefs = m_driverLoader.loadDrivers( m_locators, driverIds );
            // these are the possible driver references that have been added
            // add them to the list of included drivers
            for ( ServiceReference serviceReference : driverRefs )
            {
                DriverAttributes da = m_drivers.get( serviceReference );
                if ( da != null )
                {
                    m_included.add( da );
                }
            }

            // now start matching all drivers
            final DriverMatcher mi = new DriverMatcher( DeviceManager.this );

            for ( DriverAttributes driver : m_included )
            {
                try
                {
                    int match = driver.match( m_ref );
                    if ( match <= Device.MATCH_NONE ) 
                    {
                        continue;
                    }
                    mi.add( match, driver );
                }
                catch ( Throwable t )
                {
                    error( "match threw an exception", new Exception( t ) );
                }
            }

            // get the best match
            Match bestMatch = null;

            // local copy
            final DriverSelector selector = m_selector;
            
            if ( selector != null )
            {
                bestMatch = mi.selectBestMatch( m_ref, selector );
                if (bestMatch != null) {
                	debug(String.format("DriverSelector (%s) found best match: %s", selector.getClass().getName(), Util.showDriver(bestMatch.getDriver())));
                }
            }
            
            if (bestMatch == null) 
            {
                bestMatch = mi.getBestMatch();
            }

            if ( bestMatch == null )
            {
                noDriverFound();
                // really return
                return null;
            }

            String driverId = String.class.cast( bestMatch.getDriver().getProperty( Constants.DRIVER_ID ) );

            debug( "best match: " + driverId );
            m_finalDriver = m_drivers.get( bestMatch.getDriver() );

            if ( m_finalDriver == null )
            {
                error( "we found a driverId, but not the corresponding driver: " + driverId, null );
                noDriverFound();
                return null;
            }

            // here we get serious...
            try
            {
                debug( "attaching to: " + driverId );
                String newDriverId = m_finalDriver.attach( m_ref );
                if ( newDriverId == null )
                {
                    // successful attach
                    return null;
                }
                // its a referral
                info( "attach led to a referral to: " + newDriverId );
                m_excluded.add( m_finalDriver );
                return driverAttachment( dict, new String[]{ newDriverId } );
            }
            catch ( Throwable t )
            {
                error( "attach failed due to an exception", t );
            }
            m_excluded.add( m_finalDriver );
            return driverAttachment( dict, driverIds );
        }


        private void noDriverFound()
        {
            debug( "no suitable driver found for: " + Util.showDevice( m_ref ) );
            if ( m_device != null )
            {
                m_device.noDriverFound();
            }
        }


        @Override
        public String toString()
        {
            return getClass().getSimpleName();// + ": " +
            // Util.showDevice(m_ref);
        }

    }
}
