package org.yamcs.xtceproc;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.ContainerExtractionResult;
import org.yamcs.parameter.ParameterValueList;
import org.yamcs.utils.BitBuffer;
import org.yamcs.xtce.Parameter;
import org.yamcs.xtce.SequenceContainer;
import org.yamcs.xtce.XtceDb;
import org.yamcs.xtceproc.ContainerProcessingContext.ContainerProcessingResult;

/**
 * 
 * Extracts parameters out of packets based on the XTCE description
 *
 * 
 */
public class XtceTmExtractor {
    private static final Logger log = LoggerFactory.getLogger(XtceTmExtractor.class);
    protected final Subscription subscription;
    private ProcessingStatistics stats=new ProcessingStatistics();

    private ContainerProcessingResult result;
    
    public final XtceDb xtcedb;
    final SequenceContainer rootContainer;
    ContainerProcessingOptions options = new ContainerProcessingOptions();
    final ProcessorData pcontext;
    /**
     * Creates a TmExtractor extracting data according to the XtceDb
     * @param xtcedb
     */
    public XtceTmExtractor(XtceDb xtcedb) {
        this(xtcedb, new ProcessorData(xtcedb));
    }
    /**
     * Create a new TM extractor with the given context
     * 
     * @param xtcedb
     * @param pcontext
     */
    public XtceTmExtractor(XtceDb xtcedb, ProcessorData pcontext) {
        this.xtcedb = xtcedb;
        this.subscription = new Subscription(xtcedb);
        rootContainer = xtcedb.getRootSequenceContainer();
        this.pcontext = pcontext;
    }
    
    /**
     * Adds a parameter to the current subscription list: 
     *  finds all the SequenceContainers in which this parameter may appear and adds them to the list.
     *  also for each sequence container adds the parameter needed to instantiate the sequence container.
     * @param param parameter to be added to the current subscription list 
     */
    public void startProviding(Parameter param) {
        synchronized(subscription) {
            subscription.addParameter(param);
        }
    }

    /**
     * Adds all containers and parameters to the subscription
     */
    public void startProvidingAll() {
        for (SequenceContainer c : xtcedb.getSequenceContainers()) {
            if (c.getBaseContainer() == null) {
                subscription.addAll(c);
            }
        }
    }

    public void stopProviding(Parameter param) {
    }

    /**
     * Extract one packet, starting at the root sequence container
     */
    public void processPacket(byte[] b, long generationTime, long acquisitionTime) {
        processPacket(b, generationTime, acquisitionTime, rootContainer);
    }

    /**
     * Extract one packet, starting at the specified container.
     * @param b 
     * @param generationTime 
     * @param aquisitionTime 
     * @param startContainer 
     */
    public void processPacket(byte[] b, long generationTime, long aquisitionTime, SequenceContainer startContainer) {
        result = new ContainerProcessingResult(aquisitionTime, generationTime, stats);
        try {
             synchronized(subscription) {
                BitBuffer buf = new BitBuffer(b);
                ContainerProcessingContext cpc = new ContainerProcessingContext(pcontext, buf, result, subscription, options);
                cpc.sequenceContainerProcessor.extract(startContainer);
            }
        } catch (Exception e) {
            log.error("got exception in tmextractor ", e);
        }
    }

    public void resetStatistics() {
        stats.reset();
    }

    public ProcessingStatistics getStatistics(){
        return stats;
    }
    
    public void startProviding(SequenceContainer sequenceContainer) {
        synchronized(subscription) {
            subscription.addSequenceContainer(sequenceContainer);
        }
    }

    public void stopProviding(SequenceContainer sequenceContainer) {
    }
    

    public ParameterValueList getParameterResult() {
        return result.params;
    }

    public List<ContainerExtractionResult> getContainerResult() {
        return result.containers;
    }

    public Subscription getSubscription() {
        return subscription;
    }

    @Override
    public String toString() {
        return subscription.toString();
    }
    public void setOptions(ContainerProcessingOptions opts) {
        this.options = opts;
    }
}

@@ -419,17 +419,16 @@
 %0A%0A/**%0A *
- 
 %0A * Extr
@@ -493,17 +493,16 @@
 on%0A *%0A *
- 
 %0A */%0Apub
@@ -776,20 +776,16 @@
 result;%0A
-    
 %0A    pub
@@ -957,24 +957,25 @@
 a pcontext;%0A
+%0A
     /**%0A    
@@ -1163,24 +1163,25 @@
 db));%0A    %7D%0A
+%0A
     /**%0A    
@@ -1238,17 +1238,16 @@
 t%0A     *
- 
 %0A     * 
@@ -1538,28 +1538,24 @@
 text;%0A    %7D%0A
-    
 %0A    /**%0A   
@@ -1608,17 +1608,16 @@
 on list:
- 
 %0A     * 
@@ -1892,17 +1892,16 @@
 ion list
- 
 %0A     */
@@ -2601,17 +2601,32 @@
 sPacket(
-b
+new BitBuffer(b)
 , genera
@@ -2730,17 +2730,21 @@
 the 
-specified
+root sequence
  con
@@ -2753,72 +2753,338 @@
 iner
-.
 %0A     *
- @param b %0A     * @param generationTime %0A     * @param
+/%0A    public void processPacket(BitBuffer buf, long generationTime, long acquisitionTime) %7B%0A        processPacket(buf, generationTime, acquisitionTime, rootContainer);%0A    %7D%0A%0A    /**%0A     * Extract one packet, starting at the specified container.%0A     */%0A    public void processPacket(byte%5B%5D b, long generationTime, long
  a
+c
 quis
@@ -3096,39 +3096,214 @@
 Time
- %0A     * @param startContainer 
+, SequenceContainer startContainer) %7B%0A        processPacket(new BitBuffer(b), generationTime, acquisitionTime, startContainer);%0A    %7D%0A%0A    /**%0A     * Extract one packet, starting at the specified container.
 %0A   
@@ -3333,32 +3333,37 @@
 ocessPacket(
-byte%5B%5D b
+BitBuffer buf
 , long gener
@@ -3379,16 +3379,17 @@
 , long a
+c
 quisitio
@@ -3479,16 +3479,17 @@
 Result(a
+c
 quisitio
@@ -3541,25 +3541,24 @@
             
- 
 synchronized
@@ -3578,58 +3578,8 @@
 ) %7B%0A
-                BitBuffer buf = new BitBuffer(b);%0A
     
@@ -4038,20 +4038,16 @@
 ;%0A    %7D%0A
-    
 %0A    pub
@@ -4304,20 +4304,16 @@
 %7B%0A    %7D%0A
-    
 %0A%0A    pu

Support extraction via passed BitBuffer