package sshfx

import (
	
)

// StatusPacket defines the SSH_FXP_STATUS packet.
//
// Specified in https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt#section-7
type StatusPacket struct {
	StatusCode   Status
	ErrorMessage string
	LanguageTag  string
}

// Error makes StatusPacket an error type.
func ( *StatusPacket) () string {
	if .ErrorMessage == "" {
		return "sftp: " + .StatusCode.String()
	}

	return fmt.Sprintf("sftp: %s: %q", .StatusCode, .ErrorMessage)
}

// Is returns true if target is a StatusPacket with the same StatusCode,
// or target is a Status code which is the same as SatusCode.
func ( *StatusPacket) ( error) bool {
	if ,  := .(*StatusPacket);  {
		return .StatusCode == .StatusCode
	}

	return .StatusCode == 
}

// Type returns the SSH_FXP_xy value associated with this packet type.
func ( *StatusPacket) () PacketType {
	return PacketTypeStatus
}

// MarshalPacket returns p as a two-part binary encoding of p.
func ( *StatusPacket) ( uint32,  []byte) (,  []byte,  error) {
	 := NewBuffer()
	if .Cap() < 9 {
		// uint32(error/status code) + string(error message) + string(language tag)
		 := 4 + 4 + len(.ErrorMessage) + 4 + len(.LanguageTag)
		 = NewMarshalBuffer()
	}

	.StartPacket(PacketTypeStatus, )
	.AppendUint32(uint32(.StatusCode))
	.AppendString(.ErrorMessage)
	.AppendString(.LanguageTag)

	return .Packet()
}

// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
// It is assumed that the uint32(request-id) has already been consumed.
func ( *StatusPacket) ( *Buffer) ( error) {
	* = StatusPacket{
		StatusCode:   Status(.ConsumeUint32()),
		ErrorMessage: .ConsumeString(),
		LanguageTag:  .ConsumeString(),
	}

	return .Err
}

// HandlePacket defines the SSH_FXP_HANDLE packet.
type HandlePacket struct {
	Handle string
}

// Type returns the SSH_FXP_xy value associated with this packet type.
func ( *HandlePacket) () PacketType {
	return PacketTypeHandle
}

// MarshalPacket returns p as a two-part binary encoding of p.
func ( *HandlePacket) ( uint32,  []byte) (,  []byte,  error) {
	 := NewBuffer()
	if .Cap() < 9 {
		 := 4 + len(.Handle) // string(handle)
		 = NewMarshalBuffer()
	}

	.StartPacket(PacketTypeHandle, )
	.AppendString(.Handle)

	return .Packet()
}

// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
// It is assumed that the uint32(request-id) has already been consumed.
func ( *HandlePacket) ( *Buffer) ( error) {
	* = HandlePacket{
		Handle: .ConsumeString(),
	}

	return .Err
}

// DataPacket defines the SSH_FXP_DATA packet.
type DataPacket struct {
	Data []byte
}

// Type returns the SSH_FXP_xy value associated with this packet type.
func ( *DataPacket) () PacketType {
	return PacketTypeData
}

// MarshalPacket returns p as a two-part binary encoding of p.
func ( *DataPacket) ( uint32,  []byte) (,  []byte,  error) {
	 := NewBuffer()
	if .Cap() < 9 {
		 := 4 // uint32(len(data)); data content in payload
		 = NewMarshalBuffer()
	}

	.StartPacket(PacketTypeData, )
	.AppendUint32(uint32(len(.Data)))

	return .Packet(.Data)
}

// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
// It is assumed that the uint32(request-id) has already been consumed.
//
// If p.Data is already populated, and of sufficient length to hold the data,
// then this will copy the data into that byte slice.
//
// If p.Data has a length insufficient to hold the data,
// then this will make a new slice of sufficient length, and copy the data into that.
//
// This means this _does not_ alias any of the data buffer that is passed in.
func ( *DataPacket) ( *Buffer) ( error) {
	* = DataPacket{
		Data: .ConsumeByteSliceCopy(.Data),
	}

	return .Err
}

// NamePacket defines the SSH_FXP_NAME packet.
type NamePacket struct {
	Entries []*NameEntry
}

// Type returns the SSH_FXP_xy value associated with this packet type.
func ( *NamePacket) () PacketType {
	return PacketTypeName
}

// MarshalPacket returns p as a two-part binary encoding of p.
func ( *NamePacket) ( uint32,  []byte) (,  []byte,  error) {
	 := NewBuffer()
	if .Cap() < 9 {
		 := 4 // uint32(len(entries))

		for ,  := range .Entries {
			 += .Len()
		}

		 = NewMarshalBuffer()
	}

	.StartPacket(PacketTypeName, )
	.AppendUint32(uint32(len(.Entries)))

	for ,  := range .Entries {
		.MarshalInto()
	}

	return .Packet()
}

// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
// It is assumed that the uint32(request-id) has already been consumed.
func ( *NamePacket) ( *Buffer) ( error) {
	 := .ConsumeCount()
	if .Err != nil {
		return .Err
	}

	* = NamePacket{
		Entries: make([]*NameEntry, 0, ),
	}

	for  := 0;  < ; ++ {
		var  NameEntry
		if  := .UnmarshalFrom();  != nil {
			return 
		}

		.Entries = append(.Entries, &)
	}

	return .Err
}

// AttrsPacket defines the SSH_FXP_ATTRS packet.
type AttrsPacket struct {
	Attrs Attributes
}

// Type returns the SSH_FXP_xy value associated with this packet type.
func ( *AttrsPacket) () PacketType {
	return PacketTypeAttrs
}

// MarshalPacket returns p as a two-part binary encoding of p.
func ( *AttrsPacket) ( uint32,  []byte) (,  []byte,  error) {
	 := NewBuffer()
	if .Cap() < 9 {
		 := .Attrs.Len() // ATTRS(attrs)
		 = NewMarshalBuffer()
	}

	.StartPacket(PacketTypeAttrs, )
	.Attrs.MarshalInto()

	return .Packet()
}

// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
// It is assumed that the uint32(request-id) has already been consumed.
func ( *AttrsPacket) ( *Buffer) ( error) {
	return .Attrs.UnmarshalFrom()
}