// Copyright 2019 PingCAP, 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package randsql

import (
	"strconv"
	"sync"
)

type allocator struct {
	pool chan int64
	base int64
	sync.Mutex
}

var globalIDAllocator = newAllocator()

func newAllocator() *allocator {
	return &allocator{
		pool: make(chan int64, 1000),
		base: 0,
	}
}

func (a *allocator) alloc() int64 {
	a.Lock()
	defer a.Unlock()
	select {
	case id := <-a.pool:
		return id
	default:
		a.base++
		return a.base
	}
}

func (a *allocator) put(id int64) {
	a.Lock()
	defer a.Unlock()
	select {
	case a.pool <- id:
	default:
	}
}

func genDBName() string {
	return "d" + strconv.FormatInt(globalIDAllocator.alloc(), 10)
}

func genTableName() string {
	return "t" + strconv.FormatInt(globalIDAllocator.alloc(), 10)
}

func genViewName() string {
	return "v" + strconv.FormatInt(globalIDAllocator.alloc(), 10)
}

func genColName(table *TableInfo) string {
	return "c" + strconv.FormatInt(table.idAlloc.alloc(), 10)
}

func genIdxName(table *TableInfo) string {
	return "i" + strconv.FormatInt(table.idAlloc.alloc(), 10)
}

func parseIDFromName(name string) int64 {
	num, err := strconv.ParseInt(name[1:], 10, 64)
	if err != nil {
		return 0
	}
	return num
}

func putIDToAlloc(name string, idAlloc *allocator) {
	id := parseIDFromName(name)
	if id == 0 {
		return
	}
	idAlloc.put(id)
}
