package org.yamcs.simulator;

import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Map;

import org.yamcs.ConfigurationException;
import org.yamcs.YConfiguration;
import org.yamcs.simulation.simulator.PerfPacketGenerator;
import org.yamcs.xtce.Comparison;
import org.yamcs.xtce.DatabaseLoadException;
import org.yamcs.xtce.IntegerDataEncoding;
import org.yamcs.xtce.IntegerParameterType;
import org.yamcs.xtce.OperatorType;
import org.yamcs.xtce.Parameter;
import org.yamcs.xtce.ParameterEntry;
import org.yamcs.xtce.ParameterInstanceRef;
import org.yamcs.xtce.SequenceContainer;
import org.yamcs.xtce.SequenceEntry;
import org.yamcs.xtce.SequenceEntry.ReferenceLocationType;
import org.yamcs.xtce.util.NameReference.Type;
import org.yamcs.xtce.util.UnresolvedNameReference;
import org.yamcs.xtce.SpaceSystem;
import org.yamcs.xtce.SpaceSystemLoader;

/**
 * Generates a MDB used for performance testing.
 * 
 * For the moment it generates only int32 parameters
 * 
 * @author nm
 *
 */
public class PerfMdbLoader implements SpaceSystemLoader {
    int numPackets;
    int packetSize;
    int numParam;
    static String PACKET_ID_PARA_NAME = "packet-id";

    public PerfMdbLoader(Map<String, Object> config) {
        numPackets = YConfiguration.getInt(config, "numPackets");
        packetSize = YConfiguration.getInt(config, "packetSize");
        numParam = packetSize / 4;
    }

    @Override
    public boolean needsUpdate(RandomAccessFile consistencyDateFile) throws IOException, ConfigurationException {
        return true;
    }

    @Override
    public String getConfigName() {
        return "perf-data";
    }

    @Override
    public void writeConsistencyDate(FileWriter consistencyDateFile) {
        return;
    }

    @Override
    public SpaceSystem load() throws ConfigurationException, DatabaseLoadException {
        SpaceSystem ss = new SpaceSystem("perf-data");
        IntegerParameterType uint32 = new IntegerParameterType("uint32");
        uint32.setSizeInBits(32);
        IntegerDataEncoding ide = new IntegerDataEncoding(32);
        uint32.setEncoding(ide);
        ss.addParameterType(uint32);
        for (int j = 0; j < numPackets; j++) {
            int pktId = PerfPacketGenerator.PERF_TEST_PACKET_ID + j;
            SequenceContainer sc = new SequenceContainer("pkt_" + pktId);
            UnresolvedNameReference unr = new UnresolvedNameReference("/YSS/ccsds-default", Type.SEQUENCE_CONTAINER);

            unr.addResolvedAction(nd -> {
                addCcsdsInheritance((SequenceContainer) nd, sc, pktId);
                return true;
            });
            ss.addUnresolvedReference(unr);
            for (int i = 0; i < numParam; i++) {
                Parameter p = new Parameter("p_"+pktId+"_uint_" + i);
                p.setParameterType(uint32);
                ParameterEntry pe = new ParameterEntry(128 + 32 * i, ReferenceLocationType.containerStart, p);
                sc.addEntry(pe);
                ss.addParameter(p);
            }
            ss.addSequenceContainer(sc);
        }
        return ss;
    }

    private void addCcsdsInheritance(SequenceContainer ccsds, SequenceContainer sc, int id) {
        for (SequenceEntry se : ccsds.getEntryList()) {
            if (se instanceof ParameterEntry) {
                ParameterEntry pe = (ParameterEntry) se;
                if (PACKET_ID_PARA_NAME.equals(pe.getParameter().getName())) {
                    Parameter packetIdParam = pe.getParameter();
                    Comparison c = new Comparison(new ParameterInstanceRef(packetIdParam), id, OperatorType.EQUALITY);
                    sc.setBaseContainer(ccsds);
                    sc.setRestrictionCriteria(c);
                    return;
                }
            }
        }
        throw new ConfigurationException("Cannot find a parameter '"+PACKET_ID_PARA_NAME+"' in the container " + ccsds.getName());
    }

}

@@ -111,16 +111,41 @@
 ssFile;%0A
+import java.util.Arrays;%0A
 import j
@@ -158,16 +158,16 @@
 il.Map;%0A
-
 %0Aimport 
@@ -986,57 +986,84 @@
 %0A * 
-For the moment it generates only int32 parameters
+It generates all unsigned integer parameters with the size in bits specified
 %0A * 
@@ -1200,16 +1200,42 @@
 mParam;%0A
+    int paramSizeInBits;%0A%0A
     stat
@@ -1463,24 +1463,104 @@
 cketSize%22);%0A
+        paramSizeInBits = YConfiguration.getInt(config, %22paramSizeInBits%22, 32);%0A
         numP
@@ -1581,11 +1581,29 @@
 ize 
-/ 4
+* 8 / paramSizeInBits
 ;%0A  
@@ -2106,24 +2106,33 @@
 erf-data%22);%0A
+        %0A
         Inte
@@ -2148,22 +2148,21 @@
 terType 
-uint32
+ptype
  = new I
@@ -2190,11 +2190,25 @@
 uint
-32%22
+%22+paramSizeInBits
 );%0A 
@@ -2210,30 +2210,29 @@
 s);%0A        
-uint32
+ptype
 .setSizeInBi
@@ -2234,18 +2234,31 @@
 eInBits(
-32
+paramSizeInBits
 );%0A     
@@ -2310,18 +2310,31 @@
 ncoding(
-32
+paramSizeInBits
 );%0A     
@@ -2336,22 +2336,21 @@
         
-uint32
+ptype
 .setEnco
@@ -2380,38 +2380,37 @@
 ddParameterType(
-uint32
+ptype
 );%0A        for (
@@ -3009,21 +3009,40 @@
 %22p_%22
-+
+ + 
 pktId
-+%22_uint
+ + %22_%22+ptype.getName()+%22
 _%22 +
@@ -3085,14 +3085,13 @@
 ype(
-uint32
+ptype
 );%0A 
@@ -3150,18 +3150,31 @@
 y(128 + 
-32
+paramSizeInBits
  * i, Re
@@ -4100,16 +4100,33 @@
 ception(
+%0A                
 %22Cannot 
@@ -4144,17 +4144,19 @@
 meter '%22
-+
+ + 
 PACKET_I
@@ -4166,17 +4166,19 @@
 ARA_NAME
-+
+ + 
 %22' in th

allow to specify the size of the parameters