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

import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;

import org.apache.felix.dm.DependencyManager;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;

/**
 * OSGi service utilities.
 * 
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class ServiceUtil {
    /**
     * Useful when needing to provide empty service properties.
     */
    public final static Dictionary<String, Object> EMPTY_PROPERTIES = new Hashtable<>();
    
    /**
     * Defines service properties which must not be propagated from the dependencies to component service properties.
     */
    public final static Set<String> NOT_PROPAGATABLE_SERVICE_PROPERTIES = 
    		Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
    				Constants.SERVICE_ID,
    				Constants.SERVICE_RANKING,
    				Constants.SERVICE_BUNDLEID,
    				Constants.SERVICE_SCOPE,    				
    				Constants.OBJECTCLASS,
    				DependencyManager.ASPECT)));

    /**
     * Helper method used to convert a dictionary with untyped keys to a dictionary having a String key.
     * (this method is useful when converting a Properties object into a compatible Dictionary<String, Object>
     * object that is often needed in OSGI R6 API. 
     */
    @SuppressWarnings("unchecked")
	public static <K,V> Dictionary<K, V> toR6Dictionary(Dictionary<?,?> properties) {
    	return (Dictionary<K, V>) properties;
    }

    /**
     * Dump some service properties in a petty form.
     */
    public static void appendProperties(StringBuilder result, Dictionary<?, ?> properties) {
        if (properties != null && properties.size() > 0) {
            result.append("(");
            Enumeration<?> enumeration = properties.keys();
            while (enumeration.hasMoreElements()) {
                Object key = enumeration.nextElement();
                result.append(key.toString());
                result.append('=');
                Object value = properties.get(key);
                if (value instanceof String[]) {
                    String[] values = (String[]) value;
                    result.append('{');
                    for (int i = 0; i < values.length; i++) {
                        if (i > 0) {
                            result.append(',');
                        }
                        result.append(values[i].toString());
                    }
                    result.append('}');
                }
                else {
                    result.append(value.toString());
                }
                if (enumeration.hasMoreElements()) {
                    result.append(',');
                }
            }
            result.append(")");
        }
    }

    /**
     * Returns the service ranking of a service, based on its service reference. If
     * the service has a property specifying its ranking, that will be returned. If
     * not, the default ranking of zero will be returned.
     * 
     * @param ref the service reference to determine the ranking for
     * @return the ranking
     */
    public static int getRanking(ServiceReference<?> ref) {
        return getRankingAsInteger(ref).intValue();
    }
    
    /**
     * Returns the service ranking of a service, based on its service reference. If
     * the service has a property specifying its ranking, that will be returned. If
     * not, the default ranking of zero will be returned.
     * 
     * @param ref the service reference to determine the ranking for
     * @return the ranking
     */
    public static Integer getRankingAsInteger(ServiceReference<?> ref) {
        Integer rank = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
        if (rank != null) {
            return rank;
        }
        return new Integer(0);
    }
    
    /**
     * Returns the service ID of a service, based on its service reference. This
     * method is aware of service aspects as defined by the dependency manager and
     * will return the ID of the orginal service if you give it an aspect.
     * 
     * @param ref the service reference to determine the service ID of
     * @return the service ID
     */
    public static long getServiceId(ServiceReference<?> ref) {
        return getServiceIdAsLong(ref).longValue();
    }
    
    /**
     * Returns the service ID of a service, based on its service reference. This
     * method is aware of service aspects as defined by the dependency manager and
     * will return the ID of the orginal service if you give it an aspect.
     * 
     * @param ref the service reference to determine the service ID of
     * @return the service ID
     */
    public static Long getServiceIdAsLong(ServiceReference<?> ref) {
    	return getServiceIdObject(ref);
    }
    
    public static Long getServiceIdObject(ServiceReference<?> ref) {
        Long aid = (Long) ref.getProperty(DependencyManager.ASPECT);
        if (aid != null) {
            return aid;
        }
        Long sid = (Long) ref.getProperty(Constants.SERVICE_ID);
        if (sid != null) {
            return sid;
        }
        throw new IllegalArgumentException("Invalid service reference, no service ID found");
    }

    /**
     * Determines if the service is an aspect as defined by the dependency manager.
     * Aspects are defined by a property and this method will check for its presence.
     * 
     * @param ref the service reference
     * @return <code>true</code> if it's an aspect, <code>false</code> otherwise
     */
    public static boolean isAspect(ServiceReference<?> ref) {
        Long aid = (Long) ref.getProperty(DependencyManager.ASPECT);
        return (aid != null);
    }
    
    /**
     * Converts a service reference to a string, listing both the bundle it was
     * registered from and all properties.
     * 
     * @param ref the service reference
     * @return a string representation of the service
     */
    public static String toString(ServiceReference<?> ref) {
        if (ref == null) {
            return "ServiceReference[null]";
        }
        else {
            StringBuffer buf = new StringBuffer();
            Bundle bundle = ref.getBundle();
            if (bundle != null) {
                buf.append("ServiceReference[");
                buf.append(bundle.getBundleId());
                buf.append("]{");
            }
            else {
                buf.append("ServiceReference[unregistered]{");
            }
            buf.append(propertiesToString(ref, null));
            buf.append("}");
            return buf.toString();
        }
    }
    
    /**
     * Converts the properties of a service reference to a string.
     * 
     * @param ref the service reference
     * @param exclude a list of properties to exclude, or <code>null</code> to show everything
     * @return a string representation of the service properties
     */
    public static String propertiesToString(ServiceReference<?> ref, List<String> exclude) {
        StringBuffer buf = new StringBuffer();
        String[] keys = ref.getPropertyKeys();
        for (int i = 0; i < keys.length; i++) {
            if (i > 0) { 
                buf.append(','); 
            }
            buf.append(keys[i]);
            buf.append('=');
            Object val = ref.getProperty(keys[i]);
            if (exclude == null || !exclude.contains(val)) {
                if (val instanceof String[]) {
                    String[] valArray = (String[]) val;
                    StringBuffer valBuf = new StringBuffer();
                    valBuf.append('{');
                    for (int j = 0; j < valArray.length; j++) {
                        if (valBuf.length() > 1) {
                            valBuf.append(',');
                        }
                        valBuf.append(valArray[j].toString());
                    }
                    valBuf.append('}');
                    buf.append(valBuf);
                }
                else {
                    buf.append(val.toString());
                }
            }
        }
        return buf.toString();
    }
    
    /**
     * Wraps ServiceReference properties behind a Dictionary object.
     * @param ref the ServiceReference to wrap
     * @return a new Dictionary used to wrap the ServiceReference properties
     */
    public static Dictionary<String, Object> propertiesToDictionary(final ServiceReference<?> ref) {
        return new Dictionary<String, Object>() {
            private Dictionary<String, Object> m_wrapper;
            
            @Override
            public int size() {
                return getWrapper().size();
            }

            @Override
            public boolean isEmpty() {
                return getWrapper().isEmpty();
            }

            @Override
            public Enumeration<String> keys() {
                return getWrapper().keys();
            }

            @Override
            public Enumeration<Object> elements() {
                return getWrapper().elements();
            }

            @Override
            public Object get(Object key) {
                return ref.getProperty(key.toString());
            }

            @Override
            public Object put(String key, Object value) {
                throw new UnsupportedOperationException("Unmodified Dictionary.");
            }

            @Override
            public Object remove(Object key) {
                throw new UnsupportedOperationException("Unmodified Dictionary.");
            }
            
            @Override
            public String toString() {
                return getWrapper().toString();
            }
            
            private synchronized Dictionary<String, Object> getWrapper() {
                if (m_wrapper == null) {
                    m_wrapper = new Hashtable<String, Object>();
                    String[] keys = ref.getPropertyKeys();
                    for (String key : keys) {
                        m_wrapper.put(key, ref.getProperty(key));
                    }                    
                }
                return m_wrapper;
            }
        };
    }
}
