package webrequest

import (
	"encoding/json"
	"fmt"
	"image"
	"io/ioutil"
	"net/http"
	"strings"

	"gitbase.de/apairon/mark2web/pkg/progress"

	"gitbase.de/apairon/mark2web/pkg/logger"
)

type wrImageEntry struct {
	img    image.Image
	format string
}

type wrJSONEntry struct {
	data interface{}
}

var wrImageCache = make(map[string]*wrImageEntry)
var wrJSONCache = make(map[string]*wrJSONEntry)

// Get will fetch an url and returns reponse
func Get(url string, opts interface{}) (resp *http.Response, err error) {
	logger.N("requesting url via GET %s", url)

	progress.IncrTotal("web request")
	progress.DescribeCurrent("web request", url)
	resp, err = http.Get(url)
	progress.IncrDone("web request")
	return resp, err
}

// GetJSON will GET a json object/array from a given URL
func GetJSON(url string) interface{} {
	cached := wrJSONCache[url]
	if cached == nil {
		resp, err := Get(url, nil)
		logger.Eexit(err, "could not get url '%s'", url)
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		logger.Eexit(err, "could not read body from url '%s'", url)

		logger.D("output from url '%s':\n%s", url, string(body))

		if resp.StatusCode >= 400 {
			logger.Exit("bad status '%d - %s' from url '%s'", resp.StatusCode, resp.Status, url)
		}

		contentType := resp.Header.Get("Content-Type")

		if strings.Contains(contentType, "json") {

		} else {
			logger.Exit("is not json '%s' from url '%s'", contentType, url)
		}

		cached = new(wrJSONEntry)

		jsonMap := make(map[string]interface{})
		err = json.Unmarshal(body, &jsonMap)
		if err == nil {
			cached.data = jsonMap
		} else {
			jsonArrayMap := make([]map[string]interface{}, 0)
			err = json.Unmarshal(body, &jsonArrayMap)
			if err == nil {
				cached.data = jsonArrayMap
			} else {
				logger.Exit("could not read json from '%s': invalid type", url)
			}
		}

		wrJSONCache[url] = cached

	}
	return cached.data
}

// GetImage gets an image from an url
func GetImage(url string) (image.Image, string, error) {
	cached := wrImageCache[url]
	if cached == nil {
		resp, err := Get(url, nil)
		if err != nil {
			return nil, "", fmt.Errorf("could not get url '%s': %s", url, err)
		}

		img, format, err := image.Decode(resp.Body)
		if err != nil {
			return nil, "", fmt.Errorf("could read body from url '%s': %s", url, err)
		}

		cached = &wrImageEntry{
			img:    img,
			format: format,
		}

		wrImageCache[url] = cached
	}

	return cached.img, cached.format, nil
}
