using PlcSiemens.O;
using PlcSiemens.Protocol.Iso;

namespace PlcSiemens.Protocol.Header
{
    public class CotpHeader
    {
        public byte Length { get; set; }     // Header length : initialized to 6 (length without params - 1)

        // descending classes that add values in params field must update it.
        public byte PduType { get; set; }    // 0xE0 Connection request

        // 0xD0 Connection confirm
        // 0x80 Disconnect request
        // 0xDC Disconnect confirm
        public ushort DstRef { get; set; }     // Destination reference : Always 0x0000

        public ushort SrcRef { get; set; }      // Source reference : Always 0x0000
        public byte CoR { get; set; }       // If the telegram is used for Connection request/Confirm,

        // the meaning of this field is CLASS+OPTION :
        //   Class (High 4 bits) + Option (Low 4 bits)
        //   Class : Always 4 (0100) but is ignored in input (RFC States this)
        //   Option : Always 0, also this in ignored.
        // If the telegram is used for Disconnect request,
        // the meaning of this field is REASON :
        //    1     Congestion at TSAP
        //    2     Session entity not attached to TSAP
        //    3     Address unknown (at TCP connect time)
        //  128+0   Normal disconnect initiated by the session
        //          entity.
        //  128+1   Remote transport entity congestion at connect
        //          request time
        //  128+3   Connection negotiation failed
        //  128+5   Protocol Error
        //  128+8   Connection request refused on this network
        //          connection
        // Parameter data : depending on the protocol implementation.
        // ISO 8073 define several type of parameters, but RFC 1006 recognizes only
        // TSAP related parameters and PDU size.  See RFC 0983 for more details.
        public CoptParams Params { get; set; }

        /* Other params not used here, list only for completeness
            ACK_TIME     	   = 0x85,  1000 0101 Acknowledge Time
            RES_ERROR    	   = 0x86,  1000 0110 Residual Error Rate
            PRIORITY           = 0x87,  1000 0111 Priority
            TRANSIT_DEL  	   = 0x88,  1000 1000 Transit Delay
            THROUGHPUT   	   = 0x89,  1000 1001 Throughput
            SEQ_NR       	   = 0x8A,  1000 1010 Subsequence Number (in AK)
            REASSIGNMENT 	   = 0x8B,  1000 1011 Reassignment Time
            FLOW_CNTL    	   = 0x8C,  1000 1100 Flow Control Confirmation (in AK)
            TPDU_SIZE    	   = 0xC0,  1100 0000 TPDU Size
            SRC_TSAP     	   = 0xC1,  1100 0001 TSAP-ID / calling TSAP ( in CR/CC )
            DST_TSAP     	   = 0xC2,  1100 0010 TSAP-ID / called TSAP
            CHECKSUM     	   = 0xC3,  1100 0011 Checksum
            VERSION_NR   	   = 0xC4,  1100 0100 Version Number
            PROTECTION   	   = 0xC5,  1100 0101 Protection Parameters (user defined)
            OPT_SEL            = 0xC6,  1100 0110 Additional Option Selection
            PROTO_CLASS  	   = 0xC7,  1100 0111 Alternative Protocol Classes
            PREF_MAX_TPDU_SIZE = 0xF0,  1111 0000
            INACTIVITY_TIMER   = 0xF2,  1111 0010
            ADDICC             = 0xe0   1110 0000 Additional Information on Connection Clearing
        */

        public CotpHeader()
        {
            Params = new CoptParams();
        }

        public void GetByteBuffer(ByteBuffer buffer)
        {
            buffer.Push(Length);
            buffer.Push(PduType);
            buffer.Push(DstRef);
            buffer.Push(SrcRef);
            buffer.Push(CoR);
            Params.GetByteBuffer(buffer);
        }

        public void InitByBuffer(ByteBuffer buffer)
        {
            Length = buffer.PopByte();
            PduType = buffer.PopByte();
            DstRef = buffer.PopUshort();
            SrcRef = buffer.PopUshort();
            CoR = buffer.PopByte();
            Params.InitByBuffer(buffer);
        }
    }
}
