class InboundFlightZone {

        public IMessagesStore.StoredMessage lookup(int messageID) {
            return m_sessionsStore.inboundInflight(clientID, messageID);
        }

        public void waitingRel(int messageID, IMessagesStore.StoredMessage msg) {
            m_sessionsStore.markAsInboundInflight(clientID, messageID, msg);
        }
    }

    private static final Logger LOG = LoggerFactory.getLogger(ClientSession.class);

    public final String clientID;

    private final ISessionsStore m_sessionsStore;

    // private BlockingQueue<AbstractMessage> m_queueToPublish = new
    // ArrayBlockingQueue<>(Constants.MAX_MESSAGE_QUEUE);
    private final OutboundFlightZone outboundFlightZone;
    private final InboundFlightZone inboundFlightZone;

    public ClientSession(String clientID, ISessionsStore sessionsStore) {
        this.clientID = clientID;
        this.m_sessionsStore = sessionsStore;
        this.outboundFlightZone = new OutboundFlightZone();
        this.inboundFlightZone = new InboundFlightZone();
    }

    /**
     * Return the list of persisted publishes for the given clientID. For QoS1 and QoS2 with clean
     * session flag, this method return the list of missed publish events while the client was
     * disconnected.
     *
     * @return the list of messages to be delivered for client related to the session.
     */
    public Queue<IMessagesStore.StoredMessage> queue() {
        LOG.info("Retrieving enqueued messages. CId={}", clientID);
        return this.m_sessionsStore.queue(clientID);
    }

    @Override
    public String toString() {
        return "ClientSession{clientID='" + clientID + '\'' + "}";
    }


    public void disconnect(String userId, boolean cleanSession, boolean disableSession) {
        if (cleanSession) {
            LOG.info("Client disconnected. Removing its subscriptions. ClientId={}", clientID);
            // cleanup topic subscriptions
            cleanSession(userId);
        } else if(disableSession) {
            LOG.info("Client disconnected. disable session. ClientId={}", clientID);
            m_sessionsStore.disableSession(userId, this.clientID);
        }
    }

    public void cleanSession(String userId) {
        m_sessionsStore.cleanSession(userId, this.clientID);
    }


    public int nextPacketId() {
        return this.m_sessionsStore.nextPacketID(this.clientID);
    }

    public IMessagesStore.StoredMessage inFlightAcknowledged(int messageID) {
        return outboundFlightZone.acknowledged(messageID);
    }

    /**
     * Mark the message identified by guid as publish in flight.
     *
     * @return the packetID for the message in flight.
     * */
    public int inFlightAckWaiting(IMessagesStore.StoredMessage msg) {<FILL_FUNCTION_BODY>

        LOG.debug("Adding message ot inflight zone. ClientId={}", clientID);
        int messageId = ClientSession.this.nextPacketId();
        outboundFlightZone.waitingAck(messageId, msg);
        return messageId;
    
<no_super_class>