package main

import (
	"bytes"
	"fmt"
	"image"
	"net/http"
	"strings"
	"time"

	"github.com/animenotifier/arn"
	"github.com/parnurzeal/gorequest"
)

var netLog = avatarLog.NewChannel("NET")

// Avatar represents a single image and the name of the format.
type Avatar struct {
	User   *arn.User
	Image  image.Image
	Data   []byte
	Format string
}

// Extension ...
func (avatar *Avatar) Extension() string {
	switch avatar.Format {
	case "jpg", "jpeg":
		return ".jpg"
	case "png":
		return ".png"
	case "gif":
		return ".gif"
	default:
		return ""
	}
}

// String returns a text representation of the format, width and height.
func (avatar *Avatar) String() string {
	return fmt.Sprint(avatar.Format, " | ", avatar.Image.Bounds().Dx(), "x", avatar.Image.Bounds().Dy())
}

// AvatarFromURL downloads and decodes the image from an URL and creates an Avatar.
func AvatarFromURL(url string, user *arn.User) *Avatar {
	// Download
	response, data, networkErrs := gorequest.New().Get(url).EndBytes()

	// Network errors
	if len(networkErrs) > 0 {
		netLog.Error(user.Nick, url, networkErrs[0])
		return nil
	}

	// Retry HTTP only version after 5 seconds if service unavailable
	if response == nil || response.StatusCode == http.StatusServiceUnavailable {
		time.Sleep(5 * time.Second)
		response, data, networkErrs = gorequest.New().Get(strings.Replace(url, "https://", "http://", 1)).EndBytes()
	}

	// Network errors on 2nd try
	if len(networkErrs) > 0 {
		netLog.Error(user.Nick, url, networkErrs[0])
		return nil
	}

	// Bad status codes
	if response.StatusCode != http.StatusOK {
		netLog.Error(user.Nick, url, response.StatusCode)
		return nil
	}

	// Decode
	img, format, decodeErr := image.Decode(bytes.NewReader(data))

	if decodeErr != nil {
		netLog.Error(user.Nick, url, decodeErr)
		return nil
	}

	return &Avatar{
		User:   user,
		Image:  img,
		Data:   data,
		Format: format,
	}
}