/*
 * 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"
	"net/http"
	"sync"

	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	"github.com/opencord/bbsim/api/legacy"
	"github.com/opencord/bbsim/internal/bbsim/devices"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

type BBSimLegacyServer struct {
}

// Response Constants
const (
	RequestAccepted = "API request accepted"
	OLTNotEnabled   = "OLT not enabled"
	RequestFailed   = "API request failed"
	SoftReboot      = "soft-reboot"
	HardReboot      = "hard-reboot"
	DeviceTypeOlt   = "olt"
	DeviceTypeOnu   = "onu"
)

// OLTStatus method returns the OLT status.
func (s BBSimLegacyServer) OLTStatus(ctx context.Context, in *legacy.Empty) (*legacy.OLTStatusResponse, error) {
	logger.Trace("OLTStatus request received")

	olt := devices.GetOLT()
	oltInfo := &legacy.OLTStatusResponse{
		Olt: &legacy.OLTInfo{
			OltId:     int64(olt.ID),
			OltVendor: "BBSIM",
			OltSerial: olt.SerialNumber,
			//OltIp:     getOltIP().String(),
			OltState: olt.OperState.Current(),
		},
	}

	for _, nni := range olt.Nnis {
		nniPortInfo := &legacy.PortInfo{
			PortType:  "nni",
			PortId:    uint32(nni.ID),
			PortState: nni.OperState.Current(),
		}
		oltInfo.Ports = append(oltInfo.Ports, nniPortInfo)
	}

	for _, pon := range olt.Pons {
		ponPortInfo := &legacy.PortInfo{
			PortType:          "pon",
			PortId:            uint32(pon.ID),
			PonPortMaxOnus:    uint32(olt.NumOnuPerPon),
			PonPortActiveOnus: uint32(olt.NumPon),
			PortState:         pon.OperState.Current(),
		}
		oltInfo.Ports = append(oltInfo.Ports, ponPortInfo)
	}

	return oltInfo, nil
}

// PortStatus method returns Port status.
func (s BBSimLegacyServer) PortStatus(ctx context.Context, in *legacy.PortInfo) (*legacy.Ports, error) {
	logger.Trace("PortStatus() invoked")
	ports := &legacy.Ports{}
	switch portType := in.GetPortType(); portType {
	case "pon":
		portInfo, err := s.fetchPortDetail(in.PortId, portType)
		if err != nil {
			return ports, err
		}
		ports.Ports = append(ports.Ports, portInfo)
	case "nni":
		portInfo, _ := s.fetchPortDetail(in.PortId, portType)
		ports.Ports = append(ports.Ports, portInfo)
	default:
		return &legacy.Ports{}, status.Errorf(codes.InvalidArgument, "Invalid port type")
	}

	return ports, nil
}

// ONUStatus method returns ONU status.
func (s BBSimLegacyServer) ONUStatus(ctx context.Context, in *legacy.ONURequest) (*legacy.ONUs, error) {
	logger.Trace("ONUStatus request received")
	onuInfo := &legacy.ONUs{}

	if in.GetOnu() != nil {
		logger.Debugf("Received single ONU: %+v, %d\n", in.GetOnu().OnuId, in.GetOnu().PonPortId)
		return s.handleONUStatusRequest(in.GetOnu())
	}

	logger.Debug("Received all ONUs status request")

	// Get status of all ONUs
	olt := devices.GetOLT()
	for _, p := range olt.Pons {
		for _, o := range p.Onus {
			onuInfo.Onus = append(onuInfo.Onus, copyONUInfo(o))
		}
	}

	return onuInfo, nil
}

// ONUActivate method handles ONU activate requests from user.
func (s BBSimLegacyServer) ONUActivate(ctx context.Context, in *legacy.ONURequest) (*legacy.BBSimResponse, error) {
	logger.Trace("ONUActivate request received")
	logger.Error("Not implemented")

	return &legacy.BBSimResponse{StatusMsg: RequestAccepted}, nil
}

// ONUDeactivate method handles ONU deactivation request.
func (s BBSimLegacyServer) ONUDeactivate(ctx context.Context, in *legacy.ONURequest) (*legacy.BBSimResponse, error) {
	logger.Info("ONUDeactivate request received")
	logger.Error("Not implemented")

	return &legacy.BBSimResponse{StatusMsg: RequestAccepted}, nil
}

// GenerateONUAlarm RPC generates alarm for the onu
func (s BBSimLegacyServer) GenerateONUAlarm(ctx context.Context, in *legacy.ONUAlarmRequest) (*legacy.BBSimResponse, error) {
	logger.Trace("GenerateONUAlarms() invoked")
	logger.Error("Not implemented")

	return nil, nil
}

// GenerateOLTAlarm RPC generates alarm for the OLT
func (s BBSimLegacyServer) GenerateOLTAlarm(ctx context.Context, in *legacy.OLTAlarmRequest) (*legacy.BBSimResponse, error) {
	logger.Trace("GenerateOLTAlarm() invoked")
	logger.Error("Not implemented")

	return &legacy.BBSimResponse{StatusMsg: RequestAccepted}, nil
}

// PerformDeviceAction rpc take the device request and performs OLT and ONU hard and soft reboot
func (s BBSimLegacyServer) PerformDeviceAction(ctx context.Context, in *legacy.DeviceAction) (*legacy.BBSimResponse, error) {
	logger.Trace("PerformDeviceAction() invoked")
	logger.Error("Not implemented")

	return &legacy.BBSimResponse{StatusMsg: RequestAccepted}, nil
}

// GetFlows returns all flows or flows for specified ONU
func (s BBSimLegacyServer) GetFlows(ctx context.Context, in *legacy.ONUInfo) (*legacy.Flows, error) {
	logger.Info("GetFlow request received")
	logger.Error("Not implemented")

	return &legacy.Flows{}, nil
}

// StartRestGatewayService method starts REST server for BBSim.
func StartRestGatewayService(channel chan bool, group *sync.WaitGroup, grpcAddress string, hostandport string) {
	ctx := context.Background()
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	mux := runtime.NewServeMux()
	opts := []grpc.DialOption{grpc.WithInsecure()}

	// Register REST endpoints
	err := legacy.RegisterBBSimServiceHandlerFromEndpoint(ctx, mux, grpcAddress, opts)
	if err != nil {
		logger.Errorf("%v", err)
		return
	}

	s := &http.Server{Addr: hostandport, Handler: mux}

	go func() {
		logger.Infof("legacy REST API server listening on %s", hostandport)
		if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			logger.Errorf("Could not start legacy API server: %v", err)
			return
		}
	}()

	x := <-channel
	if x {
		logger.Warnf("Stopping legacy API REST server")
		if err := s.Shutdown(ctx); err != nil {
			logger.Errorf("Could not stop server: %v", err)
		}
		group.Done()
	}
}
