/*
 * Copyright 2020-2023 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 events

import (
	"context"
	"strconv"
	"testing"
	"time"

	"github.com/opencord/voltha-lib-go/v7/pkg/kafka"
	"github.com/opencord/voltha-lib-go/v7/pkg/log"
	mock_kafka "github.com/opencord/voltha-lib-go/v7/pkg/mocks/kafka"
	"github.com/opencord/voltha-protos/v5/go/common"
	"github.com/opencord/voltha-protos/v5/go/voltha"
	"github.com/stretchr/testify/assert"
)

const waitForKafkaEventsTimeout = 20 * time.Second
const waitForEventProxyTimeout = 10 * time.Second

func waitForEventProxyToStop(ep *EventProxy, resp chan string) {
	timer := time.NewTimer(waitForEventProxyTimeout)
	defer timer.Stop()
	for {
		select {
		case <-time.After(2 * time.Millisecond):
			if ep.eventQueue.insertPosition == nil {
				resp <- "ok"
				return
			}
		case <-timer.C:
			resp <- "timer expired"
			return
		}

	}
}
func waitForKafkaEvents(kc kafka.Client, topic *kafka.Topic, numEvents int, resp chan string) {
	kafkaChnl, err := kc.Subscribe(context.Background(), topic)
	if err != nil {
		resp <- err.Error()
		return
	}
	defer func() {
		if kafkaChnl != nil {
			if err = kc.UnSubscribe(context.Background(), topic, kafkaChnl); err != nil {
				logger.Errorw(context.Background(), "unsubscribe-failed", log.Fields{"error": err})
			}
		}
	}()
	timer := time.NewTimer(waitForKafkaEventsTimeout)
	defer timer.Stop()
	count := 0
loop:
	for {
		select {
		case msg := <-kafkaChnl:
			if _, ok := msg.(*voltha.Event); ok {
				count += 1
				if count == numEvents {
					resp <- "ok"
					break loop
				}
			}
		case <-timer.C:
			resp <- "timer expired"
			break loop
		}
	}
}

func createAndSendEvent(proxy *EventProxy, id string) error {
	eventMsg := &voltha.RPCEvent{
		Rpc:         "dummy",
		OperationId: id,
		ResourceId:  "dummy",
		Service:     "dummy",
		StackId:     "dummy",
		Status: &common.OperationResp{
			Code: common.OperationResp_OPERATION_FAILURE,
		},
		Description: "dummy",
		Context:     nil,
	}
	var event voltha.Event
	raisedTS := time.Now().Unix()
	event.Header, _ = proxy.getEventHeader("RPC_ERROR_RAISE_EVENT", voltha.EventCategory_COMMUNICATION, nil, voltha.EventType_RPC_EVENT, raisedTS)
	event.EventType = &voltha.Event_RpcEvent{RpcEvent: eventMsg}
	err := proxy.SendRPCEvent(context.Background(), "RPC_ERROR_RAISE_EVENT", eventMsg, voltha.EventCategory_COMMUNICATION,
		nil, time.Now().Unix())
	return err
}

func TestEventProxyReceiveAndSendMessage(t *testing.T) {
	// Init Kafka client
	log.SetAllLogLevel(log.FatalLevel)
	cTkc := mock_kafka.NewKafkaClient()
	topic := kafka.Topic{Name: "myTopic"}

	numEvents := 10
	resp := make(chan string)
	go waitForKafkaEvents(cTkc, &topic, numEvents, resp)

	// Init Event Proxy
	ep := NewEventProxy(MsgClient(cTkc), MsgTopic(topic))
	go func() {
		if err := ep.Start(); err != nil {
			logger.Fatalw(context.Background(), "failure-starting-event-proxy", log.Fields{"error": err})
		}
	}()
	time.Sleep(1 * time.Millisecond)
	for i := 0; i < numEvents; i++ {
		go func(ID int) {
			err := createAndSendEvent(ep, strconv.Itoa(ID))
			assert.Nil(t, err)
		}(i)
	}
	val := <-resp
	assert.Equal(t, val, "ok")
	go ep.Stop()
	go waitForEventProxyToStop(ep, resp)
	val = <-resp
	assert.Equal(t, val, "ok")
}

func TestEventProxyStopWhileSendingEvents(t *testing.T) {
	// Init Kafka client
	log.SetAllLogLevel(log.FatalLevel)
	cTkc := mock_kafka.NewKafkaClient()
	topic := kafka.Topic{Name: "myTopic"}

	numEvents := 10
	resp := make(chan string)
	// Init Event Proxy
	ep := NewEventProxy(MsgClient(cTkc), MsgTopic(topic))
	go func() {
		if err := ep.Start(); err != nil {
			logger.Fatalw(context.Background(), "failure-starting-event-proxy", log.Fields{"error": err})
		}
	}()
	time.Sleep(1 * time.Millisecond)
	for i := 0; i < numEvents; i++ {
		go func(ID int) {
			err := createAndSendEvent(ep, strconv.Itoa(ID))
			assert.Nil(t, err)
		}(i)
	}
	// In this case we cannot guarantee how many events are send before
	// sending the last event(stopping event proxy), any event send before Stop would be received.
	go ep.Stop()
	go waitForEventProxyToStop(ep, resp)
	val := <-resp
	assert.Equal(t, val, "ok")
}

func TestEventProxyStopWhenNoEventsSend(t *testing.T) {
	// Init Kafka client
	log.SetAllLogLevel(log.FatalLevel)
	cTkc := mock_kafka.NewKafkaClient()
	topic := kafka.Topic{Name: "myTopic"}
	resp := make(chan string)
	// Init Event Proxy
	ep := NewEventProxy(MsgClient(cTkc), MsgTopic(topic))
	go func() {
		if err := ep.Start(); err != nil {
			logger.Fatalw(context.Background(), "failure-starting-event-proxy", log.Fields{"error": err})
		}
	}()
	time.Sleep(1 * time.Millisecond)
	go ep.Stop()
	go waitForEventProxyToStop(ep, resp)
	val := <-resp
	assert.Equal(t, val, "ok")
}
