// 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 apidAnalytics

import (
	"database/sql"
	"github.com/apigee-labs/transicator/common"
	"sync"
)

// Cache for scope uuid to org, env and tenantId information
var tenantCache map[string]tenant

// RW lock for tenant map cache since the cache can be
// read while its being written to and vice versa
var tenantCachelock = sync.RWMutex{}

// Cache for apiKey~tenantId to developer related information
var developerInfoCache map[string]developerInfo

// RW lock for developerInfo map cache since the cache can be
// read while its being written to and vice versa
var developerInfoCacheLock = sync.RWMutex{}

// Load data scope information into an in-memory cache so that
// for each record a DB lookup is not required
func createTenantCache(snapshot *common.Snapshot) {
	// Lock before writing to the map as it has multiple readers
	tenantCachelock.Lock()
	defer tenantCachelock.Unlock()
	tenantCache = make(map[string]tenant)

	for _, table := range snapshot.Tables {
		switch table.Name {
		case "edgex.data_scope":
			for _, row := range table.Rows {
				var org, env, tenantId, id string

				row.Get("id", &id)
				row.Get("scope", &tenantId)
				row.Get("org", &org)
				row.Get("env", &env)
				if id != "" {
					tenantCache[id] = tenant{Org: org,
						Env:      env,
						TenantId: tenantId}
				}
			}
		}
	}
	log.Debugf("Count of data scopes in the cache: %d", len(tenantCache))
}

// Load data scope information into an in-memory cache so that
// for each record a DB lookup is not required
func updateDeveloperInfoCache() {
	// Lock before writing to the map as it has multiple readers
	developerInfoCacheLock.Lock()
	defer developerInfoCacheLock.Unlock()
	developerInfoCache = make(map[string]developerInfo)
	log.Debug("Invalidated developerInfo cache")
}

// Returns Tenant Info given a scope uuid from the cache or by querying
// the DB directly based on useCachig config
func getTenantForScope(scopeuuid string) (tenant, dbError) {
	if config.GetBool(useCaching) {
		// acquire a read lock as this cache has 1 writer as well
		tenantCachelock.RLock()
		ten, exists := tenantCache[scopeuuid]
		tenantCachelock.RUnlock()
		dbErr := dbError{}

		if !exists {
			log.Debugf("No tenant found for scopeuuid = %s "+
				"in cache", scopeuuid)
			log.Debug("loading info from DB")

			// Update cache
			t, err := getTenantFromDB(scopeuuid)

			if err.ErrorCode != "" {
				dbErr = err
				ten = t
			} else {
				// update cache
				tenantCachelock.Lock()
				defer tenantCachelock.Unlock()
				tenantCache[scopeuuid] = t
				ten = t
			}
		}
		return ten, dbErr
	} else {
		return getTenantFromDB(scopeuuid)
	}
}

// Returns Developer related info given an apiKey and tenantId
// from the cache or by querying the DB directly based on useCachig config
func getDeveloperInfo(tenantId string, apiKey string) developerInfo {
	if config.GetBool(useCaching) {
		keyForMap := getKeyForDeveloperInfoCache(tenantId, apiKey)
		// acquire a read lock as this cache has 1 writer as well
		developerInfoCacheLock.RLock()
		devInfo, exists := developerInfoCache[keyForMap]
		developerInfoCacheLock.RUnlock()

		if !exists {
			log.Debugf("No data found for for tenantId = %s"+
				" and apiKey = %s in cache", tenantId, apiKey)
			log.Debug("loading info from DB")

			// Update cache
			dev, err := getDevInfoFromDB(tenantId, apiKey)

			if err == nil {
				// update cache
				developerInfoCacheLock.Lock()
				defer developerInfoCacheLock.Unlock()
				key := getKeyForDeveloperInfoCache(tenantId, apiKey)
				developerInfoCache[key] = dev
			}

			devInfo = dev

		}
		return devInfo
	} else {
		devInfo, _ := getDevInfoFromDB(tenantId, apiKey)
		return devInfo
	}
}

// Returns tenant info by querying DB directly
func getTenantFromDB(scopeuuid string) (tenant, dbError) {
	var org, env, tenantId string

	db := getDB()
	error := db.QueryRow("SELECT env, org, scope FROM edgex_data_scope"+
		" where id = ?", scopeuuid).Scan(&env, &org, &tenantId)

	switch {
	case error == sql.ErrNoRows:
		reason := "No tenant found for this scopeuuid: " + scopeuuid
		errorCode := "UNKNOWN_SCOPE"
		return tenant{}, dbError{
			ErrorCode: errorCode,
			Reason:    reason}
	case error != nil:
		reason := error.Error()
		errorCode := "INTERNAL_SEARCH_ERROR"
		return tenant{}, dbError{
			ErrorCode: errorCode,
			Reason:    reason}
	}
	return tenant{
		Org:      org,
		Env:      env,
		TenantId: tenantId}, dbError{}
}

// Returns developer info by querying DB directly
func getDevInfoFromDB(tenantId string, apiKey string) (developerInfo, error) {
	var apiProduct, developerApp, developerEmail sql.NullString
	var developer sql.NullString

	db := getDB()
	sSql := "SELECT ap.name, a.name, d.username, d.email " +
		"FROM kms_app_credential_apiproduct_mapper as mp " +
		"INNER JOIN kms_api_product as ap ON ap.id = mp.apiprdt_id " +
		"INNER JOIN kms_app AS a ON a.id = mp.app_id " +
		"INNER JOIN kms_developer as d ON d.id = a.developer_id " +
		"where mp.tenant_id = ? and mp.appcred_id = ?;"
	error := db.QueryRow(sSql, tenantId, apiKey).
		Scan(&apiProduct, &developerApp,
			&developer, &developerEmail)

	switch {
	case error == sql.ErrNoRows:
		log.Debugf("No data found for for tenantId = %s "+
			"and apiKey = %s in DB", tenantId, apiKey)
		return developerInfo{}, error
	case error != nil:
		log.Debugf("No data found for for tenantId = %s and "+
			"apiKey = %s due to: %v", tenantId, apiKey, error)
		return developerInfo{}, error
	}

	apiPrd := getValuesIgnoringNull(apiProduct)
	devApp := getValuesIgnoringNull(developerApp)
	dev := getValuesIgnoringNull(developer)
	devEmail := getValuesIgnoringNull(developerEmail)

	return developerInfo{ApiProduct: apiPrd,
		DeveloperApp:   devApp,
		DeveloperEmail: devEmail,
		Developer:      dev}, nil
}

// Helper method to handle scanning null values in DB to empty string
func getValuesIgnoringNull(sqlValue sql.NullString) string {
	if sqlValue.Valid {
		return sqlValue.String
	} else {
		return ""
	}
}

// Build Key as a combination of tenantId and apiKey for the developerInfo Cache
func getKeyForDeveloperInfoCache(tenantId string, apiKey string) string {
	return tenantId + "~" + apiKey
}
