# encoding: utf-8
import os, atexit, shutil
from smisk.util._bsddb import db, dbshelve
from smisk.util.cache import app_shared_key
from tempfile import gettempdir

_dicts = {}

def shared_dict(filename=None, homedir=None, name=None, mode=0600, dbenv=None, 
								type=db.DB_HASH, flags=db.DB_CREATE, persistent=False):
	orig_name = name
	is_tempdir = False
	
	if filename:
		filename = os.path.abspath(filename)
		homedir = os.path.dirname(filename)
		name = os.path.basename(filename)
	else:
		if name is None:
			name = app_shared_key()
		if homedir is None:
			is_tempdir = True
			homedir = os.path.join(gettempdir(), '%s.ipc' % name)
		filename = os.path.abspath(os.path.join(homedir, name))
	
	try:
		return _dicts[filename]
	except KeyError:
		pass
	
	if not persistent and os.path.isdir(homedir):
		try:
			shutil.rmtree(homedir, True)
			os.mkdir(homedir)
		except:
			pass
	
	if not os.path.isdir(homedir):
		if os.path.exists(homedir):
			os.remove(homedir)
		os.mkdir(homedir)	# if this fail w errno 17, the homedir or it's parent is not writeable
	
	if not dbenv:
		dbenv = db.DBEnv()
		dbenv.open(homedir, db.DB_CREATE | db.DB_INIT_MPOOL | db.DB_INIT_CDB)
	
	d = DBDict(dbenv, sync=persistent)
	d.open(filename, name, type, flags, mode)
	_dicts[filename] = d
	
	if not persistent and is_tempdir:
		atexit.register(shutil.rmtree, homedir, True)
	
	return d


class DBDict(dbshelve.DBShelf):
	def __init__(self, dbenv, sync=False, *va, **kw):
		dbshelve.DBShelf.__init__(self, dbenv, *va, **kw)
		self.sync = sync
		self._closed = True
	
	def __del__(self):
		self.close()
		dbshelve.DBShelf.__del__(self)
	
	def open(self, *args, **kwargs):
		self.db.open(*args, **kwargs)
		self._closed = False
	
	def close(self, *args, **kwargs):
		try:
			if self.sync:
				self.db.sync()
			self.db.close(*args, **kwargs)
		except db.DBError:
			pass
		self._closed = True
	
