/*
 * 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 (

	"github.com/opencord/voltha-bbsim/common/logger"
	"github.com/opencord/voltha-bbsim/device"
	openolt "github.com/opencord/voltha-bbsim/protos"
)

func sendOltIndUp(stream openolt.Openolt_EnableIndicationServer, olt *device.Olt) error {
	data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: "up"}}
	if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
		logger.Error("Failed to send OLT UP indication: %v", err)
		return err
	}
	return nil
}

func sendOltIndDown(stream openolt.Openolt_EnableIndicationServer) error {
	data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: "down"}}
	if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
		logger.Error("Failed to send OLT DOWN indication: %v", err)
		return err
	}
	return nil
}

func sendIntfInd(stream openolt.Openolt_EnableIndicationServer, olt *device.Olt) error {
	// There is no need to send IntfInd for NNI
	for i := uint32(0); i < olt.NumPonIntf; i++ {
		intf := olt.PonIntfs[i]
		data := &openolt.Indication_IntfInd{&openolt.IntfIndication{IntfId: intf.IntfID, OperState: intf.OperState}}
		if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
			logger.Error("Failed to send Intf [id: %d] indication : %v", i, err)
			return err
		}
		logger.Info("SendIntfInd olt:%d intf:%d (%s)", olt.ID, intf.IntfID, intf.Type)
	}
	return nil
}

func sendOperInd(stream openolt.Openolt_EnableIndicationServer, olt *device.Olt) error {
	// Send OperInd for Nni
	for i := uint32(0); i < olt.NumNniIntf; i++ {
		intf := olt.NniIntfs[i]
		data := &openolt.Indication_IntfOperInd{&openolt.IntfOperIndication{Type: intf.Type, IntfId: intf.IntfID, OperState: intf.OperState}}
		if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
			logger.Error("Failed to send NNI IntfOper [id: %d] indication : %v", i, err)
			return err
		}
		logger.Info("SendOperInd NNI olt:%d intf:%d (%s)", olt.ID, intf.IntfID, intf.Type)
	}

	// Send OperInd for Pon
	for i := uint32(0); i < olt.NumPonIntf; i++ {
		intf := olt.PonIntfs[i]
		data := &openolt.Indication_IntfOperInd{&openolt.IntfOperIndication{Type: intf.Type, IntfId: intf.IntfID, OperState: intf.OperState}}
		if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
			logger.Error("Failed to send PON IntfOper [id: %d] indication : %v", i, err)
			return err
		}
		logger.Info("SendOperInd PON olt:%d intf:%d (%s)", olt.ID, intf.IntfID, intf.Type)
	}
	return nil
}

func sendOnuDiscInd(stream openolt.Openolt_EnableIndicationServer, onu *device.Onu) error {
	data := &openolt.Indication_OnuDiscInd{OnuDiscInd: &openolt.OnuDiscIndication{IntfId: onu.IntfID, SerialNumber: onu.SerialNumber}}
	if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
		logger.Error("Failed to send ONUDiscInd [id: %d]: %v", onu.OnuID, err)
		return err
	}
	device.LoggerWithOnu(onu).Info("sendONUDiscInd Onuid")
	return nil
}

func sendOnuInd(stream openolt.Openolt_EnableIndicationServer, onu *device.Onu, operState string, adminState string) error {
	data := &openolt.Indication_OnuInd{OnuInd: &openolt.OnuIndication{
		IntfId:       onu.IntfID,
		OnuId:        onu.OnuID,
		OperState:    operState,
		AdminState:   adminState,
		SerialNumber: onu.SerialNumber,
	}}
	if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
		logger.Error("Failed to send ONUInd [id: %d]: %v", onu.OnuID, err)
		return err
	}
	device.LoggerWithOnu(onu).Info("sendONUInd Onuid")
	return nil
}

func sendDyingGaspInd(stream openolt.Openolt_EnableIndicationServer, intfID uint32, onuID uint32) error {
	// Form DyingGasp Indication with ONU-ID and Intf-ID
	alarmData := &openolt.AlarmIndication_DyingGaspInd{DyingGaspInd: &openolt.DyingGaspIndication{IntfId: intfID, OnuId: onuID, Status: "on"}}
	data := &openolt.Indication_AlarmInd{AlarmInd: &openolt.AlarmIndication{Data: alarmData}}

	// Send Indication to VOLTHA
	if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
		logger.Error("Failed to send DyingGaspInd : %v", err)
		return err
	}
	logger.Info("sendDyingGaspInd Intf-ID:%d ONU-ID:%d", intfID, onuID)
	return nil
}

func startAlarmLoop(stream openolt.Openolt_EnableIndicationServer, alarmchan chan *openolt.Indication) {
	logger.Debug("SendAlarm() Invoked")
	for {
		select {
		case ind := <-alarmchan:
			logger.Debug("Alarm recieved at alarm-channel to send to voltha %+v", ind)
			err := stream.Send(ind)
			if err != nil {
				logger.Debug("Error occured while sending alarm indication %v", err)
			}
		}
	}
}
