package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"time"
)

func saveURL(url string) (tmpFile string, contentType string, err error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return
	}
	return saveHTTPRequest(req)
}

//{"video_url":"http://153.37.232.145/vweixinp.tc.qq.com/1007_6475d21fb443453b8adeac7e59cc0e1c.f10.mp4?vkey=E79C6B0DA06E7A434D15E24774F91412386D1956768C400AC93ECA5320ACAAAF050E1E1BA5C22DFD81B5EE3FBA97E928E0FC2DC597CF611B3E6641BC1AEE2892736FFE29E993F200AA4A0811FEB4E234C48516131207DDE4&sha=0&save=1"}
type videoURL struct {
	VideoURL string `json:"video_url"`
}

//readVideoURL try to read a file into json structure
//containing video_url
//
func readVideoURL(path string) (u string) {
	body, err := ioutil.ReadFile(path)
	if err == nil {
		var v = videoURL{}
		err = json.Unmarshal([]byte(body), &v)
		if err == nil {
			_, err = url.ParseRequestURI(v.VideoURL)
			if err == nil {
				return v.VideoURL
			}
		}
	}
	return ""
}

func buildHTTPReqWithHeader(httpMethod, targetURL string, headers map[string]string) (req *http.Request, err error) {
	req, err = http.NewRequest(httpMethod, targetURL, nil)
	if err != nil {
		return
	}

	if headers != nil {
		for k, v := range headers {
			req.Header.Set(k, v)
		}
	}
	return
}

func saveHTTPRequest(req *http.Request) (tmpFile string, contentType string, err error) {
	var myClient = &http.Client{Timeout: 20 * time.Second}

	r, err := myClient.Do(req)
	if err != nil {
		log.Printf("Fail to get URL: %s", req.RequestURI)
		log.Println(err)
		return "", "", err
	}
	defer r.Body.Close()

	contentType = r.Header.Get("Content-Type")
	contentLen := r.Header.Get("Content-Length")
	len, _ := strconv.Atoi(contentLen)
	log.Println(r)
	file, err := ioutil.TempFile(os.TempDir(), "wechat_hitxy_")
	// Use io.Copy to just dump the response body to the file. This supports huge files
	_, err = io.Copy(file, r.Body)
	if err != nil {
		log.Println(err)
		return "", contentType, err
	}
	noSuffix := file.Name()
	file.Close()
	tmpFile = noSuffix + contentType2Suffix(contentType)
	os.Rename(noSuffix, tmpFile)

	//see if its a video url
	if len < 4096 && contentType == "text/plain" {
		u := readVideoURL(tmpFile)
		if u != "" {
			fmt.Println("saveing video url: " + u)
			os.Remove(tmpFile) //remove json file
			tmpFile, contentType, err = saveURL(u)
		}
	}

	return
}

func saveURLwithHTTPHeader(url string, headers map[string]string) (tmpFile string, contentType string, err error) {
	log.Println("saveURL: " + url)
	req, err := buildHTTPReqWithHeader("GET", url, headers)
	if err != nil {
		return
	}
	return saveHTTPRequest(req)
}

func contentType2Suffix(typ string) string {
	exts, err := mime.ExtensionsByType(typ)
	if err != nil {
		return ""
	}
	return exts[0]
}
