package pool

import (
	
	
	
	
	

	
	
)

var noDeadline = time.Time{}

type Conn struct {
	usedAt  int64 // atomic
	netConn net.Conn

	rd *proto.Reader
	bw *bufio.Writer
	wr *proto.Writer

	Inited    bool
	pooled    bool
	createdAt time.Time
}

func ( net.Conn) *Conn {
	 := &Conn{
		netConn:   ,
		createdAt: time.Now(),
	}
	.rd = proto.NewReader()
	.bw = bufio.NewWriter()
	.wr = proto.NewWriter(.bw)
	.SetUsedAt(time.Now())
	return 
}

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

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

func ( *Conn) ( net.Conn) {
	.netConn = 
	.rd.Reset()
	.bw.Reset()
}

func ( *Conn) ( []byte) (int, error) {
	return .netConn.Write()
}

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

func ( *Conn) ( context.Context,  time.Duration,  func( *proto.Reader) error) error {
	return internal.WithSpan(, "with_reader", func( context.Context) error {
		if  := .netConn.SetReadDeadline(.deadline(, ));  != nil {
			return internal.RecordError(, )
		}
		if  := (.rd);  != nil {
			return internal.RecordError(, )
		}
		return nil
	})
}

func ( *Conn) (
	 context.Context,  time.Duration,  func( *proto.Writer) error,
) error {
	return internal.WithSpan(, "with_writer", func( context.Context) error {
		if  := .netConn.SetWriteDeadline(.deadline(, ));  != nil {
			return internal.RecordError(, )
		}

		if .bw.Buffered() > 0 {
			.bw.Reset(.netConn)
		}

		if  := (.wr);  != nil {
			return internal.RecordError(, )
		}

		if  := .bw.Flush();  != nil {
			return internal.RecordError(, )
		}

		internal.WritesCounter.Add(, 1)

		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