package api

import (
	"net/http"
	"strconv"
	"time"

	"github.com/gorilla/mux"
	"github.com/ngaut/log"
	"github.com/pingcap/wormhole/ether"
	"github.com/pingcap/wormhole/pkg/whpb"
	"github.com/unrolled/render"
)

type workerHandler struct {
	*ether.Handler
	r *render.Render
}

// Worker is an object for front
type Worker struct {
	ID    uint64 `json:"id"`
	Type  string `json:"type"`
	State string `json:"state"`
	Host  string `json:"host"`
}

func newWorkerHandler(handler *ether.Handler, r *render.Render) *workerHandler {
	return &workerHandler{
		Handler: handler,
		r:       r,
	}
}

func (h *workerHandler) Get(w http.ResponseWriter, r *http.Request) {
	id := mux.Vars(r)["worker_id"]
	workerID, err := strconv.ParseUint(id, 10, 64)
	if err != nil {
		log.Errorf("[ether] parser worker_id %s error %v", id, err)
		h.r.JSON(w, http.StatusOK, errResponsef("[ether] parse worker_id %s error %v", id, err))
		return
	}

	worker, err := h.GetWorker(workerID)
	if err != nil {
		h.r.JSON(w, http.StatusOK, errResponsef("[ether] get worker %d error %v", workerID, err))
		return
	}
	if worker == nil {
		h.r.JSON(w, http.StatusOK, notFoundResponsef("[ether] worker %d", workerID))
		return
	}

	state := "online"
	if time.Now().Unix()-worker.LastTime > ether.MaxOfflineThreshold {
		state = "offline"
	}
	annotations := worker.GetAnnotations()
	data := &Worker{ID: workerID, Type: worker.GetType().String(), State: state, Host: annotations["host"]}
	h.r.JSON(w, http.StatusOK, successResponse(data))
}

func (h *workerHandler) List(w http.ResponseWriter, r *http.Request) {
	h.list(w, r, whpb.WorkerType_Portal, true)
}

func (h *workerHandler) ListPortals(w http.ResponseWriter, r *http.Request) {
	h.list(w, r, whpb.WorkerType_Portal, false)
}

func (h *workerHandler) ListStargates(w http.ResponseWriter, r *http.Request) {
	h.list(w, r, whpb.WorkerType_Stargate, false)
}

func (h *workerHandler) list(w http.ResponseWriter, r *http.Request, tp whpb.WorkerType, all bool) {
	workers, err := h.GetWorkers()
	if err != nil {
		h.r.JSON(w, http.StatusOK, errResponsef("[ether] get workers error %v", err))
		return
	}

	t := time.Now().Unix()
	ws := make([]*Worker, 0, len(workers))
	for _, worker := range workers {
		if !all && worker.GetType() != tp {
			continue
		}
		state := "online"
		if t-worker.LastTime > ether.MaxOfflineThreshold {
			state = "offline"
		}
		w := &Worker{
			ID:    worker.GetId(),
			Type:  worker.GetType().String(),
			State: state,
			Host:  worker.GetAnnotations()["host"],
		}
		ws = append(ws, w)
	}

	h.r.JSON(w, http.StatusOK, successResponse(ws))
}
