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

import java.math.BigInteger;
import java.util.logging.Logger;

import org.elvior.ttcn.tritci.IntegerValueEx;
import org.elvior.ttcn.tritci.TciProvider;
import org.etsi.adapter.TERFactory;
import org.etsi.codec.ITciCDWrapper;
import org.etsi.ttcn.tci.BooleanValue;
import org.etsi.ttcn.tci.CharstringValue;
import org.etsi.ttcn.tci.EnumeratedValue;
import org.etsi.ttcn.tci.FloatValue;
import org.etsi.ttcn.tci.IntegerValue;
import org.etsi.ttcn.tci.OctetstringValue;
import org.etsi.ttcn.tci.RecordOfValue;
import org.etsi.ttcn.tci.RecordValue;
import org.etsi.ttcn.tci.TciCDRequired;
import org.etsi.ttcn.tci.Type;
import org.etsi.ttcn.tci.Value;

/** This class implements the ITciCDWrapper interface
 * 
 * Note that the TCI Codec Interface (TCI-CD) describes the operations a TTCN-3 Executable is required to implement and the operations a codec implementation for a certain encoding scheme shall provide to the TE
 * 
 * See ETSI ES 201 873-6 V4.2.1 - Clause 7.3.2.1 TCI-CD required
 */
public class TciCDWrapper implements ITciCDWrapper {

    private TciCDRequired _tciFactory = TciProvider.getInstance().getTciCDRequired();
    
    private Logger _logger;
    
    public TciCDWrapper() {
        _logger = Logger.getLogger("org.etsi.its");
    }
    
    @Override
    public IntegerValue setInteger(final Integer value) {
        IntegerValue iv = (IntegerValue)_tciFactory.getInteger().newInstance();
        iv.setInteger(value);
        return iv;
    }

    @Override
    public int getInteger(final IntegerValue iv) {
        return iv.getInteger();
    }

    @Override
    public IntegerValue setInteger(final BigInteger value) { 
//        TERFactory.getInstance().logDebug(">>> getBigInteger: " + value);
        IntegerValueEx bi = (IntegerValueEx) _tciFactory.getInteger().newInstance(); //_tciFactory.getTypeForName("org.elvior.ttcn.tritci.IntegerValueEx");
        if (bi != null) { 
//            TERFactory.getInstance().logDebug("getBigInteger: then");
            bi.setInt64(value.longValue()); 
//            TERFactory.getInstance().logDebug("getBigInteger: bi=" + bi.getInt64());
            return (IntegerValue)bi;
        } else { 
//            TERFactory.getInstance().logDebug("getBigInteger: else");
            IntegerValue i = (IntegerValue) _tciFactory.getInteger().newInstance();
//            TERFactory.getInstance().logDebug("getBigInteger: i=" + i);
            i.setInteger(value.intValue());
            return i;
        }
    }

    @Override
    public void setInteger(BigInteger value, IntegerValue setInt) {
        ((IntegerValueEx)setInt).setInt64(value.longValue());
    }
    
    @Override
    public long getBigInteger(final IntegerValue iv) {
        return ((IntegerValueEx)iv).getInt64();
    }

    @Override
    public OctetstringValue getOctetstring() {
        return (OctetstringValue)_tciFactory.getOctetstring().newInstance();
    }

    /** Constructs and returns a basic TTCN-3 string type
     * 
     * @return An instance of Type representing a TTCN-3 string type
     */
    @Override
    public CharstringValue getCharstringValue() {
        return (CharstringValue)_tciFactory.getCharstring().newInstance();
    }

    @Override
    public FloatValue getFloat() {
        return (FloatValue)_tciFactory.getFloat().newInstance();
    }

    @Override
    public Value getUnionValue(final Type decodingHypothesis, final String variantName) {
//        TERFactory.getInstance().logDebug(">>> getUnionValue: " + decodingHypothesis.getName() + ", " + variantName);
        
        String variantTypeName = decodingHypothesis.getDefiningModule().getModuleName() + "." + decodingHypothesis.getName() + "." + variantName;
//        TERFactory.getInstance().logDebug("variantTypeName is " + variantTypeName);
        Type variantType = getTypeForName(variantTypeName);
        if(variantType != null) {
            Value testVal = variantType.newInstance();
            if(testVal != null) {
//                TERFactory.getInstance().logDebug("Variant value has been created.");
                return testVal;
            }
        }
        TERFactory.getInstance().logError("variantType is null");
        
        TERFactory.getInstance().logDebug("Variant value hasn't been created.");
        return null;
    }
    
    @Override
    public Type getTypeForName(final String type) { 
//        TERFactory.getInstance().logDebug("TciCDWrapper.getTypeForName: " + type);
        Type originalType; 
        if (type.indexOf("DecodedBtpPayload") != -1) {
            if (type.endsWith("camPacket")) {
                originalType = _tciFactory.getTypeForName("CAM_PDU_Descriptions.CAM");
            } else if (type.endsWith("denmPacket")) {
                originalType = _tciFactory.getTypeForName("DENM_PDU_Descriptions.DENM");
            } else if (type.endsWith("mapemPacket")) {
                originalType = _tciFactory.getTypeForName("MAPEM_PDU_Descriptions.MAPEM");
            } else if (type.endsWith("spatemPacket")) {
                originalType = _tciFactory.getTypeForName("MAPEM_PDU_Descriptions.SPATEM");
            } else if (type.endsWith("ivimPacket")) {
                originalType = _tciFactory.getTypeForName("IVIM_PDU_Descriptions.IVIM");
            } else {
                originalType = _tciFactory.getTypeForName(type);
            }
        } else {
            originalType = _tciFactory.getTypeForName(type);
        }
//        TERFactory.getInstance().logDebug("TciCDWrapper.getTypeForName: " + originalType.getName());
        return originalType;
    } // End of method getTypeForName
    
    @Override
    public BooleanValue getBoolean() {
        return (BooleanValue)_tciFactory.getBoolean().newInstance();
    }

    @Override
    public EnumeratedValue getEnumValue(String typeName) {
        return (EnumeratedValue)_tciFactory.getTypeForName(typeName).newInstance();
    }
    
    @Override
    public RecordValue getRecordValue(final String typeName) {
        return (RecordValue)_tciFactory.getTypeForName(typeName).newInstance();
    }

    @Override
    public RecordOfValue getRecordOfValue(final String typeName) {
        return (RecordOfValue)_tciFactory.getTypeForName(typeName).newInstance();
    }

    @Override
    public void setInteger(IntegerValue intValue, final Integer value) {
        intValue.setInteger(value);
    }
    
    @Override
    public void logDebug(String debugMessage) {
        _logger.info(debugMessage);
    }

    @Override
    public void logError(String errorMessage) {
        _logger.severe(errorMessage);
    }

} // End of class TciCDWrapper
