/*
 * 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

/* Source-Router

   This router implements source routing where the caller identifies the
   component the message should be routed to. The `RouteField` should be
   configured with the gRPC field name to inspect to determine the
   destination. This field is assumed to be a string. That string will
   then be used to identify a particular connection on a particular
   backend.

   The source-router must be configured with a backend cluster, as all routers
   must identify a backend cluster. However, that backend cluster
   is merely a placeholder and is not used by the source-router. The
   source-router's Route() function will return whatever backend cluster is
   specified by the `RouteField`.
*/

import (
	"errors"
	"fmt"
	"github.com/golang/protobuf/proto"
	"github.com/opencord/voltha-go/common/log"
	"google.golang.org/grpc"
	"regexp"
	"strconv"
)

type SourceRouter struct {
	name        string
	grpcService string
	methodMap   map[string]byte
	cluster     *cluster
}

func newSourceRouter(rconf *RouterConfig, config *RouteConfig) (Router, error) {
	var err error
	var rtrn_err = false
	var pkg_re = regexp.MustCompile(`^(\.[^.]+\.)(.+)$`)
	// Validate the configuration

	// 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
	}

	if config.RouteField == "" {
		log.Error("A 'routing_field' must be specified")
		rtrn_err = true
	}

	// TODO The overrieds section is currently not being used
	// so the router will route all methods based on the
	// routing_field. This needs to be added so that methods
	// can have different routing fields.
	dr := SourceRouter{
		name:        config.Name,
		grpcService: rconf.ProtoService,
		methodMap:   make(map[string]byte),
	}

	// Build the routing structure based on the loaded protobuf
	// descriptor file and the config information.
	type key struct {
		method string
		field  string
	}
	var fieldNumberLookup = make(map[key]byte)
	for _, f := range rconf.protoDescriptor.File {
		// Build a temporary map of message types by name.
		for _, m := range f.MessageType {
			for _, fld := range m.Field {
				log.Debugf("Processing message '%s', field '%s'", *m.Name, *fld.Name)
				fieldNumberLookup[key{*m.Name, *fld.Name}] = byte(*fld.Number)
			}
		}
	}
	for _, f := range rconf.protoDescriptor.File {
		if *f.Package == rconf.ProtoPackage {
			for _, s := range f.Service {
				if *s.Name == rconf.ProtoService {
					log.Debugf("Loading package data '%s' for service '%s' for router '%s'", *f.Package, *s.Name, dr.name)
					// Now create a map keyed by method name with the value being the
					// field number of the route selector.
					var ok bool
					for _, m := range s.Method {
						// Find the input type in the messages and extract the
						// field number and save it for future reference.
						log.Debugf("Processing method '%s'", *m.Name)
						// Determine if this is a method we're supposed to be processing.
						if needMethod(*m.Name, config) {
							log.Debugf("Enabling method '%s'", *m.Name)
							pkg_methd := pkg_re.FindStringSubmatch(*m.InputType)
							if pkg_methd == nil {
								log.Errorf("Regular expression didn't match input type '%s'", *m.InputType)
								rtrn_err = true
							}
							// The input type has the package name prepended to it. Remove it.
							//in := (*m.InputType)[len(rconf.ProtoPackage)+2:]
							in := pkg_methd[PKG_MTHD_MTHD]
							dr.methodMap[*m.Name], ok = fieldNumberLookup[key{in, config.RouteField}]
							if !ok {
								log.Errorf("Method '%s' has no field named '%s' in it's parameter message '%s'",
									*m.Name, config.RouteField, in)
								rtrn_err = true
							}
						}
					}
				}
			}
		}
	}

	// We need to pick a cluster, because server will call cluster.handler. The choice we make doesn't
	// matter, as we can return a different cluster from Route().
	var ok bool
	if dr.cluster, ok = clusters[config.backendCluster.Name]; !ok {
		if dr.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 dr, fmt.Errorf("Failed to create a new router '%s'", dr.name)
	}

	return dr, nil
}

func (ar SourceRouter) Service() string {
	return ar.grpcService
}

func (ar SourceRouter) Name() string {
	return ar.name
}

func (ar SourceRouter) skipField(data *[]byte, idx *int) error {
	switch (*data)[*idx] & 3 {
	case 0: // Varint
		// skip the field number/type
		*idx++
		// if the msb is set, then more bytes to follow
		for (*data)[*idx] >= 128 {
			*idx++
		}
		// the last byte doesn't have the msb set
		*idx++
	case 1: // 64 bit
		*idx += 9
	case 2: // Length delimited
		// skip the field number / type
		*idx++
		// read a varint that tells length of string
		b := proto.NewBuffer((*data)[*idx:])
		t, _ := b.DecodeVarint()
		// skip the length varint and the string bytes
		// TODO: This assumes the varint was one byte long -- max string length is 127 bytes
		*idx += int(t) + 1
	case 3: // Deprecated
	case 4: // Deprecated
	case 5: // 32 bit
		*idx += 5
	}
	return nil
}

func (ar SourceRouter) decodeProtoField(payload []byte, fieldId byte) (string, error) {
	idx := 0
	b := proto.NewBuffer([]byte{})
	//b.DebugPrint("The Buffer", payload)
	for { // Find the route selector field
		if idx >= len(payload) {
			err := fmt.Errorf("At end of message, attribute %d not found", fieldId)
			return "", err
		}

		log.Debugf("Decoding source value attributeNumber: %d from %v at index %d", fieldId, payload, idx)
		log.Debugf("Attempting match with payload: %d, methodTable: %d", payload[idx], fieldId)
		if payload[idx]>>3 == fieldId {
			log.Debugf("Method match with payload: %d, methodTable: %d", payload[idx], fieldId)
			// TODO: Consider supporting other selector types.... Way, way in the future
			// ok, the future is now, support strings as well... ugh.
			var selector string
			switch payload[idx] & 3 {
			case 0: // Integer
				b.SetBuf(payload[idx+1:])
				v, e := b.DecodeVarint()
				if e == nil {
					log.Debugf("Decoded the ing field: %v", v)
					selector = strconv.Itoa(int(v))
				} else {
					log.Errorf("Failed to decode varint %v", e)
					return "", e
				}
			case 2: // Length delimited AKA string
				b.SetBuf(payload[idx+1:])
				v, e := b.DecodeStringBytes()
				if e == nil {
					log.Debugf("Decoded the string field: %v", v)
					selector = v
				} else {
					log.Errorf("Failed to decode string %v", e)
					return "", e
				}
			default:
				err := errors.New("Only integer and string route selectors are permitted")
				log.Error(err)
				return "", err
			}
			return selector, nil
		} else if err := ar.skipField(&payload, &idx); err != nil {
			log.Errorf("Parsing message failed %v", err)
			return "", err
		}
	}
}

func (ar SourceRouter) Route(sel interface{}) (*backend, *connection) {
	log.Debugf("SourceRouter sel %v", sel)
	switch sl := sel.(type) {
	case *requestFrame:
		log.Debugf("Route called for nbFrame with method %s", sl.methodInfo.method)
		// Not a south affinity binding method, proceed with north affinity binding.
		if selector, err := ar.decodeProtoField(sl.payload, ar.methodMap[sl.methodInfo.method]); err == nil {
			// selector is

			for _, cluster := range clusters {
				for _, backend := range cluster.backends {
					log.Debugf("Checking backend %s", backend.name)
					for _, connection := range backend.connections {
						log.Debugf("Checking connection %s", connection.name)
						// caller specified a backend and a connection
						if backend.name+"."+connection.name == selector {
							return backend, connection
						}
					}
					// caller specified just a backend
					if backend.name == selector {
						return backend, nil
					}
				}
			}
			sl.err = fmt.Errorf("Backend %s not found", selector)
			return nil, nil
		}
	default:
		log.Errorf("Internal: invalid data type in Route call %v", sel)
		return nil, nil
	}
	log.Errorf("Bad routing in SourceRouter:Route")
	return nil, nil
}

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

func (ar SourceRouter) IsStreaming(_ string) (bool, bool) {
	panic("not implemented")
}

func (ar SourceRouter) BackendCluster(mthd string, metaKey string) (*cluster, error) {
	// unsupported?
	return ar.cluster, nil
}

func (ar SourceRouter) FindBackendCluster(beName string) *cluster {
	// unsupported?
	if beName == ar.cluster.name {
		return ar.cluster
	}
	return nil
}

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