package com.galois.qrstream.qrpipe;

import java.util.HashMap;
import java.util.Map;

/**
 * Stores message from sequence of decoded QR codes. Note, the initial
 * capacity is unknown until first QR code is read.
 */
public class DecodedMessage {
  /* Container for saving received data */
  private Map<Integer, byte[]> receivedData;

  /* Track progress of decoding */
  private final DecodeState decodeState;
  private final IProgress decodeProgress;

  private static final boolean DEBUG = false;

  public DecodedMessage (IProgress progress) {
    receivedData = null;
    decodeState = new DecodeState();
    decodeProgress = progress;
    decodeProgress.changeState(decodeState);
  }

  /**
   * Mark progress of data transmission by setting the {@code chunkId}
   * bit in {@code DecodeState} to true whenever a QR code has been decoded.
   * It also sets up the initial sizes of {@code receivedData} if this is
   * the first QR code encountered.
   */
  public void saveMessageChunk(int chunkId, int totalChunks, byte[] msg) {
    if (totalChunks < 1 || chunkId < 1) {
      throw new IllegalArgumentException("Expected positive chunk inputs.");
    }else if (msg == null) {
      throw new NullPointerException("Invalid input for msg.");
    }
    // Set up message container if this is the first QR code encountered.
    // Could have initialized before knowing capacity but then
    // it's likely map would need to be resized.
    if (receivedData == null) {
      receivedData = new HashMap<Integer, byte[]>(totalChunks);
      decodeState.setInitialCapacity(totalChunks);
      if(DEBUG) {
        System.out.println("saveMessageChunk: initialize to size " + totalChunks);
      }
    }
    // Save message part if we haven't seen it already.
    if (!receivedData.containsKey(chunkId)) {
      decodeState.markDataReceived(chunkId);
      receivedData.put(chunkId, msg.clone());
      decodeProgress.changeState(decodeState);
      if(DEBUG) {
        System.out.println("saveMessageChunk: updated state to " + decodeState.getState());
      }
    }else{
      if(DEBUG) {
        System.out.println("saveMessageChunk: nothing to do - already recorded chunk");
      }
    }
  }

}

@@ -47,20 +47,50 @@
 va.util.
-Hash
+Map.Entry;%0Aimport java.util.Sorted
 Map;%0Aimp
@@ -103,16 +103,20 @@
 va.util.
+Tree
 Map;%0A%0A/*
@@ -277,17 +277,17 @@
 ge %7B%0A  /
-*
+/
  Contain
@@ -313,30 +313,104 @@
 ved data
- */%0A  private 
+.%0A  // Using SortedMap so that message can be assembled in order.%0A  private final Sorted
 Map%3CInte
@@ -440,17 +440,17 @@
 ta;%0A%0A  /
-*
+/
  Track p
@@ -472,52 +472,8 @@
 ding
- */%0A  private final DecodeState decodeState;
 %0A  p
@@ -511,17 +511,16 @@
 ogress;%0A
-%0A
   privat
@@ -525,41 +525,30 @@
 ate 
-static final boolean DEBUG = fals
+DecodeState decodeStat
 e;%0A%0A
@@ -602,140 +602,145 @@
     
-receivedData = null;%0A    decodeState = new DecodeState();
+// Initialize 'decodeState' upon decoding first QR code.
 %0A    
-decodeProgress = progress;%0A    decodeProgress.changeState(decodeState)
+receivedData = new TreeMap%3CInteger, byte%5B%5D%3E();%0A    decodeProgress = progress
 ;%0A  
@@ -1387,136 +1387,23 @@
     
-// Could have initialized before knowing capacity but then%0A    // it's likely map would need to be resized.%0A    if (receivedData
+if (decodeState
  == 
@@ -1420,225 +1420,79 @@
     
-receivedData
+decodeState
  = new 
-HashMap%3CInteger, byte%5B%5D%3E(totalChunks);%0A      decodeState.setInitialCapacity(totalChunks);%0A      if(DEBUG) %7B%0A        System.out.println(%22saveMessageChunk: initialize to size %22 + totalChunks);%0A      %7D
+DecodeState(totalChunks);%0A      receivedData.clear();
 %0A   
@@ -1600,53 +1600,8 @@
 ) %7B%0A
-      decodeState.markDataReceived(chunkId);%0A
     
@@ -1638,24 +1638,69 @@
 g.clone());%0A
+      decodeState.markDataReceived(chunkId);%0A
       decode
@@ -1742,246 +1742,14 @@
     
-  if(DEBUG) %7B%0A        System.out.println(%22saveMessageChunk: updated state to %22 + decodeState.getState());%0A      %7D%0A    %7Delse%7B%0A      if(DEBUG) %7B%0A        System.out.println(%22saveMessageChunk: nothing to do - already recorded chunk%22);%0A      %7D
+%7Delse%7B
 %0A   
@@ -1755,11 +1755,10 @@
   %7D%0A  %7D%0A
-%0A
 %7D%0A

remove lazy initialization of message container