# Copyright (c) 2006, Mayuresh Phadke
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
#         * Redistributions of source code must retain the above copyright
#           notice, this list of conditions and the following disclaimer.
#         * Redistributions in binary form must reproduce the above copyright
#           notice, this list of conditions and the following disclaimer in the
# 	    documentation and/or other materials provided with the distribution.
#         * Neither the name of 'QualEx Systems' nor the names of its
# 	    contributors may be used to endorse or promote products derived from
# 	    this software without specific prior written permission.
# 
#         THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

import os, sys
from errno import *
from stat import *
import fuse
from fuse import Fuse
import TagHelper
from TagHelper import TagDir, TagFile
from Tagging import Tagging
from GPStor import GPStor

fuse.feature_assert('stateful_files')

def flag2mode(flags):
	md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
	m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]

	if flags | os.O_APPEND:
		m = m.replace('w', 'a', 1)

	return m

class Dhtfs(Fuse):

	MAX_DIR_ENTRIES = 210
	MISSING_FILE = '__MISSING_FILE_qwertyuiopasdfghjklzxcvbnm0987654321'		

	DB_FILE = '.dhtfs.db'
	SEQ_FILE = '.dhtfs.seq'

	def checkSetup(cls, path):
		"""
		D.checkSetup() -> Check whether dhtfs filesystem is setup at path

		@param path: Path to be checked
		@type path: str

		@return: True is dhtfs is setup at path, False otherwise
		@rtype: bool
		"""

		if not Tagging.checkSetup(db_path=path, db_file=cls.DB_FILE):	
			return False
		if not GPStor.checkSetup(db_path=path, db_file=cls.SEQ_FILE):
			return False

		return True
		
	checkSetup = classmethod(checkSetup)

	def setup(cls, path, forceInit=False):
		"""
		D.setup(path, forceInitFlag) -> Do the necessary setup to mount the specified path as a dhtfs file system

		@param path: Path for which to setup
		@type path: str

		@param forceInit: If forceInit is True, do a new setup regardless of whether an older setup is present.
		@type forceInit: bool
		"""

		# If forceInit flag is true, clean up the directory
		if forceInit:
			for root, dirs, files in os.walk(path, topdown=False):
				for name in files:
					os.remove(os.path.join(root, name))
				for name in dirs:
					os.rmdir(os.path.join(root, name))

		# Initialize tagging

		t = Tagging(db_path=path, db_file=cls.DB_FILE)
		t.initDB(forceInit = forceInit)

		# Initialize sequence generator
		seqStore = GPStor(db_path=path, db_file=cls.SEQ_FILE)

		ret, currentSeqNumber = seqStore.getDataRO()

		if (ret != 0) or (not isinstance(currentSeqNumber, long) ) or forceInit:
			seqStore.getDataRW()
			currentSeqNumber = long(0)
			seqStore.writeData(currentSeqNumber)

	setup = classmethod(setup)

	def __init__(self, *args, **kw):

		Fuse.__init__(self, *args, **kw)
		self.fileCache = {}

	def __initialize(self):
		try:
			X = self.getCover
		except:
			self.getCover = "Dont Care"

		self.logger = TagHelper.getLogger('DHTFS')
		self.tagdir = TagDir(db_path=self.root, db_file=self.DB_FILE, logger=self.logger)
		self.__initSequenceNumberGenerator()

		self.logger.info("In function : %s" % sys._getframe().f_code.co_name)
		self.logger.info("Tagging and TagDir instances created for path %s" % self.root)
		self.logger.info("self.getCover = %s" % self.getCover)

	def __initSequenceNumberGenerator(self):
		self.logger.info("In function : %s" % sys._getframe().f_code.co_name)