package app

import (
	"exhibitionCentre/cache"
	"exhibitionCentre/config"
	"exhibitionCentre/logging"
	_ "exhibitionCentre/models"
	"exhibitionCentre/utils"
	"io"
	"io/ioutil"
	"net/http"
)

func init() {
}

func Run() {
	// read net config
	port := config.Config.App.HttpPort
	netType := config.Config.App.NetType
	if len(netType) == 0 || len(port) == 0 {
		logging.Log.Fatal("Read net config info failed.")
		return
	}
	address := "0.0.0.0:" + port
	chRunning := make(chan bool, 1)

	switch netType {
	case "http":
		go runHttp(address, chRunning)
	case "https":
		go runHttps(address, chRunning)
	}
	<-chRunning

	// 关闭缓存redis
	cache.Close()
}

func AddRouter(routerPath string, method func(data []byte) (int, []byte)) {
	http.HandleFunc(routerPath, func(w http.ResponseWriter, r *http.Request) {
		// w.Header().Add("Access-Control-Allow-Origin", "*")
		// w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
		// w.Header().Add("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Authorization, X-Requested-With")

		// read request body data
		body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
		if err != nil {
			logging.Log.Error("Read request body failed:", routerPath, err)
			utils.SendResponse(w, 500, []byte("Read request data failed."))
			return
		}

		// execute api method
		statusCode, responseData := method(body)
		utils.SendResponse(w, statusCode, responseData)
	})
}

func runHttps(address string, ch chan bool) {
	server_crt, server_private_key := certificate()
	if len(server_crt) == 0 || len(server_private_key) == 0 {
		logging.Log.Fatal("Read certificate config info failed.")
		return
	}
	if err := http.ListenAndServeTLS(address, server_crt, server_private_key, nil); err != nil {
		logging.Log.Error("ListenAndServeTLS: %s", err.Error())
		ch <- true
	}
}

func runHttp(address string, ch chan bool) {
	if err := http.ListenAndServe(address, nil); err != nil {
		logging.Log.Error("ListenAndServe: %s", err.Error())
		ch <- true
	}
}

func certificate() (string, string) {
	server_crt := config.Config.Certificate.ServerCrt
	server_private_key := config.Config.Certificate.ServerPrivateKey
	return server_crt, server_private_key
}
