package main

import (
	"compress/gzip"
	"fmt"
	"html/template"
	"io"
	"log"
	"mime"
	"net/http"
	"net/url"
	"path/filepath"
	"strings"
	"time"

	"code.justin.tv/common/golibs/statsd"
	"goji.io/pat"
	"golang.org/x/net/context"
)

func assetProxy(hostport string, s statsd.Stats) func(context.Context, http.ResponseWriter, *http.Request) {
	return func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
		nameClean := strings.Replace(strings.Replace(r.URL.Path, ".", "_", -1), "/", "_", -1)
		bucket := fmt.Sprintf("%s.%s", "asset", nameClean)
		s.Incr(bucket)

		// Allow CORS to facilitate darklaunching
		w.Header().Set("Access-Control-Allow-Origin", "*")

		// Generate a new url with the same path + new host as www-cdn
		path := r.URL.Path
		proxyURL := &url.URL{
			Scheme: "http",
			Host:   hostport,
			Path:   path,
		}

		resp, err := http.Get(proxyURL.String())
		if err != nil {
			log.Printf("Failed to load proxy asset %s: %s", path, err)
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprint(w, "Internal Server Error")
			errorBucket := fmt.Sprintf("%s.%s", "asset_error", nameClean)
			s.Incr(errorBucket)
			return
		}

		for header, values := range resp.Header {
			for _, value := range values {
				w.Header().Add(header, value)
			}
		}
		w.WriteHeader(resp.StatusCode)

		io.Copy(w, resp.Body)
		log.Printf("Proxied %s && incremented %s.%s.%s", path, title, env, bucket)
	}
}

// TemplateData is used to render index.html
type TemplateData struct {
	MetaTags          template.HTML
	Lang              Locale
	WWWHostport       string
	WebClientHostport string
	CDNHostport       string
}

func channelPage(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	lang := requestLocale(r)

	t, err := template.New("index.html").ParseFiles("index.html")
	if err != nil {
		log.Println(err)
		return
	}

	metatags, err := channelMetaTags(ctx, pat.Param(ctx, "login"))
	if err != nil {
		log.Println(err)
		// Render the page without metatags
	}

	err = t.Execute(w, TemplateData{
		MetaTags:          template.HTML(metatags),
		Lang:              lang,
		WWWHostport:       hostports.WWWHostport,
		CDNHostport:       hostports.CDNHostport,
		WebClientHostport: hostports.WebClientHostport,
	})
	if err != nil {
		log.Println(err)
		return
	}
}

func elbHealthCheck(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	log.Printf("health check")
}

func errorHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	log.Printf("404: " + r.URL.String())
	w.WriteHeader(http.StatusNotFound)
}

func redirect(name string, filename string, contents string, s statsd.Stats) func(context.Context, http.ResponseWriter, *http.Request) {
	nameClean := strings.Replace(strings.Replace(name, ".", "_", -1), "/", "_", -1)
	return func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
		// Cache for 12-18 seconds
		cacheLength := easyRand(12, 18)
		w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d", cacheLength))
		w.Header().Set("Expires", time.Now().UTC().Add(time.Duration(cacheLength)*time.Second).Format(http.TimeFormat))

		// Allow CORS to facilitate darklaunching
		w.Header().Set("Access-Control-Allow-Origin", "*")

		// Detect Content-Type
		w.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(name)))

		http.Redirect(w, r, contents, 302)

		bucket := fmt.Sprintf("%s.%s", "redirect", nameClean)
		s.Incr(bucket)
		log.Printf("Redirected %s && incremented %s.%s.%s", name, title, env, bucket)
	}
}

func serve(name string, filename string, contents string, s statsd.Stats) func(context.Context, http.ResponseWriter, *http.Request) {
	nameClean := strings.Replace(strings.Replace(name, ".", "_", -1), "/", "_", -1)
	return func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
		// Cache for 10 years
		w.Header().Set("Cache-Control", "max-age=315360000")
		w.Header().Set("Expires", time.Now().UTC().Add(87600*time.Hour).Format(http.TimeFormat))

		// Allow CORS to facilitate darklaunching
		w.Header().Set("Access-Control-Allow-Origin", "*")

		// Detect Content-Type
		w.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(name)))

		if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
			w.Header().Set("Content-Encoding", "gzip")
			gz := gzip.NewWriter(w)
			defer gz.Close()
			gzr := gzipResponseWriter{Writer: gz, ResponseWriter: w}
			fmt.Fprintf(gzr, "%s", contents)
		} else {
			fmt.Fprintf(w, "%s", contents)
		}

		bucket := fmt.Sprintf("%s.%s", "serve", nameClean)
		s.Incr(bucket)
		log.Printf("Served %s && incremented %s.%s.%s", filename, title, env, bucket)
	}
}
