/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * The Initial Developer of this code is David Baum.
 * Portions created by David Baum are Copyright (C) 1999 David Baum.
 * All Rights Reserved.
 *
 * Portions created by John Hansen are Copyright (C) 2005 John Hansen.
 * All Rights Reserved.
 *
 */
#ifndef __RCX_PipeTransport_h
#define __RCX_PipeTransport_h

#ifndef __RCX_Transport_h
#include "RCX_Transport.h"
#endif

#ifndef __RCX_Pipe_h
#include "RCX_Pipe.h"
#endif


class RCX_PipeTransport : public RCX_Transport
{
public:
    enum {
        kMinTimeout = 50,   ///< Minimum value, in ms, that Rx timeouts will be set to dynamically
        kMaxTimeout = 500   ///< Maximum value, in ms, that Rx timeouts will be set to dynamically  
    };

    RCX_PipeTransport(RCX_Pipe *pipe);
    virtual ~RCX_PipeTransport();

    virtual RCX_Result Open(RCX_TargetType target, const char *deviceName, ULong options);
    virtual void Close();

    /// Transport sending implementation. Most Send implementations wrap this one.
    virtual RCX_Result Send(const UByte *txData, int txLength, UByte *rxData,
        int rxExpected, int rxMax, bool retry, int timeout);

    virtual bool FastModeSupported() const;
    virtual bool FastModeOddParity() const { return fPipe->GetCapabilities() & RCX_Pipe::kFastOddParityFlag; }
    virtual void SetFastMode(bool fast);
    virtual bool GetFastMode() const { return fFastMode; }
    virtual bool GetComplementData() const { return fComplementData; }

    /// the Receive() interface is still experiemental
    RCX_Result Receive(UByte *data, int maxLength, bool echo);

private:
    int ExpectedReceiveLen(const int rxExpected);
    void BuildTxData(const UByte *data, int length, bool duplicateReduction);
    void SendFromTxBuffer(int delay);
    RCX_Result ReceiveReply(int rxExpected, int timeout, int &replyOffset);

    int FindReply(const int rxExpected, int &offset);
    void CopyReply(UByte *dst, int offset, int length);
    void AdjustTimeout(RCX_Result result, int attempt);

    void ProcessRxByte(UByte b);
    int VerifyReply(const int rxExpected, const UByte *data, int length, UByte cmd);

    RCX_Pipe* fPipe;
    UByte* fTxData;
    int fTxLength;
    UByte fTxLastCommand;

    UByte* fRxData;
    int  fRxLength;

    /// Used by the Receive() state machine
    int fRxState;

    // parameters that define packet formatting
    const UByte* fSync;     ///< sync pattern for packets (depends on target and usb mode)
    bool fComplementData;   ///< Data transfers will also contain data complement if this is set

    bool fVerbose;          ///< Flag that captures -v option from command invocation
    bool fSynced;           ///< Flag that indicates we have a sync with the remote brick
    RCX_TargetType fTarget; ///< Current target type.
    int fRxTimeout;         ///< Receive reply timeouts if dynamic timeouts are enabled @see fDynamicTimeout

    /// Adjust receive timeouts based on reply success/failure; always true on Open.
    /// @see fRxTimeout
    // TODO: maybe make this a user-settable option?
    bool fDynamicTimeout;

    /// use for fast download
    bool fFastMode;
};


#endif
