/*
 * Copyright 2018-present Open Networking Foundation

 * Licensed 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 afrouter

import (
	"fmt"
	"github.com/opencord/voltha-lib-go/v2/pkg/log"
	"google.golang.org/grpc"
)

type RoundRobinRouter struct {
	name           string
	grpcService    string
	cluster        *cluster
	currentBackend **backend
}

func newRoundRobinRouter(rconf *RouterConfig, config *RouteConfig) (Router, error) {
	var err error
	var rtrn_err = false
	// Validate the configuration

	log.Debug("Creating a new round robin router")
	// A name must exist
	if config.Name == "" {
		log.Error("A router 'name' must be specified")
		rtrn_err = true
	}

	if rconf.ProtoPackage == "" {
		log.Error("A 'package' must be specified")
		rtrn_err = true
	}

	if rconf.ProtoService == "" {
		log.Error("A 'service' must be specified")
		rtrn_err = true
	}

	var bptr *backend
	rr := RoundRobinRouter{
		name:           config.Name,
		grpcService:    rconf.ProtoService,
		currentBackend: &bptr,
	}

	// Create the backend cluster or link to an existing one
	var ok bool
	if rr.cluster, ok = clusters[config.backendCluster.Name]; !ok {
		if rr.cluster, err = newBackendCluster(config.backendCluster); err != nil {
			log.Errorf("Could not create a backend for router %s", config.Name)
			rtrn_err = true
		}
	}

	if rtrn_err {
		return rr, fmt.Errorf("Failed to create a new router '%s'", rr.name)
	}

	return rr, nil
}

func (rr RoundRobinRouter) GetMetaKeyVal(serverStream grpc.ServerStream) (string, string, error) {
	return "", "", nil
}

func (rr RoundRobinRouter) IsStreaming(_ string) (bool, bool) {
	panic("not implemented")
}

func (rr RoundRobinRouter) BackendCluster(s string, mk string) (*cluster, error) {
	return rr.cluster, nil
}

func (rr RoundRobinRouter) Name() string {
	return rr.name
}

func (rr RoundRobinRouter) Route(sel interface{}) (*backend, *connection) {
	var err error
	switch sl := sel.(type) {
	case *requestFrame:
		// Since this is a round robin router just get the next backend
		if *rr.currentBackend, err = rr.cluster.nextBackend(*rr.currentBackend, BackendSequenceRoundRobin); err == nil {
			return *rr.currentBackend, nil
		} else {
			sl.err = err
			return nil, nil
		}
	default:
		log.Errorf("Internal: invalid data type in Route call %v", sel)
		return nil, nil
	}
}

func (rr RoundRobinRouter) Service() string {
	return rr.grpcService
}

func (rr RoundRobinRouter) FindBackendCluster(becName string) *cluster {
	if becName == rr.cluster.name {
		return rr.cluster
	}
	return nil
}

func (rr RoundRobinRouter) ReplyHandler(sel interface{}) error { // This is a no-op
	return nil
}
