##############################################################################
#
# Copyright (c) 2004-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
#
# $Id: misc.py 1304 2005-09-08 14:35:42Z nicoe $
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

"""
Miscelleanous tools used by tiny ERP.
"""

import os, time, sys
import inspect

import psycopg
import netsvc
import sql_db
from config import config

if sys.version_info[:2] < (2, 4):
	from threadinglocal import local
else:
	from threading import local

#----------------------------------------------------------
# Destroy db
#----------------------------------------------------------
def sql_destroy(key):
	"""
	Delete everything from a view:
		tables, linked tables
		actions, views, workflows, inhertiancy
	"""
	logger = netsvc.Logger()
	logger.notifyChannel("init", netsvc.LOG_INFO, "DESTROYING %s%%"%key)
	cr=sql_db.db.cursor()
	try:
		cr.execute("SELECT relname FROM pg_class WHERE relkind='v' AND relname LIKE '"+key+"%'")
		for i in cr.dictfetchall():
			cr.execute("DROP VIEW %s"%i['relname'])
		cr.commit()
	except psycopg.ProgrammingError:
		pass
	cr.close()

	cr=sql_db.db.cursor()
	try:
		cr.execute("SELECT relname FROM pg_class WHERE relkind='r' AND relname LIKE '"+key+"%'")
		for i in cr.dictfetchall():
			cr.execute("DROP TABLE %s CASCADE"%i['relname'])
		cr.commit()
	except psycopg.ProgrammingError:
		pass
	cr.close()

	cr=sql_db.db.cursor()
	cr.execute("DELETE FROM ir_act_report_xml WHERE report_name LIKE '"+key+"%'")
	cr.execute("DELETE FROM ir_act_window WHERE name LIKE '"+key+"%'")
	cr.execute("DELETE FROM ir_ui_view WHERE name LIKE '"+key+"%'")
	cr.execute("DELETE FROM wkf where osv like '"+key+".%'")
	cr.execute("DELETE FROM wkf_instance where res_type like '"+key+".%'")
	cr.execute("DELETE FROM wkf_logs where res_type like '"+key+".%'")
	cr.execute("DELETE FROM inherit where obj_type like '"+key+".%'")
	cr.commit()
	cr.close()

#----------------------------------------------------------
# File paths
#----------------------------------------------------------
#file_path_root = os.getcwd()
#file_path_addons = os.path.join(file_path_root, 'addons')

def file_open(name, mode="r", subdir='addons'):
	"""Open a file from the Tiny ERP root, using a subdir folder."""
	name = os.path.join(config['root_path'], subdir, name)
	return file(name, mode)

#----------------------------------------------------------
# Emails
#----------------------------------------------------------
def email_send(email_from, email_to, subject, body, email_cc=[], email_bcc=[], on_error=False):
	"""Send an email."""
	import smtplib
	from email.MIMEText import MIMEText
	from email.Header import Header
	from email.Utils import formatdate
	msg = MIMEText(body, _charset='utf-8')
	msg['Subject'] = Header(subject, 'utf-8')
	msg['From'] = email_from
	msg['To'] = ','.join(email_to)
	if email_cc:
		msg['Cc'] = ','.join(email_cc)
	if email_bcc:
		msg['Bcc'] = ','.join(email_bcc)
	msg['Date'] = formatdate(localtime=True)
	try:
		s = smtplib.SMTP()
		s.connect(config['smtp_server'])
		s.sendmail(email_from, email_to + email_cc + email_bcc, msg.as_string())
		s.quit()
	except Exception, e:
		import logging
		logging.getLogger().info(str(e))

#----------------------------------------------------------
# SMS
#----------------------------------------------------------
# text must be latin-1 encoded
def sms_send(user, password, api_id, text, to):
	import urllib
	params = urllib.urlencode({'user': user, 'password': password, 'api_id': api_id, 'text': text, 'to':to})
	#print "http://api.clickatell.com/http/sendmsg", params
	#f = urllib.urlopen("http://api.clickatell.com/http/sendmsg", params)
	print "http://196.7.150.220/http/sendmsg", params
	f = urllib.urlopen("http://196.7.150.220/http/sendmsg", params)
	print f.read()
	
#---------------------------------------------------------
# Class that stores an updateable string (used in wizards)
#---------------------------------------------------------
class UpdateableStr(local):

	def __init__(self, string=''):
		self.string = string
	
	def __str__(self):
		return str(self.string)

	def __repr__(self):
		return str(self.string)

	def __nonzero__(self):
		return bool(self.string)

class currency(float):	

	def __init__(self, value, accuracy=2, rounding=None):
		if rounding is None:
			rounding=10**-accuracy
		self.rounding=rounding
		self.accuracy=accuracy

	def __new__(cls, value, accuracy=2, rounding=None):
		return float.__new__(cls, round(value, accuracy))

	#def __str__(self):
	#	display_value = int(self*(10**(-self.accuracy))/self.rounding)*self.rounding/(10**(-self.accuracy))
	#	return str(display_value)


#
# Use it as a decorator of the function you plan to cache
# Timeout: 0 = no timeout, otherwise in seconds
#
class cache(object):
	def __init__(self, timeout=10000, skiparg=2):
		self.timeout = timeout
		self.cache = {}

	def __call__(self, fn):
		arg_names = inspect.getargspec(fn)[0][2:]
		def cached_result(self2, cr=None, *args, **kwargs):
			if cr is None:
				self.cache = {}
				return True
			# Update named arguments with positional argument values
			kwargs.update(dict(zip(arg_names, args)))
			kwargs = kwargs.items()
			kwargs.sort()
			# Work out key as a tuple of ('argname', value) pairs
			key = tuple(kwargs)

			# Check cache and return cached value if possible
			if key in self.cache:
				(value, last_time) = self.cache[key]
				mintime = time.time() - self.timeout
				if self.timeout <= 0 or mintime <= last_time:
					return value
				else:
					pass
					#
					# Clear Cache at this point ?
					#

			# Work out new value, cache it and return it
			# Should copy() this value to avoid futur modf of the cacle ?
			result = fn(self2,cr,**dict(kwargs))

			self.cache[key] = (result, time.time())
			return result
		return cached_result

# vim:noexpandtab
