/*
 * 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 (
	"reflect"
	"runtime"

	"github.com/opencord/voltha-go/common/log"
)

// DeviceState OLT Device state
type DeviceState int

const (
	// deviceStateNull OLT is not instantiated
	deviceStateNull DeviceState = iota
	// deviceStateInit OLT is instantiated
	deviceStateInit
	// deviceStateConnected Grpc session established with OLT
	deviceStateConnected
	// deviceStateUp Admin state of OLT is UP
	deviceStateUp
	// deviceStateDown Admin state of OLT is down
	deviceStateDown
)

// Trigger for changing the state
type Trigger int

const (
	// DeviceInit Go to Device init state
	DeviceInit Trigger = iota
	// GrpcConnected Go to connected state
	GrpcConnected
	// DeviceUpInd Go to Device up state
	DeviceUpInd
	// DeviceDownInd Go to Device down state
	DeviceDownInd
	// GrpcDisconnected Go to Device init state
	GrpcDisconnected
)

// TransitionHandler function type for handling transition
type TransitionHandler func() 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)
	// In doInit establish the grpc session
	transitionMap.transitions[DeviceInit] =
		Transition{
			previousState: []DeviceState{deviceStateNull},
			currentState:  deviceStateInit,
			before:        []TransitionHandler{dh.doStateInit},
			after:         []TransitionHandler{dh.postInit}}
	// If gRpc session fails, re-establish the grpc session
	transitionMap.transitions[GrpcDisconnected] =
		Transition{
			previousState: []DeviceState{deviceStateConnected, deviceStateDown},
			currentState:  deviceStateInit,
			before:        []TransitionHandler{dh.doStateInit},
			after:         []TransitionHandler{dh.postInit}}
	// in doConnected, create logical device and read the indications
	transitionMap.transitions[GrpcConnected] =
		Transition{
			previousState: []DeviceState{deviceStateInit},
			currentState:  deviceStateConnected,
			before:        []TransitionHandler{dh.doStateConnected}}

	// Once the olt UP is indication received, then do state up
	transitionMap.transitions[DeviceUpInd] =
		Transition{
			previousState: []DeviceState{deviceStateConnected, deviceStateDown},
			currentState:  deviceStateUp,
			before:        []TransitionHandler{dh.doStateUp}}
	// If olt DOWN indication comes then do sate down
	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 {
	// Validate the state transition
	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
func (tMap *TransitionMap) Handle(trigger Trigger) {

	// Check whether the transtion is valid from current state
	if !tMap.isValidTransition(trigger) {
		log.Errorw("Invalid transition triggered ", log.Fields{"CurrentState": tMap.currentDeviceState, "Trigger": trigger})
		return
	}

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

	// Update the state
	tMap.currentDeviceState = tMap.transitions[trigger].currentState
	log.Debugw("Updated device state ", log.Fields{"CurrentDeviceState": tMap.currentDeviceState})

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