/*
 * 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.connect.felix.framework;

import org.apache.felix.connect.Revision;
import org.osgi.dto.DTO;
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.Version;
import org.osgi.framework.dto.BundleDTO;
import org.osgi.framework.dto.FrameworkDTO;
import org.osgi.framework.dto.ServiceReferenceDTO;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.startlevel.FrameworkStartLevel;
import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleRevisions;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.framework.wiring.dto.BundleRevisionDTO;
import org.osgi.framework.wiring.dto.BundleWireDTO;
import org.osgi.framework.wiring.dto.BundleWiringDTO;
import org.osgi.framework.wiring.dto.FrameworkWiringDTO;
import org.osgi.framework.wiring.dto.BundleWiringDTO.NodeDTO;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
import org.osgi.resource.Wire;
import org.osgi.resource.Wiring;
import org.osgi.resource.dto.CapabilityDTO;
import org.osgi.resource.dto.CapabilityRefDTO;
import org.osgi.resource.dto.RequirementDTO;
import org.osgi.resource.dto.RequirementRefDTO;
import org.osgi.resource.dto.WireDTO;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Creates various DTOs provided by the core framework.
 */
public class DTOFactory
{
    private DTOFactory()
    {
        // Only static methods
    }

    public static <T> T createDTO(Bundle bundle, Class<T> type)
    {
        if (Bundle.UNINSTALLED == bundle.getState())
            return null;

        if (type == BundleDTO.class)
        {
            return type.cast(createBundleDTO(bundle));
        }
        else if (type == BundleStartLevelDTO.class)
        {
            return type.cast(createBundleStartLevelDTO(bundle));
        }
        else if (type == BundleRevisionDTO.class)
        {
            return type.cast(createBundleRevisionDTO(bundle));
        }
        else if (type == BundleRevisionDTO[].class)
        {
            return type.cast(createBundleRevisionDTOArray(bundle));
        }
        else if (type == BundleWiringDTO.class)
        {
            return type.cast(createBundleWiringDTO(bundle));
        }
        else if (type == BundleWiringDTO[].class)
        {
            return type.cast(createBundleWiringDTOArray(bundle));
        }
        else if (type == ServiceReferenceDTO[].class)
        {
            return type.cast(createServiceReferenceDTOArray(bundle));
        }
        else if (type == FrameworkDTO.class)
        {
            return type.cast(createFrameworkDTO(bundle));
        }
        else if (type == FrameworkStartLevelDTO.class && bundle instanceof Framework)
        {
            return type.cast(createFrameworkStartLevelDTO((Framework) bundle));
        }
        else if (type == FrameworkWiringDTO.class)
        {
            return type.cast(createFrameworkWiringDTO(bundle));
        }
        return null;
    }

    private static BundleDTO createBundleDTO(Bundle bundle)
    {
        BundleDTO dto = new BundleDTO();
        dto.id = bundle.getBundleId();
        dto.lastModified = bundle.getLastModified();
        dto.state = bundle.getState();
        dto.symbolicName = bundle.getSymbolicName();
        dto.version = "" + bundle.getVersion();
        return dto;
    }

    private static BundleRevisionDTO createBundleRevisionDTO(Bundle bundle)
    {
        BundleRevision br = bundle.adapt(BundleRevision.class);

        return createBundleRevisionDTO(bundle, br, new HashSet<BundleRevisionDTO>());
    }

    private static BundleRevisionDTO[] createBundleRevisionDTOArray(Bundle bundle)
    {
        BundleRevisions brs = bundle.adapt(BundleRevisions.class);
        if (brs == null || brs.getRevisions() == null)
            return null;

        List<BundleRevision> revisions = brs.getRevisions();
        BundleRevisionDTO[] dtos = new BundleRevisionDTO[revisions.size()];
        for (int i=0; i < revisions.size(); i++)
        {
                dtos[i] = createBundleRevisionDTO(bundle,revisions.get(i), new HashSet<BundleRevisionDTO>());
        }
        return dtos;
    }

    private static BundleRevisionDTO createBundleRevisionDTO(BundleRevision revision, Set<BundleRevisionDTO> resources)
    {
        return createBundleRevisionDTO(revision.getBundle(), revision, resources);
    }

    private static BundleRevisionDTO createBundleRevisionDTO(Bundle bundle, BundleRevision revision, Set<BundleRevisionDTO> resources)
    {
        BundleRevisionDTO dto = new BundleRevisionDTO();
        dto.id = getRevisionID(revision);
        addBundleRevisionDTO(dto, resources);

        dto.bundle = bundle.getBundleId();
        dto.symbolicName = revision.getSymbolicName();
        dto.type = revision.getTypes();
        dto.version = revision.getVersion().toString();

        dto.capabilities = new ArrayList<CapabilityDTO>();
        for (Capability cap : revision.getCapabilities(null))
        {
            CapabilityDTO cdto = new CapabilityDTO();
            cdto.id = getCapabilityID(cap);
            cdto.namespace = cap.getNamespace();
            cdto.attributes = convertAttrsToDTO(cap.getAttributes());
            cdto.directives = new HashMap<String, String>(cap.getDirectives());
            cdto.resource = getResourceIDAndAdd(cap.getResource(), resources);

            dto.capabilities.add(cdto);
        }

        dto.requirements = new ArrayList<RequirementDTO>();
        for (Requirement req : revision.getRequirements(null))
        {
            RequirementDTO rdto = new RequirementDTO();
            rdto.id = getRequirementID(req);
            rdto.namespace = req.getNamespace();
            rdto.attributes = convertAttrsToDTO(req.getAttributes());
            rdto.directives = new HashMap<String, String>(req.getDirectives());
            rdto.resource = getResourceIDAndAdd(req.getResource(), resources);

            dto.requirements.add(rdto);
        }
        return dto;
    }

    private static BundleWiringDTO createBundleWiringDTO(Bundle bundle)
    {
        BundleWiring bw = bundle.adapt(BundleWiring.class);
        return bw != null ? createBundleWiringDTO(bw) : null;
    }

    private static BundleWiringDTO createBundleWiringDTO(BundleWiring wiring)
    {
        BundleWiringDTO dto = new BundleWiringDTO();
        dto.bundle = wiring.getBundle().getBundleId();
        dto.root = getWiringID(wiring);
        dto.nodes = new HashSet<BundleWiringDTO.NodeDTO>();
        dto.resources = new HashSet<BundleRevisionDTO>();

        createBundleRevisionDTO(wiring.getRevision(), dto.resources);
        createBundleWiringNodeDTO(wiring, dto.resources, dto.nodes);

        return dto;
    }

    private static BundleWiringDTO[] createBundleWiringDTOArray(Bundle bundle)
    {
        BundleRevisions brs = bundle.adapt(BundleRevisions.class);
        if (brs == null || brs.getRevisions() == null)
            return null;

        List<BundleRevision> revisions = brs.getRevisions();
        BundleWiringDTO[] dtos = new BundleWiringDTO[revisions.size()];
        for (int i=0; i < revisions.size(); i++)
        {
            BundleWiring wiring = revisions.get(i).getWiring();
            dtos[i] = createBundleWiringDTO(wiring);
        }
        return dtos;
    }

    private static void createBundleWiringNodeDTO(BundleWiring bw, Set<BundleRevisionDTO> resources, Set<NodeDTO> nodes)
    {
        NodeDTO node = new BundleWiringDTO.NodeDTO();
        node.id = getWiringID(bw);

        addNodeDTO(node, nodes);

        node.current = bw.isCurrent();
        node.inUse = bw.isInUse();
        node.resource = getResourceIDAndAdd(bw.getResource(), resources);

        node.capabilities = new ArrayList<CapabilityRefDTO>();
        for (Capability cap : bw.getCapabilities(null))
        {
            CapabilityRefDTO cdto = new CapabilityRefDTO();
            cdto.capability = getCapabilityID(cap);
            cdto.resource = getResourceIDAndAdd(cap.getResource(), resources);
            node.capabilities.add(cdto);
        }

        node.requirements = new ArrayList<RequirementRefDTO>();
        for (Requirement req : bw.getRequirements(null))
        {
            RequirementRefDTO rdto = new RequirementRefDTO();
            rdto.requirement = getRequirementID(req);
            rdto.resource = getResourceIDAndAdd(req.getResource(), resources);
            node.requirements.add(rdto);
        }

        node.providedWires = new ArrayList<WireDTO>();
        for (Wire pw : bw.getProvidedWires(null))
        {
            node.providedWires.add(createBundleWireDTO(pw, resources, nodes));
        }

        node.requiredWires = new ArrayList<WireDTO>();
        for (Wire rw : bw.getRequiredWires(null))
        {
            node.requiredWires.add(createBundleWireDTO(rw, resources, nodes));
        }
    }

    private static BundleWireDTO createBundleWireDTO(Wire wire, Set<BundleRevisionDTO> resources, Set<NodeDTO> nodes)
    {
        BundleWireDTO wdto = new BundleWireDTO();
        if (wire instanceof BundleWire)
        {
            BundleWire w = (BundleWire) wire;

            BundleWiring pw = w.getProviderWiring();
            addWiringNodeIfNotPresent(pw, resources, nodes);
            wdto.providerWiring = getWiringID(pw);

            BundleWiring rw = w.getRequirerWiring();
            addWiringNodeIfNotPresent(rw, resources, nodes);
            wdto.requirerWiring = getWiringID(rw);
        }
        wdto.provider = getResourceIDAndAdd(wire.getProvider(), resources);
        wdto.requirer = getResourceIDAndAdd(wire.getRequirer(), resources);
        wdto.capability = new CapabilityRefDTO();
        wdto.capability.capability = getCapabilityID(wire.getCapability());
        wdto.capability.resource = getResourceIDAndAdd(wire.getCapability().getResource(), resources);
        wdto.requirement = new RequirementRefDTO();
        wdto.requirement.requirement = getRequirementID(wire.getRequirement());
        wdto.requirement.resource = getResourceIDAndAdd(wire.getRequirement().getResource(), resources);
        return wdto;
    }

    private static BundleStartLevelDTO createBundleStartLevelDTO(Bundle bundle)
    {
        BundleStartLevelDTO dto = new BundleStartLevelDTO();
        dto.bundle = bundle.getBundleId();

        BundleStartLevel sl = bundle.adapt(BundleStartLevel.class);
        dto.activationPolicyUsed = sl.isActivationPolicyUsed();
        dto.persistentlyStarted = sl.isPersistentlyStarted();
        dto.startLevel = sl.getStartLevel();

        return dto;
    }

    private static ServiceReferenceDTO[] createServiceReferenceDTOArray(Bundle bundle)
    {
        BundleContext ctx = bundle.getBundleContext();
        if (ctx == null)
            return null;

        ServiceReference<?>[] svcs = bundle.getRegisteredServices();
        if (svcs == null)
            return new ServiceReferenceDTO[0];

        ServiceReferenceDTO[] dtos = new ServiceReferenceDTO[svcs.length];
        for (int i=0; i < svcs.length; i++)
        {
            dtos[i] = createServiceReferenceDTO(svcs[i]);
        }
        return dtos;
    }

    private static ServiceReferenceDTO createServiceReferenceDTO(ServiceReference<?> svc)
    {
        ServiceReferenceDTO dto = new ServiceReferenceDTO();
        dto.bundle = svc.getBundle().getBundleId();
        dto.id = (Long) svc.getProperty(Constants.SERVICE_ID);
        Map<String, Object> props = new HashMap<String, Object>();
        for (String key : svc.getPropertyKeys())
        {
            props.put(key, svc.getProperty(key));
        }
        dto.properties = new HashMap<String, Object>(props);

        Bundle[] ubs = svc.getUsingBundles();
        if (ubs == null)
        {
            dto.usingBundles = new long[0];
        }
        else
        {
            dto.usingBundles = new long[ubs.length];
            for (int j=0; j < ubs.length; j++)
            {
                dto.usingBundles[j] = ubs[j].getBundleId();
            }
        }
        return dto;
    }

    @SuppressWarnings("unchecked")
    private static FrameworkDTO createFrameworkDTO(Bundle framework)
    {
        FrameworkDTO dto = new FrameworkDTO();
        dto.properties = new HashMap<String, Object>();

        dto.bundles = new ArrayList<BundleDTO>();
        for (Bundle b : framework.getBundleContext().getBundles())
        {
            dto.bundles.add(DTOFactory.createDTO(b, BundleDTO.class));
        }

        dto.services = new ArrayList<ServiceReferenceDTO>();

        ServiceReference<?>[] refs = null;
        try
        {
            refs = framework.getBundleContext().getAllServiceReferences(null, null);
        }
        catch (InvalidSyntaxException e)
        {
            // No filter, should never happen
        }

        for (ServiceReference<?> sr : refs)
        {
            dto.services.add(createServiceReferenceDTO(sr));
        }

        return dto;
    }

    private static FrameworkStartLevelDTO createFrameworkStartLevelDTO(Framework framework)
    {
        FrameworkStartLevel fsl = framework.adapt(FrameworkStartLevel.class);

        FrameworkStartLevelDTO dto = new FrameworkStartLevelDTO();
        dto.initialBundleStartLevel = fsl.getInitialBundleStartLevel();
        dto.startLevel = fsl.getStartLevel();

        return dto;
    }

    private static FrameworkWiringDTO createFrameworkWiringDTO(Bundle framework)
    {
        FrameworkWiringDTO dto = new FrameworkWiringDTO();

        dto.resources = new HashSet<BundleRevisionDTO>();
        dto.wirings = new HashSet<NodeDTO>();

        Set<Bundle> bundles = new LinkedHashSet<Bundle>(Arrays.asList(framework.getBundleContext().getBundles()));

        for (Bundle bundle : bundles)
        {
            addBundleWiring(bundle, dto.resources, dto.wirings);
        }

        return dto;
    }

    private static void addBundleWiring(Bundle bundle, Set<BundleRevisionDTO> resources, Set<NodeDTO> wirings)
    {
        BundleRevisions brs = bundle.adapt(BundleRevisions.class);

        for (BundleRevision revision : brs.getRevisions())
        {
            BundleWiring wiring = revision.getWiring();
            if (wiring != null)
            {
                createBundleWiringNodeDTO(wiring, resources, wirings);
            }
        }
    }

    private static void addBundleRevisionDTO(BundleRevisionDTO dto, Set<BundleRevisionDTO> resources)
    {
        for (BundleRevisionDTO r : resources)
        {
            if (r.id == dto.id)
                return;
        }
        resources.add(dto);
    }

    private static void addNodeDTO(NodeDTO dto, Set<NodeDTO> nodes)
    {
        for (NodeDTO nodeDTO : nodes)
        {
            if (nodeDTO.id == dto.id)
                return;
        }
        nodes.add(dto);
    }

    private static void addWiringNodeIfNotPresent(BundleWiring bw, Set<BundleRevisionDTO> resources, Set<NodeDTO> nodes)
    {
        int wiringID = getWiringID(bw);
        for (NodeDTO n : nodes)
        {
            if (n.id == wiringID)
                return;
        }
        createBundleWiringNodeDTO(bw, resources, nodes);
    }

    // Attributes contain Version values which are not supported for DTOs, so if
    // these are found they need to be converted to String values.
    private static Map<String, Object> convertAttrsToDTO(Map<String, Object> map)
    {
        Map<String, Object> m = new HashMap<String, Object>();
        for (Map.Entry<String, Object> entry : map.entrySet())
        {
            Object value = convertAttrToDTO(entry.getValue());
            if (value != null)
            {
                m.put(entry.getKey(), value);
            }
        }
        return m;
    }

    private static Object convertAttrToDTO(Object value)
    {
        if (value instanceof Version)
        {
            return value.toString();
        }
        else if (isPermissibleAttribute(value.getClass())
                || (value.getClass().isArray()
                && isPermissibleAttribute(value.getClass().getComponentType())))
        {
            return value;
        }
        else if (value instanceof List)
        {
            List result = new ArrayList();
            for (Object v : ((List) value))
            {
                Object vv = convertAttrToDTO(v);
                if (vv != null)
                {
                    result.add(vv);
                }
            }
            return result.isEmpty() ? null : result;
        }
        else
        {
            return null;
        }
    }

    private static boolean isPermissibleAttribute(Class clazz)
    {
        return clazz == Boolean.class || clazz == String.class
                || DTO.class.isAssignableFrom(clazz) || Number.class.isAssignableFrom(clazz);
    }

    private static int getWiringID(Wiring bw)
    {
        Resource res = bw.getResource();
        if (res != null)
        {
            return getResourceIDAndAdd(res, null);
        }
        return bw.hashCode();
    }

    private static int getCapabilityID(Capability capability)
    {
        return capability.hashCode();
    }

    private static int getRequirementID(Requirement requirement)
    {
        return requirement.hashCode();
    }

    private static int getResourceIDAndAdd(Resource res, Set<BundleRevisionDTO> resources)
    {
        if (res instanceof Revision)
        {
            int id = res.hashCode();

            if (resources == null)
                return id;

            for (BundleRevisionDTO rdto : resources)
            {
                if (rdto.id == id)
                    return id;
            }
            createBundleRevisionDTO((BundleRevision) res, resources);
            return id;
        }
        return res.hashCode();
    }

    private static int getRevisionID(BundleRevision revision)
    {
        return revision.hashCode();
    }
}
