/** 
 * 
 * Copyright 2004 Protique Ltd
 * 
 * Licensed 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.activemq.transport.reliable;

import org.activemq.io.WireFormat;
import org.activemq.transport.TransportChannel;
import org.activemq.transport.composite.CompositeTransportChannelFactory;
import org.activemq.util.JMSExceptionHelper;

import javax.jms.JMSException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * A Reliable implementation of a TransportChannelFactory
 *
 * @version $Revision: 1.1.1.1 $
 */
public class ReliableTransportChannelFactory extends CompositeTransportChannelFactory {
    
    /**
     * Create a TransportChannel
     *
     * @param wireFormat     - the on-the-wire marshaller
     * @param remoteLocation - location to bind to
     * @return a reliable transport channel
     * @throws JMSException if an error occurs
     */
    public TransportChannel create(WireFormat wireFormat, URI remoteLocation) throws JMSException {
        try {
            List uris = new ArrayList();
            String text = parseURIs(uris, remoteLocation);
            uris = randomizeURIs(uris);

        	ReliableTransportChannel channel = new ReliableTransportChannel(wireFormat, uris);
            channel = (ReliableTransportChannel) populateProperties(channel, text);
            
            // Using singleton pattern since this factory isn't a singleton itself
            KeepAliveDaemon daemon = KeepAliveDaemon.getInstance();
            daemon.addMonitoredChannel(channel);
            daemon.start();
            
            return channel;
        }
        catch (URISyntaxException e) {
            throw JMSExceptionHelper.newJMSException("Can't parse list of URIs for: " + remoteLocation + ". Reason: "
                    + e, e);
        }
    }

    /**
     * @param uris - the URIs to randomize
     * @return randomized array
     */
    protected List randomizeURIs(List uris) {
        if (!uris.isEmpty()) {
            int size = uris.size();
            Object[] result = new Object[size];
            SMLCGRandom random = new SMLCGRandom();
            int startIndex = (int) (random.nextDouble() * (size + 1));
            int count = 0;
            for (int i = startIndex; i < size; i++) {
                result[count++] = uris.get(i);
            }
            for (int i = 0; i < startIndex; i++) {
                result[count++] = uris.get(i);
            }
            return new ArrayList(Arrays.asList(result));
        }
        return uris;
    }
}