package pool

import (
	
	
	
	
	
)

var noDeadline = time.Time{}

type Conn struct {
	netConn net.Conn
	rd      *ReaderContext

	ProcessID int32
	SecretKey int32
	lastID    int64

	createdAt time.Time
	usedAt    uint32 // atomic
	pooled    bool
	Inited    bool
}

func ( net.Conn) *Conn {
	 := &Conn{
		createdAt: time.Now(),
	}
	.SetNetConn()
	.SetUsedAt(time.Now())
	return 
}

func ( *Conn) () time.Time {
	 := atomic.LoadUint32(&.usedAt)
	return time.Unix(int64(), 0)
}

func ( *Conn) ( time.Time) {
	atomic.StoreUint32(&.usedAt, uint32(.Unix()))
}

func ( *Conn) () net.Addr {
	return .netConn.RemoteAddr()
}

func ( *Conn) ( net.Conn) {
	.netConn = 
	if .rd != nil {
		.rd.Reset()
	}
}

func ( *Conn) () {
	if .rd != nil {
		panic("not reached")
	}
	.rd = NewReaderContext()
	.rd.Reset(.netConn)
}

func ( *Conn) () net.Conn {
	return .netConn
}

func ( *Conn) () string {
	.lastID++
	return strconv.FormatInt(.lastID, 10)
}

func ( *Conn) (
	 context.Context,  time.Duration,  func( *ReaderContext) error,
) error {
	if  := .netConn.SetReadDeadline(.deadline(, ));  != nil {
		return 
	}

	 := .rd
	if  == nil {
		 = GetReaderContext()
		defer PutReaderContext()

		.Reset(.netConn)
	}

	.bytesRead = 0

	if  := ();  != nil {
		return 
	}

	return nil
}

func ( *Conn) (
	 context.Context,  time.Duration,  func( *WriteBuffer) error,
) error {
	 := GetWriteBuffer()
	defer PutWriteBuffer()

	if  := ();  != nil {
		return 
	}

	return .writeBuffer(, , )
}

func ( *Conn) ( context.Context,  time.Duration,  *WriteBuffer) error {
	return .writeBuffer(, , )
}

func ( *Conn) (
	 context.Context,
	 time.Duration,
	 *WriteBuffer,
) error {
	if  := .netConn.SetWriteDeadline(.deadline(, ));  != nil {
		return 
	}
	if ,  := .netConn.Write(.Bytes);  != nil {
		return 
	}
	return nil
}

func ( *Conn) () error {
	return .netConn.Close()
}

func ( *Conn) ( context.Context,  time.Duration) time.Time {
	 := time.Now()
	.SetUsedAt()

	if  > 0 {
		 = .Add()
	}

	if  != nil {
		,  := .Deadline()
		if  {
			if  == 0 {
				return 
			}
			if .Before() {
				return 
			}
			return 
		}
	}

	if  > 0 {
		return 
	}

	return noDeadline
}