package api

import (
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"code.justin.tv/video/spectre/playhead"
	"code.justin.tv/video/spectre/util"

	"github.com/zenazn/goji/web"
)

var ErrPlayheadNotFound = errors.New("api: channel is not currently offline broadcasting")

func (T *Router) ShowManifest(c web.C, w http.ResponseWriter, r *http.Request) {
	t0 := time.Now()
	channelID, err := idToInt(strings.Split(c.URLParams["stream_id"], "_")[0])
	if err != nil {
		T.ServeError(w, r, err)
		return
	}

	p, found := playhead.GetPlayhead(channelID)
	if !found {
		playheadRequest := PlayheadRequest{
			ChannelID: channelID,
			DoneCh:    make(chan util.Nothing),
		}
		T.RequestChan <- playheadRequest
		<-playheadRequest.DoneCh
		p, found = playhead.GetPlayhead(channelID)
	}

	if !found {
		T.ServeError(w, r, ErrPlayheadNotFound)
		return
	}

	t1 := time.Now()
	w.Header().Set("Content-Type", "application/x-mpegURL")
	w.Write(p.ActiveManifest(c.URLParams["format"], c.URLParams["stream_id"]))
	t2 := time.Now()

	go func() {
		T.StatsdClient.Timing("show_manifest.get_playhead", t1.Sub(t0))
		T.StatsdClient.Timing("show_manifest.write_active_manifest", t2.Sub(t1))
		if t2.Sub(t1) > time.Second {
			T.StatsdClient.Incr("show_manifest.write_active_manifest_long")
		}
	}()
}

func (T *Router) ShowChunk(c web.C, w http.ResponseWriter, r *http.Request) {
	t0 := time.Now()
	channelID, err := idToInt(strings.Split(c.URLParams["stream_id"], "_")[0])
	if err != nil {
		T.ServeError(w, r, err)
		return
	}

	p, found := playhead.GetPlayhead(channelID)
	if !found {
		playheadRequest := PlayheadRequest{
			ChannelID: channelID,
			DoneCh:    make(chan util.Nothing),
		}
		T.RequestChan <- playheadRequest
		<-playheadRequest.DoneCh
		p, found = playhead.GetPlayhead(channelID)
	}

	if !found {
		T.ServeError(w, r, ErrPlayheadNotFound)
		return
	}

	t1 := time.Now()
	chunkURI := c.URLParams["file"]
	if r.URL.Query().Get("start_offset") != "" {
		chunkURI = fmt.Sprintf(
			"%v?start_offset=%v&end_offset=%v",
			chunkURI,
			r.URL.Query().Get("start_offset"),
			r.URL.Query().Get("end_offset"),
		)
	}

	vodID, err := idToInt(r.URL.Query().Get("vod_id"))
	if err != nil {
		T.ServeError(w, r, err)
	}

	b, err := p.GetChunk(vodID, c.URLParams["format"], chunkURI)
	t2 := time.Now()

	if err != nil {
		T.ServeError(w, r, err)
		return
	}

	w.Header().Set("Content-Type", "video/MP2T")
	w.Write(b)

	go func() {
		T.StatsdClient.Timing("show_chunk.get_playhead", t1.Sub(t0))
		T.StatsdClient.Timing("show_chunk.get_chunk", t2.Sub(t1))
		if t2.Sub(t1) > time.Second {
			T.StatsdClient.Incr("show_chunk.get_chunk_long")
		}
	}()
}

func (T *Router) ShowThumbnail(c web.C, w http.ResponseWriter, r *http.Request) {
	channelID, err := idToInt(strings.Split(c.URLParams["stream_id"], "_")[0])
	if err != nil {
		T.ServeError(w, r, err)
		return
	}
	p, found := playhead.GetPlayhead(channelID)
	if !found {
		T.ServeError(w, r, ErrPlayheadNotFound)
		return
	}

	b, err := p.Thumbnail()
	if err != nil {
		T.ServeError(w, r, err)
		return
	}

	w.Header().Set("Content-Type", "image/jpeg")
	w.Header().Set("Content-Length", strconv.Itoa(len(b)))
	w.Write(b)
}
