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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;

import org.apache.felix.scr.Component;
import org.apache.felix.scr.Reference;
import org.apache.felix.scr.ScrService;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.dto.ServiceReferenceDTO;
import org.osgi.service.component.ComponentInstance;
import org.osgi.service.component.runtime.ServiceComponentRuntime;
import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
import org.osgi.service.component.runtime.dto.ReferenceDTO;
import org.osgi.service.component.runtime.dto.SatisfiedReferenceDTO;

public class ScrServiceImpl implements ScrService
{

	private static final String[] EMPTY = {};

	private final BundleContext context;
	private final ServiceComponentRuntime runtime;


	public ScrServiceImpl(BundleContext context, final ServiceComponentRuntime runtime)
	{
        // we always use the system bundle to avoid problems if subsystems etc.
        // are used and the SCR implemented extends those "invisible" bundles
		this.context = context.getBundle(0).getBundleContext();
		this.runtime = runtime;
	}


	// ScrService

    /**
     * @see org.apache.felix.scr.ScrService#getComponents()
     */
    public Component[] getComponents()
    {
        return this.getComponents((Bundle)null);
    }


    /**
     * @see org.apache.felix.scr.ScrService#getComponents(org.osgi.framework.Bundle)
     */
    public Component[] getComponents( final Bundle bundle )
    {
        List<Component> result = new ArrayList<Component>();

        final Collection<ComponentDescriptionDTO> descriptions = this.runtime.getComponentDescriptionDTOs(bundle);
        for(final ComponentDescriptionDTO descDTO : descriptions )
        {
            final Collection<ComponentConfigurationDTO> configs = this.runtime.getComponentConfigurationDTOs(descDTO);
            ComponentConfigurationDTO configDTO = null;
            if ( !configs.isEmpty() )
            {
                configDTO = configs.iterator().next();
            }
            result.add(new ComponentWrapper(this.context, this.runtime, descDTO, configDTO));
        }

        return result.isEmpty() ? null : result.toArray( new Component[result.size()] );
    }


    /**
     * @see org.apache.felix.scr.ScrService#getComponent(long)
     */
    public Component getComponent( long componentId )
    {
        final Collection<ComponentDescriptionDTO> descriptions = this.runtime.getComponentDescriptionDTOs();
        for(final ComponentDescriptionDTO descDTO : descriptions )
        {
            final Collection<ComponentConfigurationDTO> configs = this.runtime.getComponentConfigurationDTOs(descDTO);
            for(final ComponentConfigurationDTO configDTO : configs)
            {
                if ( configDTO.id == componentId )
                {
                    return new ComponentWrapper(this.context, this.runtime, descDTO, configDTO);
                }
            }
        }

        return null;
    }

    /**
     * @see org.apache.felix.scr.ScrService#getComponents(java.lang.String)
     */
    public Component[] getComponents( final String componentName )
    {
        List<Component> result = new ArrayList<Component>();

        final Collection<ComponentDescriptionDTO> descriptions = this.runtime.getComponentDescriptionDTOs();
        for(final ComponentDescriptionDTO descDTO : descriptions )
        {
            if ( descDTO.name.equals(componentName) ) {
                final Collection<ComponentConfigurationDTO> configs = this.runtime.getComponentConfigurationDTOs(descDTO);
                ComponentConfigurationDTO configDTO = null;
                if ( !configs.isEmpty() )
                {
                    configDTO = configs.iterator().next();
                }
                result.add(new ComponentWrapper(this.context, this.runtime, descDTO, configDTO));
            }
        }

        return result.isEmpty() ? null : result.toArray( new Component[result.size()] );
    }


    private static final class ComponentWrapper implements Component
    {
        private final ComponentDescriptionDTO description;

        private final ComponentConfigurationDTO configuration;

        private final BundleContext bundleContext;

        private final ServiceComponentRuntime runtime;

        public ComponentWrapper(final BundleContext bundleContext,
                final ServiceComponentRuntime runtime,
                final ComponentDescriptionDTO description,
                final ComponentConfigurationDTO configuration)
        {
            this.bundleContext = bundleContext;
            this.description = description;
            this.configuration = configuration;
            this.runtime = runtime;
        }

        public long getId()
        {
            return configuration != null ? configuration.id : -1;
        }

        public String getName()
        {
            return description.name;
        }

        public int getState()
        {
            if ( configuration == null )
            {
                return Component.STATE_UNSATISFIED; // TODO Check!
            }
            final int s = configuration.state;
            switch ( s )
            {
                case ComponentConfigurationDTO.ACTIVE : return Component.STATE_ACTIVE;
                case ComponentConfigurationDTO.SATISFIED : return Component.STATE_ENABLED;
                case ComponentConfigurationDTO.UNSATISFIED_CONFIGURATION : return Component.STATE_UNSATISFIED;
                case ComponentConfigurationDTO.UNSATISFIED_REFERENCE : return Component.STATE_UNSATISFIED;
                default: // satisfied
                    return Component.STATE_ENABLED;
            }
        }

        public Bundle getBundle()
        {
            return this.bundleContext.getBundle(this.description.bundle.id);
        }

        public String getFactory()
        {
            return this.description.factory;
        }

        public boolean isServiceFactory()
        {
            return !"singleton".equals(this.description.scope);
        }

        public String getClassName()
        {
            return this.description.implementationClass;
        }

        public boolean isDefaultEnabled()
        {
            return this.description.defaultEnabled;
        }

        public boolean isImmediate()
        {
            return this.description.immediate;
        }

        public String[] getServices()
        {
            return this.description.serviceInterfaces;
        }

        public Dictionary getProperties()
        {
            return new Hashtable<String, Object>(this.description.properties);
        }

        public Reference[] getReferences()
        {
            if ( this.configuration == null )
            {
                return null;
            }

            final List<Reference> result = new ArrayList<Reference>();
            for(final ReferenceDTO dto : this.description.references)
            {
                SatisfiedReferenceDTO sRef = null;
                for(final SatisfiedReferenceDTO r : this.configuration.satisfiedReferences)
                {
                    if ( r.name.equals(dto.name) )
                    {
                        sRef = r;
                        break;
                    }
                }
                result.add(new ReferenceWrapper(this.bundleContext, dto, sRef));
            }

            if ( result.isEmpty() )
            {
                return null;
            }

            return result.toArray(new Reference[result.size()]);
        }

        public ComponentInstance getComponentInstance()
        {
            // returning null as we should have never returned this in the first place
            return null;
        }

        public String getActivate()
        {
            return this.description.activate;
        }

        public boolean isActivateDeclared()
        {
            return this.description.activate != null;
        }

        public String getDeactivate()
        {
            return this.description.deactivate;
        }

        public boolean isDeactivateDeclared()
        {
            return this.description.deactivate != null;
        }

        public String getModified()
        {
            return this.description.modified;
        }

        public String getConfigurationPolicy()
        {
            return this.description.configurationPolicy;
        }

        public String getConfigurationPid()
        {
            final String[] pids = this.description.configurationPid;
            return pids[0];
        }

        public boolean isConfigurationPidDeclared()
        {
            return true;
        }

        public void enable()
        {
            // noop as the old model was broken
        }

        public void disable()
        {
            // noop as the old model was broken
        }
    }

    private static final class ReferenceWrapper implements Reference
    {
        // constant for option single reference - 0..1
        private static final String CARDINALITY_0_1 = "0..1";

        // constant for option multiple reference - 0..n
        private static final String CARDINALITY_0_N = "0..n";

        // constant for required multiple reference - 1..n
        private static final String CARDINALITY_1_N = "1..n";

        // constant for static policy
        private static final String POLICY_STATIC = "static";

        // constant for reluctant policy option
        private static final String POLICY_OPTION_RELUCTANT = "reluctant";

        private final ReferenceDTO dto;

        private final SatisfiedReferenceDTO satisfiedDTO;

        private final BundleContext bundleContext;

        public ReferenceWrapper(
                final BundleContext bundleContext,
                final ReferenceDTO dto,
                final SatisfiedReferenceDTO satisfied)
        {
            this.bundleContext = bundleContext;
            this.dto = dto;
            this.satisfiedDTO = satisfied;
        }

        public String getName()
        {
            return dto.name;
        }

        public String getServiceName()
        {
            return dto.interfaceName;
        }

        public ServiceReference[] getServiceReferences()
        {
            if ( this.satisfiedDTO == null )
            {
                return null;
            }
            final List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>();
            for(ServiceReferenceDTO dto : this.satisfiedDTO.boundServices)
            {
                try
                {
                    final ServiceReference<?>[] serviceRefs = this.bundleContext.getServiceReferences((String)null,
                            "(" + Constants.SERVICE_ID + "=" + String.valueOf(dto.id) + ")");
                    if ( serviceRefs != null && serviceRefs.length > 0 )
                    {
                        refs.add(serviceRefs[0]);
                    }
                }
                catch ( final InvalidSyntaxException ise)
                {
                    // ignore
                }
            }
            return refs.toArray(new ServiceReference<?>[refs.size()]);
        }

        public ServiceReference<?>[] getBoundServiceReferences()
        {
            return this.getServiceReferences();
        }

        public boolean isSatisfied()
        {
            return this.satisfiedDTO != null;
        }

        public boolean isOptional()
        {
            return CARDINALITY_0_1.equals(dto.cardinality) || CARDINALITY_0_N.equals(dto.cardinality);
        }

        public boolean isMultiple()
        {
            return CARDINALITY_1_N.equals(dto.cardinality) || CARDINALITY_0_N.equals(dto.cardinality);
        }

        public boolean isStatic()
        {
            return POLICY_STATIC.equals(dto.policy);
        }

        public boolean isReluctant()
        {
            return POLICY_OPTION_RELUCTANT.equals(dto.policyOption);
        }

        public String getTarget()
        {
            return this.dto.target;
        }

        public String getBindMethodName()
        {
            return this.dto.bind;
        }

        public String getUnbindMethodName()
        {
            return this.dto.unbind;
        }

        public String getUpdatedMethodName()
        {
            return this.dto.unbind;
        }
    }
}
