/*
 * 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 (
	"flag"
	"os"
	"os/signal"
	"reflect"
	"strconv"
	"strings"
	"sync"

	"gerrit.opencord.org/voltha-bbsim/common/logger"
	"gerrit.opencord.org/voltha-bbsim/device"
	log "github.com/sirupsen/logrus"
)

const (
	DEFAULT Mode = iota
	AAA
	BOTH
)

// Store emulation mode
type Mode int

// AutoONUActivate is flag for Auto ONU Add on/off.
var AutoONUActivate int

type option struct {
	address                  string
	port                     uint32
	mgmtGrpcPort             uint32
	mgmtRestPort             uint32
	oltid                    uint32
	npon                     uint32
	nonus                    uint32
	aaawait                  int
	dhcpwait                 int
	dhcpservip               string
	intvl                    int
	interactiveOnuActivation bool
	Mode                     Mode
	KafkaBroker              string
	Debuglvl                 string
}

// GetOptions receives command line options and stores them in option structure
func GetOptions() *option {
	o := new(option)
	addressport := flag.String("H", ":50060", "IP address:port")
	oltid := flag.Int("id", 0, "OLT-ID")
	npon := flag.Int("i", 1, "Number of PON-IF ports")
	nonus := flag.Int("n", 1, "Number of ONUs per PON-IF port")
	modeopt := flag.String("m", "default", "Emulation mode (default, aaa, both (aaa & dhcp))")
	aaawait := flag.Int("aw", 2, "Wait time (sec) for activation WPA supplicants after EAPOL flow entry installed")
	dhcpwait := flag.Int("dw", 2, "Wait time (sec) for activation DHCP clients after DHCP flow entry installed")
	dhcpservip := flag.String("s", "182.21.0.128", "DHCP Server IP Address")
	intvl := flag.Int("v", 1000, "Interval each Indication (ms)")
	kafkaBroker := flag.String("k", "", "Kafka broker")
	interactiveOnuActivation := flag.Bool("ia", false, "Enable interactive activation of ONUs")
	mgmtGrpcPort := flag.Int("grpc", 50061, "BBSim API server gRPC port")
	mgmtRestPort := flag.Int("rest", 50062, "BBSim API server REST port")
	o.Mode = DEFAULT
	debg := flag.String("d", "DEBUG", "Debug Level(TRACE DEBUG INFO WARN ERROR)")
	flag.Parse()
	if *modeopt == "aaa" {
		o.Mode = AAA
	} else if *modeopt == "both" {
		o.Mode = BOTH
	}
	o.Debuglvl = *debg
	o.oltid = uint32(*oltid)
	o.npon = uint32(*npon)
	o.nonus = uint32(*nonus)
	o.aaawait = *aaawait
	o.dhcpwait = *dhcpwait
	o.dhcpservip = *dhcpservip
	o.intvl = *intvl
	o.interactiveOnuActivation = *interactiveOnuActivation
	o.KafkaBroker = *kafkaBroker
	o.address = strings.Split(*addressport, ":")[0]
	tmp, _ := strconv.Atoi(strings.Split(*addressport, ":")[1])
	o.port = uint32(tmp)
	o.mgmtGrpcPort = uint32(*mgmtGrpcPort)
	o.mgmtRestPort = uint32(*mgmtRestPort)

	if o.interactiveOnuActivation == true {
		log.Info("Automatic ONU activation disabled: use BBSim API to activate ONUs")
	}

	return o
}

type mediator struct {
	opt         *option
	server      *Server
	testmanager *TestManager
}

// NewMediator returns a new mediator object
func NewMediator(o *option) *mediator {
	m := new(mediator)
	m.opt = o
	logger.WithFields(log.Fields{
		"ip":        o.address,
		"baseport":  o.port,
		"pon_ports": o.npon,
		"onus":      o.nonus,
		"mode":      o.Mode,
	}).Debug("New mediator")
	return m
}

// Start mediator
func (m *mediator) Start() {
	var wg sync.WaitGroup
	opt := m.opt
	server := NewCore(opt)
	server.wg = &sync.WaitGroup{}
	server.wg.Add(1)
	go server.StartServerActionLoop(&wg)
	server.serverActionCh <- "start"
	go server.startMgmtServer(&wg)

	tm := NewTestManager(opt)
	m.server = server
	m.testmanager = tm
	go func() {
		m.Mediate()
	}()

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		defer func() {
			logger.Debug("SIGINT catcher Done")
			wg.Done()
		}()
		for sig := range c {
			wg.Add(1)
			logger.Debug("SIGINT %v", sig)
			close(c)
			server.Stop() // Non-blocking
			tm.Stop()     // Non-blocking
			server.stopMgmtServer()
			server.wg.Done()
			return
		}
	}()
	wg.Wait()
	server.wg.Wait()
}

// Mediate method is invoked on OLT and ONU state change
func (m *mediator) Mediate() {
	defer logger.Debug("Mediate Done")
	for sr := range m.server.stateRepCh {
		next := sr.next
		current := sr.current
		dev := sr.device
		if reflect.TypeOf(dev) == reflect.TypeOf(&device.Olt{}) {
			logger.Debug("Received OLT Device %v Current: %d Next: %d", dev, current, next)
			if err := transitOlt(current, next, m.testmanager, m.opt); err != nil {
				logger.Error("%v", err)
			}
		} else if reflect.TypeOf(dev) == reflect.TypeOf(&device.Onu{}) {
			logger.Debug("Received ONU Device %v Current: %d Next: %d", dev, current, next)
			key := dev.GetDevkey()
			if err := transitOnu(key, current, next, m.testmanager, m.opt); err != nil {
				logger.Error("%v", err)
			}
		}
	}
}

func transitOlt(current device.DeviceState, next device.DeviceState, tm *TestManager, o *option) error {
	logger.Debug("trnsitOlt called current:%d , next:%d", current, next)
	if current == device.OLT_PREACTIVE && next == device.OLT_ACTIVE {
		tm.Start()
		nniup, _ := makeNniName(o.oltid)
		activateDHCPServer(nniup, o.dhcpservip)
	} else if current == device.OLT_ACTIVE && next == device.OLT_PREACTIVE {
		tm.Stop()
	} else if current == device.OLT_ACTIVE && next == device.OLT_INACTIVE {
		// Reboot case
		// TODO Point of discussion
	}
	return nil
}

func transitOnu(key device.Devkey, current device.DeviceState, next device.DeviceState, tm *TestManager, o *option) error {
	logger.Debug("trnsitOnu called with key: %v, current: %d, next: %d", key, current, next)
	if o.Mode == AAA || o.Mode == BOTH {
		if current == device.ONU_ACTIVE && next == device.ONU_OMCIACTIVE {
			t := tm.CreateTester("AAA", o, key, activateWPASupplicant, o.aaawait)
			if err := tm.StartTester(t); err != nil {
				logger.Error("Cannot Start AAA Executer error:%v", err)
			}
		} else if current == device.ONU_OMCIACTIVE && next == device.ONU_INACTIVE {
			if err := tm.StopTester("AAA", key); err != nil {
				logger.Error("Cannot Stop AAA Executer error:%v", err)
			}
		}
	}

	if o.Mode == BOTH {
		if current == device.ONU_OMCIACTIVE {
			t := tm.CreateTester("DHCP", o, key, activateDHCPClient, o.dhcpwait)
			if err := tm.StartTester(t); err != nil {
				logger.Error("Cannot Start DHCP Executer error:%v", err)
			}
		} else if current == device.ONU_AUTHENTICATED && next == device.ONU_INACTIVE {
			if err := tm.StopTester("DHCP", key); err != nil {
				logger.Error("Cannot Stop DHCP Executer error:%v", err)
			}
		}
	}
	return nil
}
