/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package server_impl

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"
	"time"
)

import (
	"github.com/emicklei/go-restful/v3"
	perrors "github.com/pkg/errors"
)

import (
	"github.com/apache/dubbo-go/common"
	"github.com/apache/dubbo-go/common/constant"
	"github.com/apache/dubbo-go/common/extension"
	"github.com/apache/dubbo-go/common/logger"
	"github.com/apache/dubbo-go/protocol/rest/config"
	"github.com/apache/dubbo-go/protocol/rest/server"
)

func init() {
	extension.SetRestServer(constant.DEFAULT_REST_SERVER, NewGoRestfulServer)
}

var filterSlice []restful.FilterFunction

// GoRestfulServer a rest server implement by go-restful
type GoRestfulServer struct {
	srv *http.Server
	ws  *restful.WebService
}

// NewGoRestfulServer a constructor of GoRestfulServer
func NewGoRestfulServer() server.RestServer {
	return &GoRestfulServer{}
}

// Start go-restful server
// It will add all go-restful filters
func (grs *GoRestfulServer) Start(url common.URL) {
	container := restful.NewContainer()
	for _, filter := range filterSlice {
		container.Filter(filter)
	}
	grs.srv = &http.Server{
		Handler: container,
	}
	grs.ws = &restful.WebService{}
	grs.ws.Path("/")
	grs.ws.SetDynamicRoutes(true)
	container.Add(grs.ws)
	ln, err := net.Listen("tcp", url.Location)
	if err != nil {
		panic(perrors.New(fmt.Sprintf("Restful Server start error:%v", err)))
	}

	go func() {
		err := grs.srv.Serve(ln)
		if err != nil && err != http.ErrServerClosed {
			logger.Errorf("[Go Restful] http.server.Serve(addr{%s}) = err{%+v}", url.Location, err)
		}
	}()
}

// Publish a http api in go-restful server
// The routeFunc should be invoked when the server receive a request
func (grs *GoRestfulServer) Deploy(restMethodConfig *config.RestMethodConfig, routeFunc func(request server.RestServerRequest, response server.RestServerResponse)) {

	rf := func(req *restful.Request, resp *restful.Response) {
		routeFunc(NewGoRestfulRequestAdapter(req), resp)
	}
	grs.ws.Route(grs.ws.Method(restMethodConfig.MethodType).
		Produces(strings.Split(restMethodConfig.Produces, ",")...).
		Consumes(strings.Split(restMethodConfig.Consumes, ",")...).
		Path(restMethodConfig.Path).To(rf))
}

// Delete a http api in go-restful server
func (grs *GoRestfulServer) UnDeploy(restMethodConfig *config.RestMethodConfig) {
	ws := new(restful.WebService)
	ws.Path(restMethodConfig.Path)
	err := grs.ws.RemoveRoute(restMethodConfig.Path, restMethodConfig.MethodType)
	if err != nil {
		logger.Warnf("[Go restful] Remove web service error:%v", err)
	}
}

// Destroy the go-restful server
func (grs *GoRestfulServer) Destroy() {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := grs.srv.Shutdown(ctx); err != nil {
		logger.Errorf("[Go Restful] Server Shutdown:", err)
	}
	logger.Infof("[Go Restful] Server exiting")
}

// AddGoRestfulServerFilter let user add the http server of go-restful
// addFilter should before config.Load()
func AddGoRestfulServerFilter(filterFuc restful.FilterFunction) {
	filterSlice = append(filterSlice, filterFuc)
}

// GoRestfulRequestAdapter a adapter struct about RestServerRequest
type GoRestfulRequestAdapter struct {
	server.RestServerRequest
	request *restful.Request
}

// NewGoRestfulRequestAdapter a constructor of GoRestfulRequestAdapter
func NewGoRestfulRequestAdapter(request *restful.Request) *GoRestfulRequestAdapter {
	return &GoRestfulRequestAdapter{request: request}
}

// RawRequest a adapter function of server.RestServerRequest's RawRequest
func (grra *GoRestfulRequestAdapter) RawRequest() *http.Request {
	return grra.request.Request
}

// PathParameter a adapter function of server.RestServerRequest's PathParameter
func (grra *GoRestfulRequestAdapter) PathParameter(name string) string {
	return grra.request.PathParameter(name)
}

// PathParameters a adapter function of server.RestServerRequest's QueryParameter
func (grra *GoRestfulRequestAdapter) PathParameters() map[string]string {
	return grra.request.PathParameters()
}

// QueryParameter a adapter function of server.RestServerRequest's QueryParameters
func (grra *GoRestfulRequestAdapter) QueryParameter(name string) string {
	return grra.request.QueryParameter(name)
}

// QueryParameters a adapter function of server.RestServerRequest's QueryParameters
func (grra *GoRestfulRequestAdapter) QueryParameters(name string) []string {
	return grra.request.QueryParameters(name)
}

// BodyParameter a adapter function of server.RestServerRequest's BodyParameter
func (grra *GoRestfulRequestAdapter) BodyParameter(name string) (string, error) {
	return grra.request.BodyParameter(name)
}

// HeaderParameter a adapter function of server.RestServerRequest's HeaderParameter
func (grra *GoRestfulRequestAdapter) HeaderParameter(name string) string {
	return grra.request.HeaderParameter(name)
}

// ReadEntity a adapter func of server.RestServerRequest's ReadEntity
func (grra *GoRestfulRequestAdapter) ReadEntity(entityPointer interface{}) error {
	return grra.request.ReadEntity(entityPointer)
}
