/*
* Copyright 2022-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 controller

import (
	"context"
	"reflect"
	"testing"
	"voltha-go-controller/internal/pkg/holder"
	"voltha-go-controller/internal/pkg/of"
	"voltha-go-controller/internal/test/mocks"

	"github.com/golang/mock/gomock"
	ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
	"github.com/stretchr/testify/assert"
)

func TestNewDevicePort(t *testing.T) {
	type args struct {
		mp *ofp.OfpPort
	}
	tests := []struct {
		name string
		args args
		want *DevicePort
	}{
		{
			name: "NewDevicePort",
			args: args{
				mp: &ofp.OfpPort{
					PortNo: uint32(1),
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := NewDevicePort(tt.args.mp)
			assert.NotNil(t, got)
		})
	}
}

func TestDevice_UpdateFlows(t *testing.T) {
	type args struct {
		flow    *of.VoltFlow
		devPort *DevicePort
	}
	tests := []struct {
		name string
		args args
	}{
		{
			name: "Device_UpdateFlows",
			args: args{
				flow: &of.VoltFlow{
					PortName: "test_port_name",
				},
				devPort: &DevicePort{
					Name: "test_name",
				},
			},
		},
	}
	for _, tt := range tests {
		flushQueue := make(map[uint32]*UniIDFlowQueue)
		flushQueue[uint32(1)] = &UniIDFlowQueue{
			ID: uint32(1),
		}
		t.Run(tt.name, func(t *testing.T) {
			d := &Device{
				flowQueue: flushQueue,
				flowHash:  uint32(1),
			}
			d.UpdateFlows(tt.args.flow, tt.args.devPort)
		})
	}
}

func TestNewDevice(t *testing.T) {
	type args struct {
		cntx         context.Context
		id           string
		slno         string
		vclientHldr  *holder.VolthaServiceClientHolder
		southBoundID string
		mfr          string
		hwDesc       string
		swDesc       string
	}
	tests := []struct {
		name string
		args args
		want *Device
	}{
		{
			name: "TestNewDevice",
			args: args{
				cntx: context.Background(),
				id:   "test_id",
				slno: "test_sl_no",
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
			db = dbintf
			dbintf.EXPECT().GetFlowHash(gomock.Any(), gomock.Any()).Return("1", nil).Times(1)
			got := NewDevice(tt.args.cntx, tt.args.id, tt.args.slno, tt.args.vclientHldr, tt.args.southBoundID, tt.args.mfr, tt.args.hwDesc, tt.args.swDesc)
			assert.NotNil(t, got)
		})
	}
}

func TestDevice_triggerFlowResultNotification(t *testing.T) {
	type args struct {
		cntx      context.Context
		cookie    uint64
		flow      *of.VoltSubFlow
		oper      of.Command
		bwDetails of.BwAvailDetails
		err       error
	}
	tests := []struct {
		name string
		args args
	}{
		{
			name: "Device_triggerFlowResultNotification",
			args: args{
				cntx:   context.Background(),
				cookie: uint64(1),
				flow: &of.VoltSubFlow{
					Cookie: uint64(1),
				},
				oper: of.CommandAdd,
				bwDetails: of.BwAvailDetails{
					PrevBw: "test_prev_bw",
				},
				err: nil,
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			flows := make(map[uint64]*of.VoltSubFlow)
			flows[uint64(1)] = &of.VoltSubFlow{
				Cookie: uint64(1),
			}
			d := &Device{
				flows: flows,
			}
			appMock := mocks.NewMockApp(gomock.NewController(t))
			_ = NewController(context.Background(), appMock)
			dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
			db = dbintf
			dbintf.EXPECT().PutFlow(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
			appMock.EXPECT().ProcessFlowModResultIndication(gomock.Any(), gomock.Any()).Times(1)
			d.triggerFlowResultNotification(tt.args.cntx, tt.args.cookie, tt.args.flow, tt.args.oper, tt.args.bwDetails, tt.args.err, false)
		})
	}
}

func TestDevice_ResetCache(t *testing.T) {
	tests := []struct {
		name string
	}{
		{
			name: "Device_ResetCache",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			d := &Device{}
			d.ResetCache()
		})
	}
}

func TestDevice_GetAllFlows(t *testing.T) {
	tests := []struct {
		name string
		want []*of.VoltSubFlow
	}{
		{
			name: "Device_GetAllFlows",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			d := &Device{}
			if got := d.GetAllFlows(); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("Device.GetAllFlows() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestDevice_PacketOutReq(t *testing.T) {
	type args struct {
		outport     string
		inport      string
		data        []byte
		isCustomPkt bool
	}
	tests := []struct {
		name    string
		args    args
		wantErr bool
	}{
		{
			name: "Device_PacketOutReq",
			args: args{
				outport: "test_out_port",
				inport:  "test_in_port",
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			portByName := make(map[string]*DevicePort)
			portByName["test_in_port"] = &DevicePort{
				Name: "test_device",
			}
			portByName["test_out_port"] = &DevicePort{
				Name: "test_device",
			}
			packetOutChannel := make(chan *ofp.PacketOut, 2)

			d := &Device{
				packetOutChannel: packetOutChannel,
				PortsByName:      portByName,
			}
			if err := d.PacketOutReq(tt.args.outport, tt.args.inport, tt.args.data, tt.args.isCustomPkt); (err != nil) != tt.wantErr {
				t.Errorf("Device.PacketOutReq() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestDevice_SetFlowHash(t *testing.T) {
	type args struct {
		cntx context.Context
		hash uint32
	}
	tests := []struct {
		name string
		args args
	}{
		{
			name: "Device_SetFlowHash",
			args: args{
				cntx: context.Background(),
				hash: uint32(2),
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			d := &Device{}
			dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
			db = dbintf
			dbintf.EXPECT().PutFlowHash(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
			d.SetFlowHash(tt.args.cntx, tt.args.hash)
		})
	}
}
