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

import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.activemq.io.WireFormat;
import org.activemq.transport.TransportServerChannelSupport;
import org.activemq.util.JMSExceptionHelper;
import pyrasun.eio.EIOGlobalContext;
import pyrasun.eio.services.EmberServiceController;
import pyrasun.eio.services.EmberServiceException;
import pyrasun.eio.services.bytearray.ByteArrayServerClient;
import pyrasun.eio.services.bytearray.ByteArrayServerClientListener;
import pyrasun.eio.services.bytearray.ByteArrayServerListener;

import javax.jms.JMSException;
import java.net.URI;

/**
 * An EmberIO (using NIO) implementation of TransportServerChannel
 *
 * @version $Revision: 1.1 $
 */
public class EmberTransportServerChannel extends TransportServerChannelSupport implements ByteArrayServerListener, ByteArrayServerClientListener {

    private static final Log log = LogFactory.getLog(EmberTransportServerChannel.class);

    private WireFormat wireFormat;
    private EIOGlobalContext context;
    private EmberServiceController controller;
    private SynchronizedBoolean closed;
    private SynchronizedBoolean started;

    public EmberTransportServerChannel(WireFormat wireFormat, URI bindAddr, EIOGlobalContext context, EmberServiceController controller) {
        super(bindAddr);
        this.wireFormat = wireFormat;
        this.context = context;
        this.controller = controller;
        closed = new SynchronizedBoolean(false);
        started = new SynchronizedBoolean(false);
    }

    /**
     * start listeneing for events
     *
     * @throws JMSException if an error occurs
     */
    public void start() throws JMSException {
        super.start();
        if (started.commit(false, true)) {
            log.info("EmberTransportServerChannel at: " + getUrl());
            try {
                context.start();
                controller.startAll();
            }
            catch (EmberServiceException e) {
                JMSException jmsEx = new JMSException("Could not start EmberIOController: " + e);
                jmsEx.setLinkedException(e);
                throw jmsEx;
            }
        }
    }

    /**
     * close the ServerChannel
     */
    public void stop() throws JMSException {
        if (closed.commit(false, true)) {
            try {
                controller.stopAll();
                context.stop();
            }
            catch (EmberServiceException e) {
                throw JMSExceptionHelper.newJMSException("Failed to stop: " + e, e);
            }
        }
    }

    /**
     * @return pretty print of this
     */
    public String toString() {
        return "EmberTransportServerChannel@" + getUrl();
    }

    protected void handleException(ByteArrayServerClient client, JMSException e) {
        log.error("Could not create new TransportChannel for client: " + client, e);
    }

    public void newClient(ByteArrayServerClient client) {
        log.trace("New client received!");

        addClient(new EmberTransportChannel(wireFormat, null, null, client));
    }

    public void clientClosed(ByteArrayServerClient client) {
        log.info("Client has disconnected: " + client);
        /** TODO implement client closing! */
        // listener.removeClient(channel);
    }

    public void newMessage(ByteArrayServerClient byteArrayServerClient, Object msg) {
        log.warn("New message received!: " + msg);
    }

}