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

import (
	"context"
	"fmt"
	"github.com/gogo/protobuf/proto"
	com "github.com/opencord/voltha-go/adapters/common"
	"github.com/opencord/voltha-go/common/log"
	ic "github.com/opencord/voltha-protos/go/inter_container"
	of "github.com/opencord/voltha-protos/go/openflow_13"
	"github.com/opencord/voltha-protos/go/voltha"
	"strconv"
	"strings"
	"sync"
)

// A set of pm names to create the initial pm config.  This is used only for testing in this simulated adapter
var pmNames = []string{
	"tx_64_pkts",
	"tx_65_127_pkts",
	"tx_128_255_pkts",
	"tx_256_511_pkts",
	"tx_512_1023_pkts",
	"tx_1024_1518_pkts",
	"tx_1519_9k_pkts",
	"rx_64_pkts",
	"rx_65_127_pkts",
	"rx_128_255_pkts",
	"rx_256_511_pkts",
	"rx_512_1023_pkts",
	"rx_1024_1518_pkts",
	"rx_1519_9k_pkts",
}

//DeviceHandler follows the same patterns as ponsim_olt.  The only difference is that it does not
// interact with an OLT device.
type DeviceHandler struct {
	deviceId     string
	deviceType   string
	device       *voltha.Device
	coreProxy    *com.CoreProxy
	simulatedOLT *SimulatedOLT
	nniPort      *voltha.Port
	ponPort      *voltha.Port
	exitChannel  chan int
	lockDevice   sync.RWMutex
	metrics      *com.PmMetrics
}

//NewDeviceHandler creates a new device handler
func NewDeviceHandler(cp *com.CoreProxy, device *voltha.Device, adapter *SimulatedOLT) *DeviceHandler {
	var dh DeviceHandler
	dh.coreProxy = cp
	cloned := (proto.Clone(device)).(*voltha.Device)
	dh.deviceId = cloned.Id
	dh.deviceType = cloned.Type
	dh.device = cloned
	dh.simulatedOLT = adapter
	dh.exitChannel = make(chan int, 1)
	dh.lockDevice = sync.RWMutex{}
	// Set up PON metrics
	dh.metrics = com.NewPmMetrics(
		cloned.Id,
		com.Frequency(150),
		com.Grouped(false),
		com.FrequencyOverride(false),
		com.Metrics(pmNames),
	)
	return &dh
}

// start save the device to the data model
func (dh *DeviceHandler) start(ctx context.Context) {
	dh.lockDevice.Lock()
	defer dh.lockDevice.Unlock()
	log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
	// Add the initial device to the local model
	log.Debug("device-agent-started")
}

// stop stops the device dh.  Not much to do for now
func (dh *DeviceHandler) stop(ctx context.Context) {
	dh.lockDevice.Lock()
	defer dh.lockDevice.Unlock()
	log.Debug("stopping-device-agent")
	dh.exitChannel <- 1
	log.Debug("device-agent-stopped")
}

func macAddressToUint32Array(mac string) []uint32 {
	slist := strings.Split(mac, ":")
	result := make([]uint32, len(slist))
	var err error
	var tmp int64
	for index, val := range slist {
		if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
			return []uint32{1, 2, 3, 4, 5, 6}
		}
		result[index] = uint32(tmp)
	}
	return result
}

func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
	log.Debugw("AdoptDevice", log.Fields{"deviceId": device.Id})

	//	Update the device info
	cloned := proto.Clone(device).(*voltha.Device)
	cloned.Root = true
	cloned.Vendor = "simulators"
	cloned.Model = "go-simulators"
	cloned.SerialNumber = com.GetRandomSerialNumber()
	cloned.MacAddress = strings.ToUpper(com.GetRandomMacAddress())

	// Synchronous call to update device - this method is run in its own go routine
	if err := dh.coreProxy.DeviceUpdate(nil, cloned); err != nil {
		log.Errorw("error-updating-device", log.Fields{"deviceId": device.Id, "error": err})
	}

	// Now, set the initial PM configuration for that device
	if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
		log.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
	}

	//	Now create the NNI Port
	dh.nniPort = &voltha.Port{
		PortNo:     2,
		Label:      fmt.Sprintf("nni-%d", 2),
		Type:       voltha.Port_ETHERNET_NNI,
		OperStatus: voltha.OperStatus_ACTIVE,
	}

	// Synchronous call to update device - this method is run in its own go routine
	if err := dh.coreProxy.PortCreated(nil, cloned.Id, dh.nniPort); err != nil {
		log.Errorw("error-creating-nni-port", log.Fields{"deviceId": device.Id, "error": err})
	}

	//	Now create the PON Port
	dh.ponPort = &voltha.Port{
		PortNo:     1,
		Label:      fmt.Sprintf("pon-%d", 1),
		Type:       voltha.Port_PON_OLT,
		OperStatus: voltha.OperStatus_ACTIVE,
	}

	// Synchronous call to update device - this method is run in its own go routine
	if err := dh.coreProxy.PortCreated(nil, cloned.Id, dh.ponPort); err != nil {
		log.Errorw("error-creating-nni-port", log.Fields{"deviceId": device.Id, "error": err})
	}

	cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
	cloned.OperStatus = voltha.OperStatus_ACTIVE

	dh.device = cloned
	//dh.device.SerialNumber = cloned.SerialNumber

	//	Update the device state
	if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
		log.Errorw("error-creating-nni-port", log.Fields{"deviceId": device.Id, "error": err})
	}

	//	Register Child device
	initialUniPortNo := 100
	log.Debugw("registering-onus", log.Fields{"total": dh.simulatedOLT.numOnus})
	for i := 0; i < dh.simulatedOLT.numOnus; i++ {
		go dh.coreProxy.ChildDeviceDetected(
			nil,
			cloned.Id,
			1,
			"simulated_onu",
			initialUniPortNo+i,
			"simulated_onu",
			com.GetRandomSerialNumber(),
			int64(i))
	}
}

func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
	return &ic.SwitchCapability{
		Desc: &of.OfpDesc{
			HwDesc:    "simulated_pon",
			SwDesc:    "simulated_pon",
			SerialNum: dh.device.SerialNumber,
		},
		SwitchFeatures: &of.OfpSwitchFeatures{
			NBuffers: 256,
			NTables:  2,
			Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
				of.OfpCapabilities_OFPC_TABLE_STATS |
				of.OfpCapabilities_OFPC_PORT_STATS |
				of.OfpCapabilities_OFPC_GROUP_STATS),
		},
	}, nil
}

func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
	cap := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
	return &ic.PortCapability{
		Port: &voltha.LogicalPort{
			OfpPort: &of.OfpPort{
				HwAddr:     macAddressToUint32Array(dh.device.MacAddress),
				Config:     0,
				State:      uint32(of.OfpPortState_OFPPS_LIVE),
				Curr:       cap,
				Advertised: cap,
				Peer:       cap,
				CurrSpeed:  uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
				MaxSpeed:   uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
			},
			DeviceId:     dh.device.Id,
			DevicePortNo: uint32(portNo),
		},
	}, nil
}

func (dh *DeviceHandler) Process_inter_adapter_message(msg *ic.InterAdapterMessage) error {
	log.Debugw("Process_inter_adapter_message", log.Fields{"msgId": msg.Header.Id})
	return nil
}

func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
	cloned := proto.Clone(device).(*voltha.Device)
	// Update the all ports state on that device to disable
	if err := dh.coreProxy.PortsStateUpdate(nil, cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
		log.Errorw("updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
		return
	}

	//Update the device state
	cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
	cloned.OperStatus = voltha.OperStatus_UNKNOWN
	dh.device = cloned

	if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
		log.Errorw("device-state-update-failed", log.Fields{"deviceId": device.Id, "error": err})
		return
	}

	// Tell the Core that all child devices have been disabled (by default it's an action already taken by the Core
	if err := dh.coreProxy.ChildDevicesLost(nil, cloned.Id); err != nil {
		log.Errorw("lost-notif-of-child-devices-failed", log.Fields{"deviceId": device.Id, "error": err})
		return
	}

	log.Debugw("DisableDevice-end", log.Fields{"deviceId": device.Id})
}

func (dh *DeviceHandler) ReEnableDevice(device *voltha.Device) {

	cloned := proto.Clone(device).(*voltha.Device)
	// Update the all ports state on that device to enable
	if err := dh.coreProxy.PortsStateUpdate(nil, cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
		log.Errorw("updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
		return
	}

	//Update the device state
	cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
	cloned.OperStatus = voltha.OperStatus_ACTIVE
	dh.device = cloned

	if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
		log.Errorw("device-state-update-failed", log.Fields{"deviceId": device.Id, "error": err})
		return
	}

	// Tell the Core that all child devices have been enabled
	if err := dh.coreProxy.ChildDevicesDetected(nil, cloned.Id); err != nil {
		log.Errorw("detection-notif-of-child-devices-failed", log.Fields{"deviceId": device.Id, "error": err})
		return
	}

	log.Debugw("ReEnableDevice-end", log.Fields{"deviceId": device.Id})
}

func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) {
	cloned := proto.Clone(device).(*voltha.Device)
	// Update the all ports state on that device to disable
	if err := dh.coreProxy.DeleteAllPorts(nil, cloned.Id); err != nil {
		log.Errorw("delete-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
		return
	}

	log.Debugw("DeleteDevice-end", log.Fields{"deviceId": device.Id})
}

func (dh *DeviceHandler) UpdateFlowsBulk(device *voltha.Device, flows *voltha.Flows, groups *voltha.FlowGroups) {
	log.Debugw("UpdateFlowsBulk", log.Fields{"deviceId": device.Id, "flows": flows, "groups": groups})
	// For now we do nothing with it
	return
}

func (dh *DeviceHandler) UpdateFlowsIncremental(device *voltha.Device, flowChanges *of.FlowChanges, groupChanges *of.FlowGroupChanges) {
	log.Debugw("UpdateFlowsIncremental", log.Fields{"deviceId": device.Id, "flowChanges": flowChanges, "groupChanges": groupChanges})
	// For now we do nothing with it
	return
}

func (dh *DeviceHandler) UpdatePmConfigs(device *voltha.Device, pmConfigs *voltha.PmConfigs) {
	log.Debugw("UpdatePmConfigs", log.Fields{"deviceId": device.Id, "pmConfigs": pmConfigs})
	// For now we do nothing with it
	return
}

func (dh *DeviceHandler) ReconcileDevice(device *voltha.Device) {
	// Update the device info
	cloned := proto.Clone(device).(*voltha.Device)
	cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
	cloned.OperStatus = voltha.OperStatus_ACTIVE

	dh.device = cloned

	// Update the device state
	if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
		log.Errorw("error-creating-nni-port", log.Fields{"deviceId": device.Id, "error": err})
	}

	// Since we don't know how long we were down, let's reconcile the child devices
	go dh.coreProxy.ReconcileChildDevices(nil, cloned.Id)
}
