/*
 * Copyright 2022-2024 Open Networking Foundation (ONF) and the ONF Contributors
 *
 * 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 core provides the utility for onu devices, flows and statistics
package core

import (
	"context"
	"fmt"
	"time"

	"github.com/golang/protobuf/ptypes/empty"
	"github.com/opencord/voltha-lib-go/v7/pkg/log"
	"github.com/opencord/voltha-protos/v5/go/common"
	"github.com/opencord/voltha-protos/v5/go/health"
	ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
	"github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
)

// OpenONUACInterAdapter structure holds a reference to ONU adapter
type OpenONUACInterAdapter struct {
	onuAdapter  *OpenONUAC
	exitChannel chan struct{}
}

// NewOpenONUACAdapter returns a new instance of OpenONUACAdapter
func NewOpenONUACAdapter(ctx context.Context, onuAdapter *OpenONUAC) *OpenONUACInterAdapter {
	return &OpenONUACInterAdapter{onuAdapter: onuAdapter, exitChannel: make(chan struct{})}
}

// Start starts (logs) the adapter
func (oo *OpenONUACInterAdapter) Start(ctx context.Context) error {
	logger.Info(ctx, "starting-openonu-inter-adapter")
	return nil
}

// OnuIndication redirects the request the the core ONU adapter handler
func (oo *OpenONUACInterAdapter) OnuIndication(ctx context.Context, onuInd *ia.OnuIndicationMessage) (*empty.Empty, error) {
	return oo.onuAdapter.OnuIndication(ctx, onuInd)
}

// OmciIndication redirects the request the the core ONU adapter handler
func (oo *OpenONUACInterAdapter) OmciIndication(ctx context.Context, msg *ia.OmciMessage) (*empty.Empty, error) {
	return oo.onuAdapter.OmciIndication(ctx, msg)
}

// DownloadTechProfile redirects the request the the core ONU adapter handler
func (oo *OpenONUACInterAdapter) DownloadTechProfile(ctx context.Context, tProfile *ia.TechProfileDownloadMessage) (*empty.Empty, error) {
	return oo.onuAdapter.DownloadTechProfile(ctx, tProfile)
}

// DeleteGemPort redirects the request the the core ONU adapter handler
func (oo *OpenONUACInterAdapter) DeleteGemPort(ctx context.Context, gPort *ia.DeleteGemPortMessage) (*empty.Empty, error) {
	return oo.onuAdapter.DeleteGemPort(ctx, gPort)
}

// DeleteTCont redirects the request the the core ONU adapter handler
func (oo *OpenONUACInterAdapter) DeleteTCont(ctx context.Context, tConf *ia.DeleteTcontMessage) (*empty.Empty, error) {
	return oo.onuAdapter.DeleteTCont(ctx, tConf)
}

// Stop terminates the session
func (oo *OpenONUACInterAdapter) Stop(ctx context.Context) error {
	close(oo.exitChannel)
	logger.Info(ctx, "openonu-inter-adapter-stopped")
	return nil
}

// GetHealthStatus is used by a OnuInterAdapterService client to detect a connection
// lost with the gRPC server hosting the OnuInterAdapterService service
func (oo *OpenONUACInterAdapter) GetHealthStatus(stream onu_inter_adapter_service.OnuInterAdapterService_GetHealthStatusServer) error {
	ctx := context.Background()
	logger.Debugw(ctx, "receive-stream-connection", log.Fields{"stream": stream})

	if stream == nil {
		return fmt.Errorf("conn-is-nil %v", stream)
	}
	initialRequestTime := time.Now()
	var remoteClient *common.Connection
	var tempClient *common.Connection
	var err error
loop:
	for {
		tempClient, err = stream.Recv()
		if err != nil {
			logger.Warnw(ctx, "received-stream-error", log.Fields{"remote-client": remoteClient, "error": err})
			break loop
		}
		// Send a response back
		err = stream.Send(&health.HealthStatus{State: health.HealthStatus_HEALTHY})
		if err != nil {
			logger.Warnw(ctx, "sending-stream-error", log.Fields{"remote-client": remoteClient, "error": err})
			break loop
		}

		remoteClient = tempClient
		logger.Debugw(ctx, "received-keep-alive", log.Fields{"remote-client": remoteClient})
		oo.onuAdapter.updateReachabilityFromRemote(context.Background(), remoteClient)

		select {
		case <-stream.Context().Done():
			logger.Infow(ctx, "stream-keep-alive-context-done", log.Fields{"remote-client": remoteClient, "error": stream.Context().Err()})
			break loop
		case <-oo.exitChannel:
			logger.Warnw(ctx, "received-stop", log.Fields{"remote-client": remoteClient, "initial-conn-time": initialRequestTime})
			break loop
		default:
		}
	}
	logger.Errorw(ctx, "connection-down", log.Fields{"remote-client": remoteClient, "error": err, "initial-conn-time": initialRequestTime})
	return err
}
