/*
 * 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 provides the utility for olt devices, flows and statistics
package core

import (
	"context"
	"reflect"
	"runtime"

	"github.com/opencord/voltha-lib-go/v3/pkg/log"
)

// DeviceState OLT Device state
type DeviceState int

const (
	deviceStateNull DeviceState = iota
	deviceStateInit
	deviceStateConnected
	deviceStateUp
	deviceStateDown
)

// Trigger for changing the state
type Trigger int

const (
	DeviceInit Trigger = iota
	GrpcConnected
	DeviceUpInd
	DeviceDownInd
	GrpcDisconnected
)

// TransitionHandler function type for handling transition
type TransitionHandler func(ctx context.Context) error

// Transition to store state machine
type Transition struct {
	previousState []DeviceState
	currentState  DeviceState
	before        []TransitionHandler
	after         []TransitionHandler
}

// TransitionMap to store all the states and current device state
type TransitionMap struct {
	transitions        map[Trigger]Transition
	currentDeviceState DeviceState
}

//    OpenoltDevice state machine:
//
//        null ----> init ------> connected -----> up -----> down
//                   ^ ^             |             ^         | |
//                   | |             |             |         | |
//                   | +-------------+             +---------+ |
//                   |                                         |
//                   +-----------------------------------------+

// NewTransitionMap create a new state machine with all the transitions
func NewTransitionMap(dh *DeviceHandler) *TransitionMap {
	var transitionMap TransitionMap
	transitionMap.currentDeviceState = deviceStateNull
	transitionMap.transitions = make(map[Trigger]Transition)
	transitionMap.transitions[DeviceInit] =
		Transition{
			previousState: []DeviceState{deviceStateNull, deviceStateUp, deviceStateDown},
			currentState:  deviceStateInit,
			before:        []TransitionHandler{dh.doStateInit},
			after:         []TransitionHandler{dh.postInit}}
	transitionMap.transitions[GrpcDisconnected] =
		Transition{
			previousState: []DeviceState{deviceStateConnected, deviceStateDown},
			currentState:  deviceStateInit,
			before:        []TransitionHandler{dh.doStateInit},
			after:         []TransitionHandler{dh.postInit}}
	transitionMap.transitions[GrpcConnected] =
		Transition{
			previousState: []DeviceState{deviceStateInit},
			currentState:  deviceStateConnected,
			before:        []TransitionHandler{dh.doStateConnected}}

	transitionMap.transitions[DeviceUpInd] =
		Transition{
			previousState: []DeviceState{deviceStateConnected, deviceStateDown},
			currentState:  deviceStateUp,
			before:        []TransitionHandler{dh.doStateUp}}
	transitionMap.transitions[DeviceDownInd] =
		Transition{
			previousState: []DeviceState{deviceStateUp},
			currentState:  deviceStateDown,
			before:        []TransitionHandler{dh.doStateDown}}

	return &transitionMap
}

// funcName gets the handler function name
func funcName(f interface{}) string {
	p := reflect.ValueOf(f).Pointer()
	rf := runtime.FuncForPC(p)
	return rf.Name()
}

// isValidTransition checks for the new state transition is valid from current state
func (tMap *TransitionMap) isValidTransition(trigger Trigger) bool {
	for _, state := range tMap.transitions[trigger].previousState {
		if tMap.currentDeviceState == state {
			return true
		}
	}
	return false
}

// Handle moves the state machine to next state based on the trigger and invokes the before and
// after handlers if the transition is a valid transition
func (tMap *TransitionMap) Handle(ctx context.Context, trigger Trigger) {

	if !tMap.isValidTransition(trigger) {
		logger.Errorw(ctx, "invalid-transition-triggered",
			log.Fields{
				"current-state": tMap.currentDeviceState,
				"trigger":       trigger})
		return
	}

	beforeHandlers := tMap.transitions[trigger].before
	if beforeHandlers == nil {
		logger.Debugw(ctx, "no-handlers-for-before", log.Fields{"trigger": trigger})
	}
	for _, handler := range beforeHandlers {
		logger.Debugw(ctx, "running-before-handler", log.Fields{"handler": funcName(handler)})
		if err := handler(ctx); err != nil {
			// TODO handle error
			logger.Error(ctx, err)
			return
		}
	}

	tMap.currentDeviceState = tMap.transitions[trigger].currentState
	logger.Debugw(ctx, "updated-device-state ", log.Fields{"current-device-state": tMap.currentDeviceState})

	afterHandlers := tMap.transitions[trigger].after
	if afterHandlers == nil {
		logger.Debugw(ctx, "no-handlers-for-after", log.Fields{"trigger": trigger})
	}
	for _, handler := range afterHandlers {
		logger.Debugw(ctx, "running-after-handler", log.Fields{"handler": funcName(handler)})
		if err := handler(ctx); err != nil {
			// TODO handle error
			logger.Error(ctx, err)
			return
		}
	}
}
