/*
 * Copyright 2019-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 (
	"context"
	"github.com/opencord/voltha-lib-go/v2/pkg/log"
	"google.golang.org/grpc"
	"google.golang.org/grpc/connectivity"
	"time"
)

// connection represents a connection to a single backend
type connection struct {
	backend *backend
	name    string
	addr    string
	port    string
	ctx     context.Context
	close   context.CancelFunc
}

func (cn *connection) connect() {
	for {
		log.Infof("Connecting to %s with addr: %s and port %s", cn.name, cn.addr, cn.port)
		// Dial doesn't block, it just returns and continues connecting in the background.
		// Check back later to confirm and increase the connection count.

		var err error
		conn, err := grpc.Dial(cn.addr+":"+cn.port, grpc.WithDefaultCallOptions(grpc.ForceCodec(Codec())), grpc.WithInsecure(), grpc.WithBackoffMaxDelay(time.Second*15))
		if err != nil {
			log.Fatalf("Dialing connection %v:%v", cn, err)
		}

		log.Debugf("Starting the connection monitor for '%s'", cn.name)
		cn.monitor(conn)
		conn.Close()

		select {
		case <-cn.ctx.Done():
			return
		default:
		}
	}
}

func (cn *connection) monitor(conn *grpc.ClientConn) {
	be := cn.backend
	log.Debugf("Setting up monitoring for backend %s", be.name)
	state := connectivity.Idle
monitorLoop:
	for {
		if !conn.WaitForStateChange(cn.ctx, state) {
			log.Debugf("Context canceled for connection '%s' on backend '%s'", cn.name, be.name)
			break monitorLoop // connection closed
		}

		if newState := conn.GetState(); newState != state {
			previousState := state
			state = newState

			if previousState == connectivity.Ready {
				be.decConn(cn)
				log.Infof("Lost connection '%s' on backend '%s'", cn.name, be.name)
			}

			switch state {
			case connectivity.Ready:
				log.Infof("Connection '%s' on backend '%s' becomes ready", cn.name, be.name)
				be.incConn(cn, conn)
			case connectivity.TransientFailure, connectivity.Connecting:
				// we don't log these, to avoid spam
			case connectivity.Shutdown:
				// the connection was closed
				log.Infof("Shutdown for connection '%s' on backend '%s'", cn.name, be.name)
				break monitorLoop
			case connectivity.Idle:
				// This can only happen if the server sends a GoAway. This can
				// only happen if the server has modified MaxConnectionIdle from
				// its default of infinity. The only solution here is to close the
				// connection and keepTrying()?
				//TODO: Read the grpc source code to see if there's a different approach
				log.Errorf("Server sent 'GoAway' on connection '%s' on backend '%s'", cn.name, be.name)
				break monitorLoop
			}
		}
	}
}
