/*
 * Copyright (c) 2002-2003 IST-2004-2006-511731 ModelWare - ModelBus.
 * All rights reserved.
 *
 * This software is published under the terms of the ModelBus Software License
 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * A copy of ModelBus Software License is provided with this distribution in
 * doc/LICENSE.txt file.
 */

package org.eclipse.mddi.modelbus.adapter.user.consumer.impl;

import org.apache.log4j.Logger;
import org.eclipse.mddi.modelbus.adapter.infrastructure.model_manipulation.DescriptionUtil;
import org.eclipse.mddi.modelbus.adapter.infrastructure.registry.RegistryManager;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.ProviderProxy;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.SessionManager;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.SessionProviderProxy;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.TransportManager;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.client.AbstractInvocationSender;
import org.eclipse.mddi.modelbus.adapter.user.AdapterStub;
import org.eclipse.mddi.modelbus.adapter.user.ModelingServiceError;
import org.eclipse.mddi.modelbus.adapter.user.consumer.GenericConsumer;
import org.eclipse.mddi.modelbus.adapter.user.consumer.ModelBusCommunicationException;
import org.eclipse.mddi.modelbus.adapter.user.consumer.ModelTypeMismatchException;
import org.eclipse.mddi.modelbus.adapter.user.consumer.NoToolAvailableException;
import org.eclipse.mddi.modelbus.adapter.user.consumer.ServiceUnknownException;
import org.eclipse.mddi.modelbus.description.abstract_.ModelingService;
import org.eclipse.mddi.modelbus.description.concrete.Tool;

/**
 * @author Prawee Sriplakich, Andrey Sadovykh (LIP6)
 * 
 */
public class GenericConsumerImpl implements GenericConsumer {

    private static Logger logger = Logger.getLogger(GenericConsumerImpl.class);

    AdapterStub adapter;

    public GenericConsumerImpl(AdapterStub adapter) {
        this.adapter = adapter;
    }

    public Object[] consume(String serviceName, Object[] parameterValues)
            throws ServiceUnknownException, NoToolAvailableException,
            ModelTypeMismatchException, ModelBusCommunicationException,
            ModelingServiceError{

        if (parameterValues == null) {
            logger.error("null inputs");
            throw new ModelTypeMismatchException("null inputs");
        }
        Tool toolDescription = RegistryManager.getInstance()
                .getToolDescription(serviceName, adapter);

        // Check if Provider Tool is SessionEnabled
        if (DescriptionUtil.getIsSessionEnabled(toolDescription)) {
            String sessionId;
            // try to find if session is already created
            String [] sessions = getOpenSessions(serviceName);
            if (sessions.length>0) sessionId = sessions[0];
            else sessionId = newSession(serviceName);
            
            return consume(serviceName, parameterValues, sessionId);
        }
        ModelingService ms = DescriptionUtil.getServiceDescription(serviceName,
                toolDescription);
        ProviderProxy sender = adapter.getTransportManager().getProviderProxy(
                toolDescription);

        Object[] outputs = sender.invoke(ms, parameterValues);
        return outputs;
    }

    public void consumeAsync(String serviceName, Object[] parameterValues)
            throws ServiceUnknownException, NoToolAvailableException,
            ModelTypeMismatchException, ModelBusCommunicationException {

    }

    public boolean isResultReady(String serviceName) {

        return false;
    }

    public Object[] getResult(String serviceName) {

        return null;
    }

    public Object[] consume(String serviceName, Object[] parameterValues,
            String sessionId) throws ModelingServiceError,
            ServiceUnknownException, NoToolAvailableException,
            ModelTypeMismatchException, ModelBusCommunicationException {
        if (parameterValues == null) {
            logger.error("null inputs");
            throw new ModelTypeMismatchException("null inputs");
        }
        Tool toolDescription = RegistryManager.getInstance()
                .getToolDescription(serviceName, adapter);
        ModelingService ms = DescriptionUtil.getServiceDescription(serviceName,
                toolDescription);
        //  return session proxy
        SessionProviderProxy sender = adapter.getTransportManager().getSessionProviderProxy(
                toolDescription);
        Object[] outputs =  sender.invoke(ms,
                parameterValues, sessionId);
        return outputs;
    }

    public String newSession(String serviceName)
            throws ModelBusCommunicationException, ServiceUnknownException {
        Tool toolDescription = RegistryManager.getInstance()
                .getToolDescription(serviceName, adapter);
        SessionProviderProxy proxy = adapter.getTransportManager().getSessionProviderProxy(
                toolDescription);

        String sessionId =  proxy.newSession();
        return sessionId;
    }

    public void endSession(String sessionId)
            throws ModelBusCommunicationException {
        TransportManager tm =adapter.getTransportManager();
        SessionManager sm = tm.getSessionManager();
        SessionProviderProxy proxy = sm.getProviderProxy(sessionId);
        logger.debug("Proxy:"+proxy);
        proxy.endSession(sessionId);
    }

    public String[] getAllOpenSessions() {
        String[] sessions = adapter.getTransportManager().getSessionManager()
                .getAllOpenSessions();
        return sessions;
    }

    public String[] getOpenSessions(String serviceName) {
        String[] sessions = adapter.getTransportManager().getSessionManager()
                .getOpenSessions(serviceName);
        return sessions;

    }

}
