// Copyright 2017 Google Inc.
//
// 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 quotaBucket

import (
	"github.com/30x/apidQuota/constants"
	"sync"
	"time"
	"errors"
)

var quotaCachelock = sync.RWMutex{}

type quotaBucketCache struct {
	qBucket    *QuotaBucket
	expiryTime int64
}

var quotaCache map[string]quotaBucketCache

func init() {
	quotaCache = make(map[string]quotaBucketCache)
}

func getFromCache(cacheKey string, weight int64) (*QuotaBucket, bool) {
	quotaCachelock.Lock()
	qBucketCache, ok := quotaCache[cacheKey]
	quotaCachelock.Unlock()

	if !ok {
		return nil, false
	}

	isExpired := time.Unix(qBucketCache.expiryTime, 0).Before(time.Now().UTC())
	if isExpired {

		removeFromCache(cacheKey, qBucketCache)
		return nil, false
	}

	// update expiry time every time you access.
	qBucketCache.qBucket.Weight = weight
	ttl := time.Now().UTC().Add(constants.CacheTTL).Unix()
	qBucketCache.expiryTime = ttl

	quotaCachelock.Lock()
	quotaCache[cacheKey] = qBucketCache
	quotaCachelock.Unlock()

	return qBucketCache.qBucket, true

}

func removeFromCache(cacheKey string, qBucketCache quotaBucketCache) error {
	//for async Stop the scheduler.

	if qBucketCache.qBucket.Distributed && !qBucketCache.qBucket.IsSynchronous() {
		aSyncBucket := qBucketCache.qBucket.GetAsyncQuotaBucket()
		if aSyncBucket == nil {
			return errors.New(constants.AsyncQuotaBucketEmpty + " : aSyncQuotaBucket to increment cannot be empty.")
		}
		qticker, err := aSyncBucket.getAsyncQTicker()
		if err != nil {
			return err
		}
		qticker.Stop()
	}

	quotaCachelock.Lock()
	delete(quotaCache, cacheKey)
	quotaCachelock.Unlock()
	return nil
}

func addToCache(qBucketToAdd *QuotaBucket) {

	cacheKey := qBucketToAdd.GetEdgeOrgID() + constants.CacheKeyDelimiter + qBucketToAdd.GetID()
	ttl := time.Now().UTC().Add(constants.CacheTTL).Unix()
	qCacheData := quotaBucketCache{
		qBucket:    qBucketToAdd,
		expiryTime: ttl,
	}

	quotaCachelock.Lock()
	quotaCache[cacheKey] = qCacheData
	quotaCachelock.Unlock()
}
