package loader

import (
	"crypto/tls"
	"dbweb/core"
	"encoding/json"
	"io"
	"net/http"
	"os"
	"path"
	"time"

	"net/url"

	log "github.com/Sirupsen/logrus"
)

type updateInfo struct {
	ViewsTime       time.Time
	StaticTime      time.Time
	InstitutionTime time.Time
}

func setupUpdateHandle() {
	http.HandleFunc("/update.json", func(w http.ResponseWriter, r *http.Request) {
		info := &updateInfo{}

		f, err := os.Stat(core.DataFile("institution.zip"))
		if err != nil {
			log.Panic(err)
		}
		info.InstitutionTime = f.ModTime()

		f, err = os.Stat(core.DataFile("static.zip"))
		if err != nil {
			log.Panic(err)
		}
		info.StaticTime = f.ModTime()

		f, err = os.Stat(core.DataFile("views.zip"))
		if err != nil {
			log.Panic(err)
		}
		info.ViewsTime = f.ModTime()

		js, err := json.Marshal(info)
		if err != nil {
			log.Panic(err)
		}
		w.Header().Set("Content-Type", "application/json")
		w.Write(js)
	})
	http.HandleFunc("/institution.zip", func(res http.ResponseWriter, r *http.Request) {
		http.ServeFile(res, r, core.DataFile("institution.zip"))
	})
	http.HandleFunc("/static.zip", func(res http.ResponseWriter, r *http.Request) {
		http.ServeFile(res, r, core.DataFile("static.zip"))
	})
	http.HandleFunc("/views.zip", func(res http.ResponseWriter, r *http.Request) {
		http.ServeFile(res, r, core.DataFile("views.zip"))
	})

}

//checkUdpateFile 检查本地文件最后修改时间，如果早于给定的，或者不存在，则下载更新
func checkUdpateFile(updateURL, fileName string, lastTime time.Time) error {
	bUpdate := false
	f, err := os.Stat(core.DataFile(fileName))
	if os.IsNotExist(err) {
		bUpdate = true
	} else if err != nil {
		return err
	} else if f.ModTime().Before(lastTime) {
		bUpdate = true
	}
	if !bUpdate {
		return nil
	}
	u, err := url.Parse(updateURL)
	if err != nil {
		return err
	}
	u.Path = path.Join(u.Path, fileName)
	client := http.Client{
		Timeout: 120 * time.Second,
		Transport: &http.Transport{
			TLSClientConfig:     &tls.Config{InsecureSkipVerify: true},
			TLSHandshakeTimeout: 3 * time.Second,
		},
	}

	resp, err := client.Get(u.String())
	if err != nil {
		return err
	}
	core.LOG.WithFields(log.Fields{
		"filename":  fileName,
		"updateURL": updateURL,
		"lasttime":  lastTime,
		"localtime": func() string {
			if f != nil {
				return f.ModTime().Format(time.RFC3339)
			}
			return ""

		}(),
	}).Info("download update file")
	defer resp.Body.Close()
	out, err := os.Create(core.DataFile(fileName))
	if err != nil {
		return err
	}

	if _, err = io.Copy(out, resp.Body); err != nil {
		return err
	}
	if err = out.Close(); err != nil {
		return err
	}

	return os.Chtimes(core.DataFile(fileName), lastTime, lastTime)
}
func checkUpdate(updateURL string) error {
	if len(updateURL) == 0 {
		return nil
	}
	core.LOG.Info("check remote update...")
	u, err := url.Parse(updateURL)
	if err != nil {
		return err
	}
	client := http.Client{
		Timeout: 2 * time.Second,
		Transport: &http.Transport{
			TLSClientConfig:     &tls.Config{InsecureSkipVerify: true},
			TLSHandshakeTimeout: 1 * time.Second,
		},
	}
	u.Path = path.Join(u.Path, "update.json")
	resp, err := client.Get(u.String())
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	dec := json.NewDecoder(resp.Body)
	info := &updateInfo{}
	if err = dec.Decode(info); err != nil {
		return err
	}

	if err = checkUdpateFile(updateURL, "static.zip", info.StaticTime); err != nil {
		return err
	}
	if err = checkUdpateFile(updateURL, "views.zip", info.ViewsTime); err != nil {
		return err
	}
	if err = checkUdpateFile(updateURL, "institution.zip", info.InstitutionTime); err != nil {
		return err
	}
	core.LOG.Info("update finished")

	return nil
}
