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

type oltState int

type Olt struct {
	ID                 uint32
	NumPonIntf         uint32
	NumNniIntf         uint32
	Mac                string
	SerialNumber       string
	Manufacture        string
	Name               string
	InternalState      oltState
	OperState          string
	Intfs              []intf
	HeartbeatSignature uint32
}

type intf struct {
	Type      string
	IntfID    uint32
	OperState string
}

const (
	PRE_ENABLE oltState = iota
	OLT_UP
	PONIF_UP
	ONU_DISCOVERED
)

func CreateOlt(oltid uint32, npon uint32, nnni uint32) *Olt {
	olt := Olt{}
	olt.ID = oltid
	olt.NumPonIntf = npon
	olt.NumNniIntf = nnni
	olt.Name = "BBSIM OLT"
	olt.InternalState = PRE_ENABLE
	olt.OperState = "up"
	olt.Intfs = make([]intf, olt.NumPonIntf+olt.NumNniIntf)
	olt.HeartbeatSignature = oltid
	for i := uint32(0); i < olt.NumNniIntf; i++ {
		olt.Intfs[i].IntfID = i
		olt.Intfs[i].OperState = "up"
		olt.Intfs[i].Type = "nni"
	}
	for i := uint32(olt.NumNniIntf); i < olt.NumPonIntf+olt.NumNniIntf; i++ {
		olt.Intfs[i].IntfID = i
		olt.Intfs[i].OperState = "up"
		olt.Intfs[i].Type = "pon"
	}
	return &olt
}
