package packp

import (
	"bytes"
	"fmt"
	"io"
	"time"

	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/format/pktline"
)

// Encode writes the UlReq encoding of u to the stream.
//
// All the payloads will end with a newline character.  Wants and
// shallows are sorted alphabetically.  A depth of 0 means no depth
// request is sent.
func (u *UploadRequest) Encode(w io.Writer) error {
	e := newUlReqEncoder(w)
	return e.Encode(u)
}

type ulReqEncoder struct {
	pe   *pktline.Encoder // where to write the encoded data
	data *UploadRequest   // the data to encode
	err  error            // sticky error
}

func newUlReqEncoder(w io.Writer) *ulReqEncoder {
	return &ulReqEncoder{
		pe: pktline.NewEncoder(w),
	}
}

func (e *ulReqEncoder) Encode(v *UploadRequest) error {
	e.data = v

	if len(v.Wants) == 0 {
		return fmt.Errorf("empty wants provided")
	}

	plumbing.HashesSort(e.data.Wants)
	for state := e.encodeFirstWant; state != nil; {
		state = state()
	}

	return e.err
}

func (e *ulReqEncoder) encodeFirstWant() stateFn {
	var err error
	if e.data.Capabilities.IsEmpty() {
		err = e.pe.Encodef("want %s\n", e.data.Wants[0])
	} else {
		err = e.pe.Encodef(
			"want %s %s\n",
			e.data.Wants[0],
			e.data.Capabilities.String(),
		)
	}

	if err != nil {
		e.err = fmt.Errorf("encoding first want line: %s", err)
		return nil
	}

	return e.encodeAditionalWants
}

func (e *ulReqEncoder) encodeAditionalWants() stateFn {
	last := e.data.Wants[0]
	for _, w := range e.data.Wants[1:] {
		if bytes.Compare(last[:], w[:]) == 0 {
			continue
		}

		if err := e.pe.Encodef("want %s\n", w); err != nil {
			e.err = fmt.Errorf("encoding want %q: %s", w, err)
			return nil
		}

		last = w
	}

	return e.encodeShallows
}

func (e *ulReqEncoder) encodeShallows() stateFn {
	plumbing.HashesSort(e.data.Shallows)

	var last plumbing.Hash
	for _, s := range e.data.Shallows {
		if bytes.Compare(last[:], s[:]) == 0 {
			continue
		}

		if err := e.pe.Encodef("shallow %s\n", s); err != nil {
			e.err = fmt.Errorf("encoding shallow %q: %s", s, err)
			return nil
		}

		last = s
	}

	return e.encodeDepth
}

func (e *ulReqEncoder) encodeDepth() stateFn {
	switch depth := e.data.Depth.(type) {
	case DepthCommits:
		if depth != 0 {
			commits := int(depth)
			if err := e.pe.Encodef("deepen %d\n", commits); err != nil {
				e.err = fmt.Errorf("encoding depth %d: %s", depth, err)
				return nil
			}
		}
	case DepthSince:
		when := time.Time(depth).UTC()
		if err := e.pe.Encodef("deepen-since %d\n", when.Unix()); err != nil {
			e.err = fmt.Errorf("encoding depth %s: %s", when, err)
			return nil
		}
	case DepthReference:
		reference := string(depth)
		if err := e.pe.Encodef("deepen-not %s\n", reference); err != nil {
			e.err = fmt.Errorf("encoding depth %s: %s", reference, err)
			return nil
		}
	default:
		e.err = fmt.Errorf("unsupported depth type")
		return nil
	}

	return e.encodeFlush
}

func (e *ulReqEncoder) encodeFlush() stateFn {
	if err := e.pe.Flush(); err != nil {
		e.err = fmt.Errorf("encoding flush-pkt: %s", err)
		return nil
	}

	return nil
}
