#!/usr/bin/python
# Filip Lundborg (filip@mkeyd.net)

import socket,os

# All the different daemon-states
state={\
	"0": "Up to date", \
	"1": "Synchronizing", \
	"2": "Not connected", \
	"NA": "Not available" \
		# except for that last one
		# it's for when we're not connected to the daemon.
	}

class DB():
	def __init__(self):
		self.connected=False
		self.state="NA"
	def connect(self):
		# try to connect
		try:
			self.cmd=socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
			self.iface=socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)

			self.cmd.connect(os.path.expanduser("~/.dropbox/command_socket"))
			self.iface.connect(os.path.expanduser("~/.dropbox/iface_socket"))

		except Exception,e:
			return False

		# alright, so we're connected to both sockets
		self.connected=True
		self.tmp=""
		return True
	
#	def disconnect(self):
#		asdf
#	garbagecollector <3

	def get_state(self):
		"Waits for a state change, and then returns it."
		if not self.connected:
			return state["NA"]

		tmp=self.tmp
		flg=False
		while True:
			t=self.iface.recv(1024)

			if t=="":
				self.connected=False
				return state["NA"]
			tmp+=t

			if len(t)>=1024:
				continue # there's more to get.

			res=tmp.split("done\n")
			self.tmp=tmp=res[-1] # put the rest back in tmp
			res=res[:-1] # and just take the whole commands

			for s in res:
				if s.startswith("change_state"):
					flg=True
					self.state=s[23] # magic numbers, terrible :S
						# it's from "change_state\nnew_state\t1\n"
						# we want the 1, which can be 0, 1 or 2.
						# look at the state dictionary further up.

			if flg:
				return state[self.state]

	def get_state_nonblocking(self):
		"Fetches the state, if there's a state change. Otherwise it returns the last state."
		if not self.connected:
			return state["NA"]

		# now we should fetch all the data from the iface-socket
		# and see if there's anything new interesting
		res=self.tmp
		while True:
			tmp=self.iface.recv(1024)
			if (tmp==""):
				self.connected=False
				return state["NA"]
	
			res+=tmp
			if len(tmp)<1000:
				break # if we didnt fill the buffer, there shouldn't be anything
					# more to fetch.

		res=res.split("done\n")

		for s in res:
			if s.startswith("change_state"):
				self.state=s[23] # same magic number, hehe.

		return state[self.state]
	
	def ask_for_state(self):
		"""This one asks for the state directly to the daemon.
		For some reasen, it doesn't always give you a state... which leaves me clueless."""
		if not self.connected:
			return state["NA"]

		self.cmd.send("get_dropbox_globals\nkeys\ticon_state\ndone\n")
		res=self.cmd.recv(1024)

		if res=="":
			self.connected=False
			return state["NA"]

		try:
			res=res.split("\t")
			if res[1][0] != "\n":
				self.state=res[1][0]
			else:
				# we didn't get a state this time. eh.
				self.state="NA"
		except Exception, e:
			# for some reason here, the daemon threw us a .. strange line back.
			self.state="NA"
		
		return state[self.state]


# Actually, there should be pretty easy to add further commands.
# Just like the old module, this could be modified to ask for different files status.

# example usage:
if __name__=="__main__":
	import time
	db=DB()

	while True:
		if not db.connect():
			time.sleep(1) # to not wear out the CPU ;)
		while db.connected:
			print db.get_state()
