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

import (
	"context"
	"fmt"
	"strings"
	"time"

	"google.golang.org/grpc/status"

	"github.com/opencord/bbsim/api/bbsim"
	"github.com/opencord/bbsim/internal/bbsim/devices"
	"github.com/opencord/bbsim/internal/common"
	log "github.com/sirupsen/logrus"
	"google.golang.org/grpc/codes"
)

var logger = log.WithFields(log.Fields{
	"module": "GrpcApiServer",
})

var (
	version    string
	buildTime  string
	commitHash string
	gitStatus  string
)

type BBSimServer struct {
}

func (s BBSimServer) Version(ctx context.Context, req *bbsim.Empty) (*bbsim.VersionNumber, error) {
	// TODO add a flag to specify whether the tree was clean at this commit or not
	return &bbsim.VersionNumber{
		Version:    version,
		BuildTime:  buildTime,
		CommitHash: commitHash,
		GitStatus:  gitStatus,
	}, nil
}

func (s BBSimServer) GetOlt(ctx context.Context, req *bbsim.Empty) (*bbsim.Olt, error) {
	olt := devices.GetOLT()
	nnis := []*bbsim.NNIPort{}
	pons := []*bbsim.PONPort{}

	for _, nni := range olt.Nnis {
		n := bbsim.NNIPort{
			ID:        int32(nni.ID),
			OperState: nni.OperState.Current(),
		}
		nnis = append(nnis, &n)
	}

	for _, pon := range olt.Pons {

		allocatedOnuIds := []*bbsim.PonAllocatedResources{}
		allocatedAllocIds := []*bbsim.PonAllocatedResources{}
		allocatedGemPorts := []*bbsim.PonAllocatedResources{}

		for k, v := range pon.AllocatedOnuIds {
			resource := &bbsim.PonAllocatedResources{
				SerialNumber: common.OnuSnToString(v),
				Id:           int32(k),
			}
			allocatedOnuIds = append(allocatedOnuIds, resource)
		}

		for k, v := range pon.AllocatedGemPorts {
			resource := &bbsim.PonAllocatedResources{
				SerialNumber: common.OnuSnToString(v),
				Id:           int32(k),
			}
			allocatedGemPorts = append(allocatedGemPorts, resource)
		}

		for _, v := range pon.AllocatedAllocIds {
			resource := &bbsim.PonAllocatedResources{
				SerialNumber: common.OnuSnToString(v.OnuSn),
				Id:           int32(v.AllocID),
			}
			allocatedAllocIds = append(allocatedAllocIds, resource)
		}

		p := bbsim.PONPort{
			ID:                int32(pon.ID),
			Technology:        pon.Technology.String(),
			OperState:         pon.OperState.Current(),
			InternalState:     pon.InternalState.Current(),
			PacketCount:       pon.PacketCount,
			AllocatedOnuIds:   allocatedOnuIds,
			AllocatedAllocIds: allocatedAllocIds,
			AllocatedGemPorts: allocatedGemPorts,
		}
		pons = append(pons, &p)
	}

	oltAddress := strings.Split(common.Config.BBSim.OpenOltAddress, ":")[0]
	if oltAddress == "" {
		oltAddress = getOltIP().String()
	}

	res := bbsim.Olt{
		ID:            int32(olt.ID),
		SerialNumber:  olt.SerialNumber,
		OperState:     olt.OperState.Current(),
		InternalState: olt.InternalState.Current(),
		IP:            oltAddress,
		NNIPorts:      nnis,
		PONPorts:      pons,
	}
	return &res, nil
}

// takes a nested map and return a proto
func resourcesMapToresourcesProto(resourceType bbsim.OltAllocatedResourceType_Type, resources map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool) *bbsim.OltAllocatedResources {
	proto := &bbsim.OltAllocatedResources{
		Resources: []*bbsim.OltAllocatedResource{},
	}
	for ponId, ponValues := range resources {
		for onuId, onuValues := range ponValues {
			for uniId, uniValues := range onuValues {
				for allocId, flows := range uniValues {
					for flow := range flows {
						resource := &bbsim.OltAllocatedResource{
							Type:       resourceType.String(),
							PonPortId:  ponId,
							OnuId:      onuId,
							PortNo:     uniId,
							ResourceId: allocId,
							FlowId:     flow,
						}
						proto.Resources = append(proto.Resources, resource)
					}
				}
			}
		}
	}
	return proto
}

func (s BBSimServer) GetOltAllocatedResources(ctx context.Context, req *bbsim.OltAllocatedResourceType) (*bbsim.OltAllocatedResources, error) {
	o := devices.GetOLT()

	switch req.Type {
	case bbsim.OltAllocatedResourceType_UNKNOWN:
		return nil, status.Errorf(codes.InvalidArgument, "resource-type-%s-is-invalid", req.Type)
	case bbsim.OltAllocatedResourceType_ALLOC_ID:
		return resourcesMapToresourcesProto(bbsim.OltAllocatedResourceType_ALLOC_ID, o.AllocIDs), nil
	case bbsim.OltAllocatedResourceType_GEM_PORT:
		return resourcesMapToresourcesProto(bbsim.OltAllocatedResourceType_GEM_PORT, o.GemPortIDs), nil
	default:
		return nil, status.Errorf(codes.InvalidArgument, "unkown-resource-type-%s", req.Type)
	}
}

func (s BBSimServer) PoweronOlt(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) {
	res := &bbsim.Response{}
	o := devices.GetOLT()

	if err := o.InternalState.Event(devices.OltInternalTxInitialize); err != nil {
		log.Errorf("Error initializing OLT: %v", err)
		res.StatusCode = int32(codes.FailedPrecondition)
		return res, err
	}

	res.StatusCode = int32(codes.OK)
	return res, nil
}

func (s BBSimServer) ShutdownOlt(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) {
	res := &bbsim.Response{}
	o := devices.GetOLT()

	if err := o.InternalState.Event(devices.OltInternalTxDisable); err != nil {
		log.Errorf("Error disabling OLT: %v", err)
		res.StatusCode = int32(codes.FailedPrecondition)
		return res, err
	}

	res.StatusCode = int32(codes.OK)
	return res, nil
}

func (s BBSimServer) RebootOlt(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) {
	res := &bbsim.Response{}
	o := devices.GetOLT()
	go func() { _ = o.RestartOLT() }()
	res.StatusCode = int32(codes.OK)
	res.Message = fmt.Sprintf("OLT restart triggered.")
	return res, nil
}

func (s BBSimServer) StopgRPCServer(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) {
	res := &bbsim.Response{}
	res.StatusCode = int32(codes.OK)
	res.Message = fmt.Sprintf("Openolt gRPC server stopped")
	o := devices.GetOLT()

	logger.Infof("Received request to stop Openolt gRPC Server")

	o.StopOltServer()

	return res, nil
}

func (s BBSimServer) StartgRPCServer(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) {
	res := &bbsim.Response{}
	res.StatusCode = int32(codes.OK)
	res.Message = fmt.Sprintf("Openolt gRPC server started")
	o := devices.GetOLT()

	logger.Infof("Received request to start Openolt gRPC Server")

	if o.OltServer != nil {
		return nil, fmt.Errorf("Openolt gRPC server already running.")
	}

	oltGrpcServer, err := o.StartOltServer()
	if err != nil {
		return nil, err
	}
	o.OltServer = oltGrpcServer

	return res, nil
}

func (s BBSimServer) RestartgRPCServer(ctx context.Context, req *bbsim.Timeout) (*bbsim.Response, error) {
	o := devices.GetOLT()
	logger.Infof("Received request to restart Openolt gRPC Server in %v seconds", req.Delay)
	o.StopOltServer()

	res := &bbsim.Response{}
	res.StatusCode = int32(codes.OK)
	res.Message = fmt.Sprintf("Openolt gRPC server stopped, restarting in %v", req.Delay)

	go func() {
		time.Sleep(time.Duration(req.Delay) * time.Second)
		oltGrpcServer, err := o.StartOltServer()
		if err != nil {
			logger.WithFields(log.Fields{
				"err": err,
			}).Error("Cannot restart Openolt gRPC server")
		}
		o.OltServer = oltGrpcServer
		logger.Infof("Openolt gRPC Server restarted after %v seconds", req.Delay)
	}()

	return res, nil
}

func (s BBSimServer) SetLogLevel(ctx context.Context, req *bbsim.LogLevel) (*bbsim.LogLevel, error) {

	common.SetLogLevel(log.StandardLogger(), req.Level, req.Caller)

	return &bbsim.LogLevel{
		Level:  log.StandardLogger().Level.String(),
		Caller: log.StandardLogger().ReportCaller,
	}, nil
}

func (s BBSimServer) SetOnuAlarmIndication(ctx context.Context, req *bbsim.ONUAlarmRequest) (*bbsim.Response, error) {
	o := devices.GetOLT()

	res := &bbsim.Response{}

	onu, err := o.FindOnuBySn(req.SerialNumber)
	if err != nil {
		res.StatusCode = int32(codes.NotFound)
		res.Message = err.Error()
		return nil, err
	}

	if err := onu.SetAlarm(req.AlarmType, req.Status); err != nil {
		res.StatusCode = int32(codes.Internal)
		res.Message = err.Error()
		return nil, err
	}

	res.StatusCode = int32(codes.OK)
	res.Message = fmt.Sprintf("Onu Alarm Indication Sent.")
	return res, nil
}

// SetOltAlarmIndication generates OLT Alarms for LOS
func (s BBSimServer) SetOltAlarmIndication(ctx context.Context, req *bbsim.OLTAlarmRequest) (*bbsim.Response, error) {
	o := devices.GetOLT()
	res := &bbsim.Response{}

	if err := o.SetAlarm(req.InterfaceID, req.InterfaceType, req.Status); err != nil {
		res.StatusCode = int32(codes.Internal)
		res.Message = err.Error()
		return nil, err
	}

	res.StatusCode = int32(codes.OK)
	res.Message = fmt.Sprintf("Olt Alarm Indication Sent.")
	return res, nil
}
