// Handle a unsubscribe for the different protocol levels.
func HandleUnsubscribe(c *stompngo.Connection, d, i string) {
	sbh := stompngo.Headers{}
	//
	switch c.Protocol() {
	case stompngo.SPL_12:
		sbh = sbh.Add("id", i)
	case stompngo.SPL_11:
		sbh = sbh.Add("id", i)
	case stompngo.SPL_10:
		sbh = sbh.Add("destination", d)
	default:
		llu.Fatalf("v1:%v v2:%v\n", "unsubscribe invalid protocol level, should not happen")
	}
	e := c.Unsubscribe(sbh)
	if e != nil {
		llu.Fatalf("v1:%v v2:%v d:%v\n", "unsubscribe failed", e, d)
	}
	return
}
// Handle a subscribe for the different protocol levels.
func doSubscribe(c *stompngo.Connection, d, id, a string, h stompngo.Headers) <-chan stompngo.MessageData {
	h = h.Add("destination", d).Add("ack", a)
	//
	switch c.Protocol() {
	case stompngo.SPL_12:
		// Add required id header
		h = h.Add("id", id)
	case stompngo.SPL_11:
		// Add required id header
		h = h.Add("id", id)
	case stompngo.SPL_10:
		// Nothing else to do here
	default:
		ll.Fatalf("v1:%v\n", "subscribe invalid protocol level, should not happen")
	}
	//
	r, e := c.Subscribe(h)
	if e != nil {
		ll.Fatalf("subscribe failed err:[%v]\n", e)
	}
	return r
}
// Handle ACKs for the different protocol levels.
func HandleAck(c *stompngo.Connection, h stompngo.Headers, id string) {
	ah := stompngo.Headers{}
	//
	switch c.Protocol() {
	case stompngo.SPL_12:
		ah = ah.Add("id", h.Value("ack"))
	case stompngo.SPL_11:
		ah = ah.Add("message-id", h.Value("message-id")).Add("subscription", id)
	case stompngo.SPL_10:
		ah = ah.Add("message-id", h.Value("message-id"))
	default:
		llu.Fatalf("v1:%v v2:%v\n", "ack invalid protocol level, should not happen")
	}
	if cv, ok := h.Contains(stompngo.HK_RECEIPT); ok {
		ah = ah.Add(stompngo.HK_RECEIPT, cv)
	}
	e := c.Ack(ah)
	if e != nil {
		llu.Fatalf("v1:%v v2:%v v3:%v\n", "ack failed", e, c.Protocol())
	}
	return
}
// Handle a subscribe for the different protocol levels.
func HandleSubscribe(c *stompngo.Connection, d, i, a string) <-chan stompngo.MessageData {
	h := stompngo.Headers{"destination", d, "ack", a}
	//
	switch c.Protocol() {
	case stompngo.SPL_12:
		// Add required id header
		h = h.Add("id", i)
	case stompngo.SPL_11:
		// Add required id header
		h = h.Add("id", i)
	case stompngo.SPL_10:
		// Nothing else to do here
	default:
		llu.Fatalf("v1:%v v2:%v\n", "subscribe invalid protocol level, should not happen")
	}
	//
	r, e := c.Subscribe(h)
	if e != nil {
		llu.Fatalf("v1:%v v2:%v\n", "subscribe failed", e)
	}
	return r
}
func runNextQueue(qn int, conn *stompngo.Connection) {

	qns := fmt.Sprintf("%d", qn) // string number of the queue
	conn.SetLogger(ll)           // stompngo logging
	pbc := sngecomm.Pbc()        // Print byte count
	d := senv.Dest() + qns       // Destination
	id := stompngo.Uuid()        // A unique name/id
	nmsgs := qn                  // int number of messages to get, same as queue number
	am := sngecomm.AckMode()     // ACK mode to use on SUBSCRIBE
	nfa := true                  // Need "final" ACK (possiby reset below)
	wh := stompngo.Headers{}     // Starting SUBSCRIBE headers

	// Sanity check ACK mode
	if conn.Protocol() == stompngo.SPL_10 &&
		am == stompngo.AckModeClientIndividual {
		ll.Fatalf("%stag:%s connsess:%s invalid_ack_mode am:%v proto:%v\n",
			exampid, tag, session,
			am, conn.Protocol()) //
	}
	// Do not do final ACK if running ACKs are issued
	if am == stompngo.AckModeClientIndividual ||
		am == stompngo.AckModeAuto {
		nfa = false
	}

	// Show run parameters
	ll.Printf("%stag:%s connsess:%s run_parms\n\tqns:%v\n\tpbc:%v\n\td:%v\n\tid:%v\n\tnmsgs:%v\n\tam:%v\n\tnfa:%v\n\twh:%v\n",
		exampid, tag, session,
		qns, pbc, d, id, nmsgs, am, nfa, wh)

	// Run SUBSCRIBE
	sc := doSubscribe(conn, d, id, am, wh)
	ll.Printf("%stag:%s connsess:%s stomp_subscribe_complete\n",
		exampid, tag, session)

	var md stompngo.MessageData  // Message data from basic read
	var lmd stompngo.MessageData // Possible save (copy) of received data
	mc := 1                      // Initial message number

	// Loop for the requested number of messages
GetLoop:
	for {
		ll.Printf("%stag:%s connsess:%s start_of_read_loop mc:%v nmsgs:%v\n",
			exampid, tag, session, mc, nmsgs)

		mcs := fmt.Sprintf("%d", mc) // string number message count

		// Get something from the stompngo read routine
		select {
		case md = <-sc:
		case md = <-conn.MessageData:
			//
			if md.Message.Command == stompngo.RECEIPT {
				ll.Printf("%stag:%s connsess:%s have_receipt md:%v\n",
					exampid, tag, session,
					md)
				continue GetLoop
			}
			ll.Fatalf("%stag:%s connsess:%s ERROR_frame hdrs:%v body:%v\n",
				exampid, tag, session,
				md.Message.Headers, string(md.Message.Body)) // Handle this ......
		}

		// Save message data for possible use in the final ACK
		if mc == nmsgs && nfa {
			lmd = md // Save last message
		}

		// Basic loop logging
		ll.Printf("%stag:%s connsess:%s channel_read_complete qn:%d mc:%d\n",
			exampid, tag, session,
			qn, mc)
		ll.Printf("%stag:%s connsess:%s message_number:%v\n",
			exampid, tag, session,
			mc)

		// Check if reader returned any error
		if md.Error != nil {
			ll.Fatalf("%stag:%s connsess:%s error_read error:%v",
				exampid, tag, session,
				md.Error) // Handle this ......
		}

		// Show frame type
		ll.Printf("%stag:%s connsess:%s frame_type cmd:%s\n",
			exampid, tag, session,
			md.Message.Command)

		// Pure sanity check:  this should *never* happen based on logic
		// above.
		if md.Message.Command != stompngo.MESSAGE {
			ll.Fatalf("%stag:%s connsess:%s error_frame_type md:%v",
				exampid, tag, session,
				md) // Handle this ......
		}

		// Show Message Headers
		wh := md.Message.Headers
		for j := 0; j < len(wh)-1; j += 2 {
			ll.Printf("%stag:%s connsess:%s Header:%s:%s\n",
				exampid, tag, session,
				wh[j], wh[j+1])
		}
		// Show (part of) Message Body
		if pbc > 0 {
			maxlen := pbc
			if len(md.Message.Body) < maxlen {
				maxlen = len(md.Message.Body)
			}
			ss := string(md.Message.Body[0:maxlen])
			ll.Printf("%stag:%s connsess:%s payload body:%s\n",
				exampid, tag, session,
				ss)
		}

		// Sanity check this message payload
		wm := wlp + mcs // The left part plus the (string) meassage number]
		bm := string(md.Message.Body)
		if bm != wm {
			ll.Fatalf("%stag:%s connsess:%s error_message_payload\n\tGot %s\n\tWant%s\n",
				exampid, tag, session,
				bm, wm) // Handle this ......
		} else {
			ll.Printf("%stag:%s connsess:%s  matched_body_string\n%s\n%s\n",
				exampid, tag, session,
				bm, wm) // Handle this ......)
		}

		// Run individual ACK if required
		if am == stompngo.AckModeClientIndividual {
			wh := md.Message.Headers // Copy Headers
			if ar {                  // ACK receipt wanted
				wh = wh.Add(stompngo.HK_RECEIPT, "rwanted-"+mcs)
			}
			sngecomm.HandleAck(conn, wh, id)
			ll.Printf("%stag:%s connsess:%s  individual_ack_complete mc:%v headers:%v\n",
				exampid, tag, session,
				mc, md.Message.Headers)

		}

		// Check for end of loop condition
		if mc == nmsgs {
			break
		}

		// Increment loop/message counter
		mc++
	}

	qc := make(chan bool)
	go drainSub(session, sc, qc, qn)
	dd := false

	// Issue the final ACK if needed
	if nfa {
		wh := lmd.Message.Headers // Copy Headers
		if ar {                   // ACK receipt wanted
			wh = wh.Add(stompngo.HK_RECEIPT, "rwanted-fin")
		}
		sngecomm.HandleAck(conn, wh, id)
		ll.Printf("%stag:%s connsess:%s  final_ack_complete\n",
			exampid, tag, session)
		if ar {
			ll.Printf("%stag:%s connsess:%s  ack_receive_wait_for_drain qn:%d\n",
				exampid, tag, session,
				qn)
			<-qc // Wait for drainSub
			ll.Printf("%stag:%s connsess:%s  ack_receive_drain_complete qn:%d\n",
				exampid, tag, session,
				qn)
			dd = true
			getReceipt(conn)
		}
	}

	if !dd {
		ll.Printf("%stag:%s connsess:%s  message_loop_wait_for_drain qn:%d\n",
			exampid, tag, session,
			qn)
		<-qc
		ll.Printf("%stag:%s connsess:%s  message_loop_drain_complete qn:%d\n",
			exampid, tag, session,
			qn)
	}

	// Unsubscribe (may be skipped if requested)
	if unsub {
		sngecomm.HandleUnsubscribe(conn, d, id)
		ll.Printf("%stag:%s connsess:%s stomp_unsubscribe_complete\n",
			exampid, tag, session)
	} else {
		ll.Printf("%stag:%s connsess:%s skipping_unsubscribe\n",
			exampid, tag, session)
	}
}