/**
 * @author    STF 424_ITS_Test_Platform
 * @version    $id$
 */
package org.etsi.ttcn.tool.elvior.adapter;

import org.elvior.ttcn.tritci.ChannelEventHandler;
import org.elvior.ttcn.tritci.TriProvider;
import org.elvior.ttcn.tritci.TriTciChannel;

import org.etsi.ttcn.adapter.core.TERFactory;
import org.etsi.ttcn.extfunc.core.ExternalFunction;
import org.etsi.ttcn.extfunc.core.XfFactory;
import org.etsi.ttcn.tci.TciParameterList;
import org.etsi.ttcn.tci.TciValueList;
import org.etsi.ttcn.tci.Value;
import org.etsi.ttcn.tri.TriAddress;
import org.etsi.ttcn.tri.TriAddressList;
import org.etsi.ttcn.tri.TriBoolean;
import org.etsi.ttcn.tri.TriCommunicationSA;
import org.etsi.ttcn.tri.TriCommunicationTE;
import org.etsi.ttcn.tri.TriComponentId;
import org.etsi.ttcn.tri.TriException;
import org.etsi.ttcn.tri.TriFunctionId;
import org.etsi.ttcn.tri.TriLong;
import org.etsi.ttcn.tri.TriMessage;
import org.etsi.ttcn.tri.TriParameter;
import org.etsi.ttcn.tri.TriParameterList;
import org.etsi.ttcn.tri.TriPlatformPA;
import org.etsi.ttcn.tri.TriPortId;
import org.etsi.ttcn.tri.TriPortIdList;
import org.etsi.ttcn.tri.TriSignatureId;
import org.etsi.ttcn.tri.TriStatus;
import org.etsi.ttcn.tri.TriTestCaseId;
import org.etsi.ttcn.tri.TriTimerDuration;
import org.etsi.ttcn.tri.TriTimerId;
import org.etsi.ttcn.xtri.xTriCommunicationSA;

public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xTriCommunicationSA, TriPlatformPA, ChannelEventHandler {
    /**
     * This is the main PluginAdapter class
     */
    private TestAdapter testAdapter;

    public PluginAdapter() {
        
        // Register this object as the instance implementing the TRI-SA interface
        TriProvider.getInstance().setTriCommunicationSA(this);
        
        // Register this object as the instance implementing the TRI-PA interface
        TriProvider.getInstance().setTriPlatformPA(this);
        
        TriTciChannel channel = TriTciChannel.getInstance();
        
        // Set application name that will be displayed in the TestCast log
        channel.setApplicationName("EtsiTestPlatform"); 
        
        // Register this object as the receiver of events generated by TestCast framework
        channel.setEventHandler(this);
                
        TERFactory.setImpl(new TeRequiredImpl(this));
    }
    
    public void run() {
        
        // Attempt to connect to TestCast
        if (TriTciChannel.getInstance().open()) {
            testAdapter = new TestAdapter();
            try {
                synchronized(this) {
                    wait();
                }
            } catch (InterruptedException e) {
            }
        }
    }
    
    public TriStatus triCall(TriComponentId componentId, TriPortId tsiPortId,
            TriAddress sutAddress, TriSignatureId signatureId,
            TriParameterList parameterList) {
        return testAdapter.triCall(componentId, tsiPortId, sutAddress, signatureId, parameterList);
    }

    public TriStatus triCallBC(TriComponentId componentId, TriPortId tsiPortId,
            TriSignatureId signatureId, TriParameterList parameterList) {
        return testAdapter.triCallBC(componentId, tsiPortId, signatureId, parameterList);
    }

    public TriStatus triCallMC(TriComponentId componentId, TriPortId tsiPortId,
            TriAddressList sutAddresses, TriSignatureId signatureId,
            TriParameterList parameterList) {
        return testAdapter.triCallMC(componentId, tsiPortId, sutAddresses, signatureId, parameterList);
    }

    public TriStatus triEndTestCase() {
        return testAdapter.triEndTestCase();
    }

    public TriStatus triExecuteTestCase(TriTestCaseId testCaseId, TriPortIdList tsiPorts) {
        // Disable XTRI functionality for all ports, so that existing SA implementation can be reused
        for(int i = 0; i < tsiPorts.size(); i++) {
            TriTciChannel.getInstance().enableXTriForPort(tsiPorts.get(i), false);
        }
        return testAdapter.triExecuteTestCase(testCaseId, tsiPorts);
    }

    public TriStatus triMap(TriPortId compPortId, TriPortId tsiPortId) {
        return testAdapter.triMap(compPortId, tsiPortId);
    }

    public TriStatus triRaise(TriComponentId componentId, TriPortId tsiPortId,
            TriAddress sutAddress, TriSignatureId signatureId, TriException exception) {
        return testAdapter.triRaise(componentId, tsiPortId, sutAddress, signatureId, exception);
    }

    public TriStatus triRaiseBC(TriComponentId componentId,
            TriPortId tsiPortId, TriSignatureId signatureId, TriException exc) {
        return testAdapter.triRaiseBC(componentId, tsiPortId, signatureId, exc);
    }

    public TriStatus triRaiseMC(TriComponentId componentId,
            TriPortId tsiPortId, TriAddressList sutAddresses,
            TriSignatureId signatureId, TriException exc) {
        return testAdapter.triRaiseMC(componentId, tsiPortId, sutAddresses, signatureId, exc);
    }

    public TriStatus triReply(TriComponentId componentId, TriPortId tsiPortId,
            TriAddress sutAddress, TriSignatureId signatureId,
            TriParameterList parameterList, TriParameter returnValue) {
        return testAdapter.triReply(componentId, tsiPortId, sutAddress, signatureId, parameterList, returnValue);
    }

    public TriStatus triReplyBC(TriComponentId componentId,
            TriPortId tsiPortId, TriSignatureId signatureId,
            TriParameterList parameterList, TriParameter returnValue) {
        return testAdapter.triReplyBC(componentId, tsiPortId, signatureId, parameterList, returnValue);
    }

    public TriStatus triReplyMC(TriComponentId componentId,
            TriPortId tsiPortId, TriAddressList sutAddresses,
            TriSignatureId signatureId, TriParameterList parameterList,
            TriParameter returnValue) {
        return testAdapter.triReplyMC(componentId, tsiPortId, sutAddresses, signatureId, parameterList, returnValue);
    }

    public TriStatus triSAReset() {
        return testAdapter.triSAReset();
    }

    public TriStatus triSend(TriComponentId componentId, TriPortId tsiPortId,
            TriAddress address, TriMessage sendMessage) {
        return testAdapter.triSend(componentId, tsiPortId, address, sendMessage);
    }

    public TriStatus triSendBC(TriComponentId componentId, TriPortId tsiPortId,
            TriMessage sendMessage) {
        return testAdapter.triSendBC(componentId, tsiPortId, sendMessage);
    }

    public TriStatus triSendMC(TriComponentId componentId, TriPortId tsiPortId,
            TriAddressList addresses, TriMessage sendMessage) {
        return testAdapter.triSendMC(componentId, tsiPortId, addresses, sendMessage);
    }

    public TriStatus triSutActionInformal(String description) {
        return testAdapter.triSutActionInformal(description);
    }

    public TriStatus triUnmap(TriPortId compPortId, TriPortId tsiPortId) {
        return testAdapter.triUnmap(compPortId, tsiPortId);
    }

    public TriStatus triExternalFunction(TriFunctionId functionId, TriParameterList parameterList, TriParameter returnValue) {

    	ExternalFunction xf = XfFactory.getInstance().getXf("");
    	
    	xf.exec(functionId, parameterList, returnValue);
    	
    	return TriProvider.getInstance().getTriFactory().createOkStatus(); // FIXME
    }
    
    public void onConnectionClosed() {
        synchronized(this) { 
            notify();
        }
    }

    public void onConnectionEstablished() {
    }

    public void onError(String error) {
    }

    @Override
    public TriStatus triPAReset() {
        return TriProvider.getInstance().getTriFactory().createOkStatus();
    }

    @Override
    public TriStatus triReadTimer(TriTimerId timerId, TriTimerDuration elapsedTime) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triStartTimer(TriTimerId timerId, TriTimerDuration timerDuration) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triStopTimer(TriTimerId timerId) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triTimerRunning(TriTimerId timerId, TriBoolean running) {
        throw new RuntimeException();
    }

    @Override
    public void triEnqueueCall(TriPortId tsiPortId, TriAddress SUTaddress, TriComponentId componentId, TriSignatureId signatureId, TriParameterList parameterList) {
        throw new RuntimeException();
    }

    @Override
    public void triEnqueueException(TriPortId tsiPortId, TriAddress sutAddress, TriComponentId componentId, TriSignatureId signatureId,
            TriException exception) {
        throw new RuntimeException();
    }

    @Override
    public void triEnqueueMsg(TriPortId tsiPortId, TriAddress sutAddress, TriComponentId componentId, TriMessage receivedMessage) {
        TriProvider.getInstance().getTriCommunicationTE().triEnqueueMsg(
            tsiPortId, 
            null, 
            componentId, 
            receivedMessage);
    }

    @Override
    public void triEnqueueReply(TriPortId tsiPortId, TriAddress address, TriComponentId componentId, TriSignatureId signatureId, TriParameterList parameterList, TriParameter returnValue) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triMapParam(TriPortId arg0, TriPortId arg1, TriParameterList arg2) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triUnmapParam(TriPortId arg0, TriPortId arg1, TriParameterList arg2) {
        throw new RuntimeException();
    }
    
    @Override
    public TriStatus xtriCall(TriComponentId arg0, TriPortId arg1, Value arg2, TriSignatureId arg3, TciParameterList arg4) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriCallBC(TriComponentId arg0, TriPortId arg1, TriSignatureId arg2, TciParameterList arg3) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriCallMC(TriComponentId arg0, TriPortId arg1, TciValueList arg2, TriSignatureId arg3, TciParameterList arg4) {
        throw new RuntimeException();
    }

    @Override
    public Value xtriConvert(Object arg0, org.etsi.ttcn.tci.Type arg1) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriMapParam(TriPortId arg0, TriPortId arg1, TciParameterList arg2) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriRaise(TriComponentId arg0, TriPortId arg1, Value arg2, TriSignatureId arg3, Value arg4) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriRaiseBC(TriComponentId arg0, TriPortId arg1, TriSignatureId arg2, Value arg3) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriRaiseMC(TriComponentId arg0, TriPortId arg1, TciValueList arg2, TriSignatureId arg3, Value arg4) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriReply(TriComponentId arg0, TriPortId arg1, Value arg2, TriSignatureId arg3, TciParameterList arg4, Value arg5) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriReplyBC(TriComponentId arg0, TriPortId arg1, TriSignatureId arg2, TciParameterList arg3, Value arg4) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriReplyMC(TriComponentId arg0, TriPortId arg1, TciValueList arg2, TriSignatureId arg3, TciParameterList arg4, Value arg5) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriSend(TriComponentId compPortId, TriPortId tsiPortId, Value arg2, Value arg3) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriSendBC(TriComponentId arg0, TriPortId arg1, Value arg2) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriSendMC(TriComponentId arg0, TriPortId arg1, TciValueList arg2, Value arg3) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus xtriUnmapParam(TriPortId arg0, TriPortId arg1, TciParameterList arg2) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triStaticMap(TriPortId arg0, TriPortId arg1) {
        throw new RuntimeException();
    }
        
    @Override
    public TriStatus triBeginWait(long arg0, TriComponentId arg1) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triNextSampling(long arg0, TriPortId arg1) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triReadClock(TriLong arg0) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triStartClock(long arg0) {
        throw new RuntimeException();
    }

    @Override
    public void triSAErrorReq(String arg0) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triGetStreamValue(TriComponentId arg0, TriPortId arg1, TriAddress arg2, TriMessage arg3) {
        throw new RuntimeException();
    }

    @Override
    public TriStatus triSetStreamValue(TriComponentId arg0, TriPortId arg1, TriAddress arg2, TriMessage arg3) {
        throw new RuntimeException();
    }
    
} // End of class PluginAdapter
