/*
* Copyright 2022-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 controller

import (
	"context"
	"time"

	infraerror "voltha-go-controller/internal/pkg/errorcodes"
	infraerrorcode "voltha-go-controller/internal/pkg/errorcodes/service"

	"voltha-go-controller/internal/pkg/of"
	"voltha-go-controller/log"
	"google.golang.org/grpc/codes"
)

//ModGroupTask - Group Modification Task
type ModGroupTask struct {
	taskID    uint8
	ctx       context.Context
	group     *of.Group
	device    *Device
	timestamp string
}

//NewModGroupTask - Initializes new group task
func NewModGroupTask(ctx context.Context, group *of.Group, device *Device) *ModGroupTask {
	var grp ModGroupTask
	grp.device = device
	grp.group = group
	grp.ctx = ctx
	tstamp := (time.Now()).Format(time.RFC3339Nano)
	grp.timestamp = tstamp
	return &grp
}

//Name - Name of task
func (grp *ModGroupTask) Name() string {
	return "Group Mod Task"
}

//TaskID - Task id
func (grp *ModGroupTask) TaskID() uint8 {
	return grp.taskID
}

// Timestamp to return timestamp of the task
func (grp *ModGroupTask) Timestamp() string {
	return grp.timestamp
}

//Stop - task stop
func (grp *ModGroupTask) Stop() {
}

//Start - task start
func (grp *ModGroupTask) Start(ctx context.Context, taskID uint8) error {
	var err error
	grp.taskID = taskID
	grp.ctx = ctx
	i := 0

	processGroupModResult := func(err error) bool {

		statusCode, statusMsg := infraerror.GetErrorInfo(err)

		if infraerrorcode.ErrorCode(statusCode) != infraerrorcode.ErrOk {

			if grp.group.Command == of.GroupCommandAdd && (codes.Code(statusCode) == codes.AlreadyExists) {
				logger.Warnw(ctx, "Update Group Table Failed - Ignoring since Group Already exists",
					log.Fields{"groupId": grp.group.GroupID, "groupOp": grp.group.Command, "Status": statusCode, "errorReason": statusMsg})
				return true
			}
			logger.Errorw(ctx, "Update Group Table Failed",
				log.Fields{"groupId": grp.group.GroupID, "groupOp": grp.group.Command, "Status": statusCode, "errorReason": statusMsg})
			return false
		}
		logger.Infow(ctx, "Group Mod Result", log.Fields{"groupID": grp.group.GroupID, "Error Code": statusCode})
		return true

	}

	if grp.group.Command != of.GroupCommandDel {
		grp.group.State = of.GroupOperPending
		grp.device.UpdateGroupEntry(ctx, grp.group)
	} else {
		grp.device.DelGroupEntry(ctx, grp.group)
	}

	if !grp.device.isSBOperAllowed(grp.group.ForceAction) {
		logger.Errorw(ctx, "Skipping Group Table Update", log.Fields{"Reason": "Device State not UP", "State": grp.device.State, "GroupID": grp.group.GroupID, "Operation": grp.group.Command})
		return nil
	}

	groupUpdate := of.CreateGroupTableUpdate(grp.group)
	if vc := grp.device.VolthaClient(); vc != nil {

		//Retry on group mod failure
		//Retry attempts = 3
		//Delay between retry = 100ms. Total Possible Delay = 200ms
		for {
			logger.Infow(ctx, "Group Mod Triggered", log.Fields{"GroupId": grp.group.GroupID, "Attempt": i})
			_, err = vc.UpdateLogicalDeviceFlowGroupTable(grp.ctx, groupUpdate)
			if isSuccess := processGroupModResult(err); isSuccess {
				break
			}
			i++
			if i < 3 {
				time.Sleep(100 * time.Millisecond)
				continue
			}
			logger.Errorw(ctx, "Update Group Table Failed on all 3 attempts. Dropping request", log.Fields{"GroupId": grp.group.GroupID, "Bucket": grp.group.Buckets})
			break

		}
		return err
	}
	logger.Error(ctx, "Update Group Flow Table Failed: Voltha Client Unavailable")
	return nil
}
