package youtube_annotations

import (
	"encoding/json"
	"fmt"

	"code.justin.tv/common/twitchhttp"
	"golang.org/x/net/context"
)

// Annotations represents whether yt annotations are enabled or not
type Annotations struct {
	Enabled bool `json:"enabled"`
}

// Client represents a youtube annotations client
type Client interface {
	GetYoutubeAnnotationsEnabled(ctx context.Context, channelID string, reqOpts *twitchhttp.ReqOpts) (*Annotations, error)
	EnableYoutubeAnnotations(ctx context.Context, channelID string, reqOpts *twitchhttp.ReqOpts) (*Annotations, error)
	DisableYoutubeAnnotations(ctx context.Context, channelID string, reqOpts *twitchhttp.ReqOpts) (*Annotations, error)
	ClearYoutubeAnnotations(ctx context.Context, channelID string, reqOpts *twitchhttp.ReqOpts) error
}

type clientImpl struct {
	twitchhttp.Client
}

var _ Client = new(clientImpl)

// NewClient returns an object implementing the Client interface
func NewClient(conf twitchhttp.ClientConf) (Client, error) {
	if conf.TimingXactName == "" {
		conf.TimingXactName = "youtube-annotations"
	}
	twitchClient, err := twitchhttp.NewClient(conf)
	return &clientImpl{twitchClient}, err
}

func (c *clientImpl) GetYoutubeAnnotationsEnabled(ctx context.Context, channelID string, reqOpts *twitchhttp.ReqOpts) (*Annotations, error) {
	req, err := c.NewRequest("GET", fmt.Sprintf("/enabled/%s", channelID), nil)
	if err != nil {
		return nil, err
	}

	resp, err := c.Do(ctx, req, twitchhttp.MergeReqOpts(reqOpts, twitchhttp.ReqOpts{
		StatName:       "service.youtube-annotations.get",
		StatSampleRate: 0.1,
	}))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var a Annotations
	err = json.NewDecoder(resp.Body).Decode(&a)
	if err != nil {
		return nil, err
	}

	return &a, nil
}

func (c *clientImpl) EnableYoutubeAnnotations(ctx context.Context, channelID string, reqOpts *twitchhttp.ReqOpts) (*Annotations, error) {
	req, err := c.NewRequest("POST", fmt.Sprintf("/enabled/%s", channelID), nil)
	if err != nil {
		return nil, err
	}

	resp, err := c.Do(ctx, req, twitchhttp.MergeReqOpts(reqOpts, twitchhttp.ReqOpts{
		StatName:       "service.youtube-annotations.enable",
		StatSampleRate: 0.1,
	}))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var a Annotations
	err = json.NewDecoder(resp.Body).Decode(&a)
	if err != nil {
		return nil, err
	}

	return &a, nil
}

func (c *clientImpl) DisableYoutubeAnnotations(ctx context.Context, channelID string, reqOpts *twitchhttp.ReqOpts) (*Annotations, error) {
	req, err := c.NewRequest("DELETE", fmt.Sprintf("/enabled/%s", channelID), nil)
	if err != nil {
		return nil, err
	}

	resp, err := c.Do(ctx, req, twitchhttp.MergeReqOpts(reqOpts, twitchhttp.ReqOpts{
		StatName:       "service.youtube-annotations.disable",
		StatSampleRate: 0.1,
	}))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var a Annotations
	err = json.NewDecoder(resp.Body).Decode(&a)
	if err != nil {
		return nil, err
	}

	return &a, nil
}

func (c *clientImpl) ClearYoutubeAnnotations(ctx context.Context, channelID string, reqOpts *twitchhttp.ReqOpts) error {
	req, err := c.NewRequest("DELETE", fmt.Sprintf("/annotations/%s", channelID), nil)
	if err != nil {
		return err
	}

	resp, err := c.Do(ctx, req, twitchhttp.MergeReqOpts(reqOpts, twitchhttp.ReqOpts{
		StatName:       "service.youtube-annotations.clear",
		StatSampleRate: 0.1,
	}))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	return nil
}
