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

import (
	"fmt"
	log "github.com/sirupsen/logrus"
)

type OmciError struct {
	Msg string
}

func (e *OmciError) Error() string {
	return fmt.Sprintf("%s", e.Msg)
}

type OnuKey struct {
	IntfId, OnuId uint32
}

func (k OnuKey) String() string {
	return fmt.Sprintf("Onu {intfid:%d, onuid:%d}", k.IntfId, k.OnuId)
}

func GetAttributes(class OmciClass, content OmciContent, key OnuKey, pkt []byte) []byte {
	log.WithFields(log.Fields{
		"IntfId": key.IntfId,
		"OnuId": key.OnuId,
	}).Tracef("GetAttributes() invoked")

	switch class {
	case ANIG:
		pos := uint(11)
		pkt, _ = GetANIGAttributes(&pos, pkt, content)
		return pkt

	case EthernetPMHistoryData:
		pos := uint(11)
		pkt, _ = GetEthernetPMHistoryDataAttributes(&pos, pkt, content)
		return pkt
	default:
		// For unimplemented MEs, just fill in the attribute mask and return 0 values for the requested attributes
		// TODO implement Get for unimplemented MEs as well
		log.WithFields(log.Fields{
			"IntfId": key.IntfId,
			"OnuId": key.OnuId,
			"class": class,
		}).Warnf("Unimplemeted GetAttributes for ME Class: %v " +
		    "Filling with zero value for the requested attributes", class)
		AttributesMask := getAttributeMask(content)
		pkt[8] = 0x00 // Command Processed Successfully
		pkt[9] = uint8(AttributesMask >> 8)
		pkt[10] = uint8(AttributesMask & 0xFF)

		return pkt
	}
}

func getAttributeMask(content OmciContent) int {
	// mask is present in pkt[8] and pkt[9]
	log.WithFields(log.Fields{
		"content[0]": content[0],
		"content[1]": content[1],
	}).Tracef("GetAttributeMask() invoked")
	return (int(content[0]) << 8) | int(content[1])
}
