package main

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	"github.com/huichen/wukong/types"
	"net/http"
	"time"
)

var (
	_httpServer *http.Server
)

type ParamIndex struct {
	Key         string `json:"key"`
	Content     string `json:"content"`
	ForceUpdate bool   `json:"forceUpdate"`
}

type ParamDelete struct {
	Key         string `json:"key"`
	ForceUpdate bool   `json:"forceUpdate"`
}

type ParamShutdown struct {
}

type ParamSearch struct {
	Keywords string `json:"keywords"`
}

type ReturnSearch types.SearchResponse

func startHttp(addr string) error {
	router := mux.NewRouter()
	v1 := router.PathPrefix("/v1").Subrouter()
	v1.HandleFunc("/index", index_v1).Methods("POST")
	v1.HandleFunc("/index", delete_index_v1).Methods("DELETE")
	v1.HandleFunc("/delete_index", delete_index_v1).Methods("POST")
	v1.HandleFunc("/search", search_v1).Methods("GET").Queries("keywords", "{keywords}")
	v1.HandleFunc("/shutdown", shutdown).Methods("POST")
	router.Use(mux.CORSMethodMiddleware(router))

	_httpServer = &http.Server{
		Handler:      router,
		Addr:         addr,
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}

	go func() {
		if err := _httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			fmt.Println("http server error: ", err)
		}
	}()

	return nil
}

func stopHttp() {
	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
	defer cancel()

	_httpServer.Shutdown(ctx)
}

func jsonBody(w *http.ResponseWriter, r *http.Request, v interface{}) error {
	//reader, err := r.GetBody()
	//if err != nil {
	//	//log
	//	return err
	//}
	//defer reader.Close()
	//
	//b, err := ioutil.ReadAll(reader)
	//if err != nil {
	//	//log
	//	return err
	//}
	return json.NewDecoder(r.Body).Decode(v)
}

// new index
func index_v1(w http.ResponseWriter, r *http.Request) {
	var param ParamIndex
	err := jsonBody(&w, r, &param)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	fmt.Println("indexing:", param)
	searcher.IndexDocumentS(param.Key, types.DocumentIndexData{
		Content: param.Content,
	}, param.ForceUpdate)

	w.WriteHeader(http.StatusOK)
	_, err = w.Write([]byte(`{"ec":0,"result":{}}`))
}

// delete index
func delete_index_v1(w http.ResponseWriter, r *http.Request) {
	var param ParamDelete
	err := jsonBody(&w, r, &param)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	fmt.Println("removing index:", param)

	searcher.RemoveDocumentS(param.Key, param.ForceUpdate)

	w.WriteHeader(http.StatusOK)
	_, err = w.Write([]byte(`{"ec":0,"result":{}}`))
}

// search
func search_v1(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	keywords := params["keywords"]
	fmt.Println("searching:", params, keywords)
	resp := searcher.Search(types.SearchRequest{Text: keywords})
	sresp, err := json.Marshal(resp)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, `{"ec":0,"result":%s}`, string(sresp))
}

func shutdown(w http.ResponseWriter, r *http.Request) {

}
