/*
 * Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors

 * 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 (
	"context"
	"fmt"
	"github.com/opencord/voltha-lib-go/v7/pkg/log"
	"sync"
)

type Store struct {
	olts sync.Map
	onus sync.Map
	bps  sync.Map
}

func NewStore() *Store {
	return &Store{
		olts: sync.Map{},
		onus: sync.Map{},
		bps:  sync.Map{},
	}
}

func (s *Store) addOlt(ctx context.Context, entry SadisOltEntry) {
	logger.Debugw(ctx, "adding-olt", log.Fields{"olt": entry})
	s.olts.Store(entry.ID, entry)
}

func (s *Store) addOnu(ctx context.Context, entry SadisOnuEntryV2) {
	logger.Debugw(ctx, "adding-onu", log.Fields{"onu": entry})
	s.onus.Store(entry.ID, entry)
}

func (s *Store) addBp(ctx context.Context, entry SadisBWPEntry) {
	logger.Debugw(ctx, "adding-bp", log.Fields{"bp": entry})
	s.bps.Store(entry.ID, entry)
}

func (s *Store) getOlt(ctx context.Context, id string) (*SadisOltEntry, error) {
	logger.Debugw(ctx, "getting-olt", log.Fields{"olt": id})
	if entry, ok := s.olts.Load(id); ok {
		e := entry.(SadisOltEntry)
		return &e, nil
	}
	return nil, fmt.Errorf("olt-not-found-in-store")
}

func (s *Store) getOnu(ctx context.Context, id string) (*SadisOnuEntryV2, error) {
	logger.Debugw(ctx, "getting-onu", log.Fields{"onu": id})
	if entry, ok := s.onus.Load(id); ok {
		e := entry.(SadisOnuEntryV2)
		return &e, nil
	}
	return nil, fmt.Errorf("onu-not-found-in-store")
}

func (s *Store) getBp(ctx context.Context, id string) (*SadisBWPEntry, error) {
	logger.Debugw(ctx, "getting-bp", log.Fields{"bp": id})
	if entry, ok := s.bps.Load(id); ok {
		e := entry.(SadisBWPEntry)
		return &e, nil
	}
	return nil, fmt.Errorf("bp-not-found-in-store")
}
