package pdu

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

type (
	PDU interface {
		Encode(*bytes.Buffer) error
		Decode(*bytes.Buffer) error
		// Size in bytes
		Size() int
		UpdateSize()
	}

	PDU_HEADER struct {
		Command_length  uint32
		Command_id      uint32
		Command_status  uint32
		Sequence_number uint32
	}

	GENERIC_NACK struct {
		Header *PDU_HEADER
	}
)

// Hmm the header can be partially encoded
// As in command_status can just be null
// So not 0s, null, non existent, not encoded
// So we'll have to maybe set them to nil or something...
// Wireshark dump of a submit_sm
// See header: 00 00 00 3e (size, 62 bytes), 00 00 00 04 (command_id), status and sequence number are 0
// So they are not encoded
// Here the header is 8 bytes, not 16
// 0000   02 00 00 00 45 00 00 66 6f ff 40 00 80 06 00 00   ....E..fo.@.....
// 0010   7f 00 00 01 7f 00 00 01 31 4f 0a d7 e8 b0 b1 b5   ........1O......
// 0020   3e 91 d9 dc 50 18 20 fa 2a 1f 00 00 00 00 00 3e   >...P. .*......>
// 0030   00 00 00 04 00 00 00 00 00 00 00 02 00 00 00 73   ...............s
// 0040   6d 70 70 5f 74 65 73 74 5f 31 00 00 00 31 32 33   mpp_test_1...123
// 0050   31 32 33 31 32 33 31 32 33 00 00 00 00 00 00 00   123123123.......
// 0060   00 c0 00 06 48 65 6c 6c 6f 21                     ....Hello!
// I AM NOT RIGHT
// Beyond the size and command_id, command_status and sequence_number here are:
// 00 00 00 00 (0) 00 00 00 02 (2)
//
// Another example - bind_transciever:
// 0000   02 00 00 00 45 00 00 47 6f fb 40 00 80 06 00 00   ....E..Go.@.....
// 0010   7f 00 00 01 7f 00 00 01 31 4f 0a d7 e8 b0 b1 96   ........1O......
// 0020   3e 91 d9 cb 50 18 20 fa df ab 00 00 00 00 00 1f   >...P. .........
// 0030   00 00 00 09 00 00 00 00 00 00 00 01 74 65 73 74   ............test
// 0040   00 74 65 73 74 00 00 50 00 00 00                  .test..P...
// 00 00 00 1f - 00 00 00 09 - 00 00 00 00 - 00 00 00 01 (header)
// 74 65 73 74 00 - 74 65 73 74 00 - 00 50 00 00 00
// ^system_id       ^password           ^interface_version
// What are the other 0s?
// Don't know

func (p *PDU_HEADER) Encode(buf *bytes.Buffer) error {
	if buf == nil {
		return fmt.Errorf("cannot encode into nil buffer")
	}
	binary.Write(buf, binary.BigEndian, p.Command_length)
	binary.Write(buf, binary.BigEndian, p.Command_id)
	binary.Write(buf, binary.BigEndian, p.Command_status)
	binary.Write(buf, binary.BigEndian, p.Sequence_number)
	return nil
}
func (p *PDU_HEADER) Decode(buf *bytes.Buffer) error {
	if buf == nil {
		return fmt.Errorf("cannot decode nil buffer")
	}
	binary.Read(buf, binary.BigEndian, &p.Command_length)
	binary.Read(buf, binary.BigEndian, &p.Command_id)
	binary.Read(buf, binary.BigEndian, &p.Command_status)
	binary.Read(buf, binary.BigEndian, &p.Sequence_number)
	return nil
}
func (p *PDU_HEADER) Size() int {
	return 16
}
func (p *PDU_HEADER) UpdateSize() {
	p.Command_length = uint32(p.Size())
}
