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

/* $Id$ */
 
package org.apache.xmlgraphics.image.loader.pipeline;

import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.SortedSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.impl.CompositeImageLoader;
import org.apache.xmlgraphics.image.loader.spi.ImageConverter;
import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry;
import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
import org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory;
import org.apache.xmlgraphics.util.dijkstra.DefaultEdgeDirectory;
import org.apache.xmlgraphics.util.dijkstra.DijkstraAlgorithm;
import org.apache.xmlgraphics.util.dijkstra.Vertex;

/**
 * Factory class for image processing pipelines.
 */
public class PipelineFactory {

    /** logger */
    protected static Log log = LogFactory.getLog(PipelineFactory.class);

    private ImageManager manager;
    
    private int converterEdgeDirectoryVersion = -1;
    
    /** Holds the EdgeDirectory for all image conversions */
    private DefaultEdgeDirectory converterEdgeDirectory;
    
    /**
     * Main constructor.
     * @param manager the ImageManager instance
     */
    public PipelineFactory(ImageManager manager) {
        this.manager = manager;
    }
    
    private DefaultEdgeDirectory getEdgeDirectory() {
        ImageImplRegistry registry = manager.getRegistry();
        if (registry.getImageConverterModifications() != converterEdgeDirectoryVersion) {
            Collection converters = registry.getImageConverters();
            
            //Rebuild edge directory
            DefaultEdgeDirectory dir = new DefaultEdgeDirectory();
            Iterator iter = converters.iterator();
            while (iter.hasNext()) {
                ImageConverter converter = (ImageConverter)iter.next();
                dir.addEdge(new ImageConversionEdge(converter));
            }
            
            converterEdgeDirectoryVersion = registry.getImageConverterModifications();
            this.converterEdgeDirectory = dir; //Replace (thread-safe)
        }
        return this.converterEdgeDirectory;
    }
    
    /**
     * Creates and returns an {@link ImageProviderPipeline} that allows to load an image of the
     * given MIME type and present it in the requested image flavor.
     * @param originalImage the original image that serves as the origin point of the conversion
     * @param targetFlavor the requested image flavor
     * @return an {@link ImageProviderPipeline} or null if no suitable pipeline could be assembled
     */
    public ImageProviderPipeline newImageConverterPipeline(
                Image originalImage, ImageFlavor targetFlavor) {
        //Get snapshot to avoid concurrent modification problems (thread-safety)
        DefaultEdgeDirectory dir = getEdgeDirectory();
        ImageRepresentation destination = new ImageRepresentation(targetFlavor);
        ImageProviderPipeline pipeline = findPipeline(dir, originalImage.getFlavor(), destination);
        return pipeline;
    }
    
    /**
     * Creates and returns an {@link ImageProviderPipeline} that allows to load an image of the
     * given MIME type and present it in the requested image flavor.
     * @param imageInfo the image info object of the original image
     * @param targetFlavor the requested image flavor
     * @return an {@link ImageProviderPipeline} or null if no suitable pipeline could be assembled
     */
    public ImageProviderPipeline newImageConverterPipeline(
                ImageInfo imageInfo, ImageFlavor targetFlavor) {
        String originalMime = imageInfo.getMimeType();
        ImageImplRegistry registry = manager.getRegistry();
        ImageProviderPipeline pipeline = null;
        
        //Get snapshot to avoid concurrent modification problems (thread-safety)
        DefaultEdgeDirectory dir = getEdgeDirectory();
        
        ImageLoaderFactory[] loaderFactories = registry.getImageLoaderFactories(
                imageInfo, targetFlavor);
        if (loaderFactories != null) {
            //Directly load image and return it
            ImageLoader loader;
            if (loaderFactories.length == 1) {
                 loader = loaderFactories[0].newImageLoader(targetFlavor);
            } else {
                int count = loaderFactories.length;
                ImageLoader[] loaders = new ImageLoader[count];
                for (int i = 0; i < count; i++) {
                    loaders[i] = loaderFactories[i].newImageLoader(targetFlavor);
                }
                loader = new CompositeImageLoader(loaders);
            }
            pipeline = new ImageProviderPipeline(manager.getCache(), loader);
        } else {
            //Need to use ImageConverters
            if (log.isTraceEnabled()) {
                log.trace("No ImageLoaderFactory found that can load this format directly."
                        + " Trying ImageConverters instead...");
            }
            
            ImageRepresentation destination = new ImageRepresentation(targetFlavor);
            //Get Loader for originalMIME
            // --> List of resulting flavors, possibly multiple loaders
            loaderFactories = registry.getImageLoaderFactories(originalMime);
            if (loaderFactories != null) {
                SortedSet candidates = new java.util.TreeSet(new PipelineComparator());
                //Find best pipeline -> best loader
                for (int i = 0, ci = loaderFactories.length; i < ci; i++) {
                    ImageLoaderFactory loaderFactory = loaderFactories[i];
                    ImageFlavor[] flavors = loaderFactory.getSupportedFlavors(originalMime);
                    for (int j = 0, cj = flavors.length; j < cj; j++) {
                        pipeline = findPipeline(dir, flavors[j], destination);
                        if (pipeline != null) {
                            ImageLoader loader = loaderFactory.newImageLoader(flavors[j]);
                            pipeline.setImageLoader(loader);
                            candidates.add(pipeline);
                        }
                    }
                }
                
                //Build final pipeline
                if (candidates.size() > 0) {
                    pipeline = (ImageProviderPipeline)candidates.first();
                }
            }
        }
        if (pipeline != null && log.isDebugEnabled()) {
            log.debug("Pipeline: " + pipeline + " with penalty " + pipeline.getConversionPenalty());
        }
        return pipeline;
    }
    
    private static class PipelineComparator implements Comparator {

        public int compare(Object o1, Object o2) {
            ImageProviderPipeline p1 = (ImageProviderPipeline)o1;
            ImageProviderPipeline p2 = (ImageProviderPipeline)o2;
            //Lowest penalty first
            return p1.getConversionPenalty() - p2.getConversionPenalty();
        }
        
    }
    
    private ImageProviderPipeline findPipeline(DefaultEdgeDirectory dir,
            ImageFlavor originFlavor, ImageRepresentation destination) {
        DijkstraAlgorithm dijkstra = new DijkstraAlgorithm(
                dir);
        ImageRepresentation origin = new ImageRepresentation(originFlavor); 
        dijkstra.execute(origin, destination);
        if (log.isTraceEnabled()) {
            log.trace("Lowest penalty: " + dijkstra.getLowestPenalty(destination));
        }
        
        Vertex prev = destination;
        Vertex pred = dijkstra.getPredecessor(destination);
        if (pred == null) {
            if (log.isTraceEnabled()) {
                log.trace("No route found!");
            }
            return null;
        } else {
            LinkedList stops = new LinkedList();
            while ((pred = dijkstra.getPredecessor(prev)) != null) {
                ImageConversionEdge edge = (ImageConversionEdge)
                        dir.getBestEdge(pred, prev);
                stops.addFirst(edge);
                prev = pred;
            }
            ImageProviderPipeline pipeline = new ImageProviderPipeline(manager.getCache(), null);
            Iterator iter = stops.iterator();
            while (iter.hasNext()) {
                ImageConversionEdge edge = (ImageConversionEdge)iter.next(); 
                pipeline.addConverter(edge.getImageConverter());
            }
            return pipeline;
        }
    }
    
    /**
     * Finds and returns an array of {@link ImageProviderPipeline} instances which can handle
     * the given MIME type and return one of the given {@link ImageFlavor}s.
     * @param imageInfo the image info object
     * @param flavors the possible target flavors
     * @return an array of pipelines
     */
    public ImageProviderPipeline[] determineCandidatePipelines(ImageInfo imageInfo,
            ImageFlavor[] flavors) {
        int count = flavors.length;
        ImageProviderPipeline[] candidates = new ImageProviderPipeline[count];
        for (int i = 0; i < count; i++) {
            candidates[i] = newImageConverterPipeline(imageInfo, flavors[i]);
        }
        return candidates;
    }
    
    /**
     * Finds and returns an array of {@link ImageProviderPipeline} instances which can handle
     * the convert the given {@link Image} and return one of the given {@link ImageFlavor}s.
     * @param sourceImage the image to be converted
     * @param flavors the possible target flavors
     * @return an array of pipelines
     */
    public ImageProviderPipeline[] determineCandidatePipelines(Image sourceImage,
            ImageFlavor[] flavors) {
        int count = flavors.length;
        ImageProviderPipeline[] candidates = new ImageProviderPipeline[count];
        for (int i = 0; i < count; i++) {
            candidates[i] = newImageConverterPipeline(sourceImage, flavors[i]);
        }
        return candidates;
    }
    
    
}
