/*
 * Copyright 2018-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 omci

import (
	"testing"

	"github.com/google/gopacket"
	"github.com/opencord/omci-lib-go/v2"
	me "github.com/opencord/omci-lib-go/v2/generated"
	"gotest.tools/assert"
)

func omciToCreateResponse(t *testing.T, omciPkt *gopacket.Packet) *omci.CreateResponse {
	msgLayer := (*omciPkt).Layer(omci.LayerTypeCreateResponse)
	if msgLayer == nil {
		t.Fatal("omci Msg layer could not be detected for CreateResponse - handling of MibSyncChan stopped")
	}
	msgObj, msgOk := msgLayer.(*omci.CreateResponse)
	if !msgOk {
		t.Fatal("omci Msg layer could not be assigned for CreateResponse - handling of MibSyncChan stopped")
	}
	return msgObj
}

type createArgs struct {
	omciPkt []byte
	result  me.Results
}

type createWant struct {
	result me.Results
}

func TestCreateResponse(t *testing.T) {

	// generate a CreateRequest packet to create a GemPort
	omciReq := &omci.CreateRequest{
		MeBasePacket: omci.MeBasePacket{
			EntityClass:    me.GemPortNetworkCtpClassID,
			EntityInstance: 12,
		},
		Attributes: me.AttributeValueMap{
			me.GemPortNetworkCtp_PortId:                                       0,
			me.GemPortNetworkCtp_TContPointer:                                 0,
			me.GemPortNetworkCtp_Direction:                                    0,
			me.GemPortNetworkCtp_TrafficManagementPointerForUpstream:          0,
			me.GemPortNetworkCtp_TrafficDescriptorProfilePointerForUpstream:   0,
			me.GemPortNetworkCtp_PriorityQueuePointerForDownStream:            0,
			me.GemPortNetworkCtp_TrafficDescriptorProfilePointerForDownstream: 0,
			me.GemPortNetworkCtp_EncryptionKeyRing:                            0,
		},
	}
	omciPkt, err := Serialize(omci.CreateRequestType, omciReq, 66)
	if err != nil {
		t.Fatal(err.Error())
	}

	omciPkt, _ = HexEncode(omciPkt)

	tests := []struct {
		name string
		args createArgs
		want createWant
	}{
		{"createSuccess",
			createArgs{omciPkt, me.Success},
			createWant{me.Success},
		},
		{"createProcessingError",
			createArgs{omciPkt, me.ProcessingError},
			createWant{me.ProcessingError},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			pkt, msg, _ := ParseOpenOltOmciPacket(tt.args.omciPkt)
			requestPkt, _ := CreateCreateResponse(pkt, msg, tt.args.result)

			omciMsg, omciPkt := omciBytesToMsg(t, requestPkt)

			assert.Equal(t, omciMsg.MessageType, omci.CreateResponseType)

			getResponseLayer := omciToCreateResponse(t, omciPkt)

			assert.Equal(t, getResponseLayer.Result, tt.want.result)

		})
	}
}
