# -*- coding: latin-1 -*-
""" 
   Copyright (C) 1999-2006 PimenTech SARL (http://www.pimentech.net)

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.	
"""

from Products.PimenTechLibCommon.row import *
from Products.PimenTechLibCommon.map import *
from Products.PimenTechLibCommon.dbp import *

from Products.ZCatalog import CatalogPathAwareness

from Globals import HTMLFile

import DateTime
import AccessControl.Role

class PgObject(Map, DBP, CatalogPathAwareness.CatalogAware):
	"""
	PgObject class
	This object use acquisition from a PgRoot object : if you haven't, use pgroot.
	"""

	meta_type = "PgObject"
	named_path = "/"
	tablename = None

	__DBP_init = DBP.__init__
	__Map_init = Map.__init__

	view_history = HTMLFile('dtml/history', globals()) 

	manage_options = (
		Map.manage_options[0], Map.manage_options[3], Map.manage_options[7],
		{'label' : 'History', 'action' : 'view_history' },
		)

	__date_type__ = type(DateTime.DateTime())

	def __init__(self, id, connection_id, uid = None, initialized_from = 'postgresql', tablename = None, meta_type = None):
		id = str(id)
		self._initialized_from = initialized_from # 'interface' or 'postgresql'
		self.__DBP_init(id, connection_id)
		self.__Map_init(id)
		self.uid = int(uid or id)
		self.meta_type = meta_type or self.meta_type
		self.tablename = tablename or self.tablename

	def manage_afterAdd(self, id, container):
		" Zope method : automaticaly called when an instance is created. "
		
		self.message("%s.manage_afterAdd(%s)" % (self.tablename, self.id))

		self._create_current_row()

		if self._initialized_from == 'interface':
			PgObject.insert(self)
		else:
			self._pgobject_update()

	_pgobject_manage_afterAdd = manage_afterAdd
	
	def manage_beforeDelete(self, id, container):
		" Zope method : automaticaly called when an instance is deleted. "			
		self.unindex_object()
		self.notice("id %s : %s.manage_beforeDelete" % (self.id, self.tablename))

	def is_allowed(self, method_name, REQUEST):
		" return true if the method has the permission "
		if not getattr(self, '__ac_permissions__', None):
			self.message('no __ac_permissions__ !')
			return 0
		roles = []
		for (permission, list) in self.__ac_permissions__:
			if method_name in list:
				for dict in self.get_root_app().rolesOfPermission(permission):
					if dict['selected'] == 'SELECTED':
						roles.append(dict['name'])
				for role in roles:
					if role in REQUEST.AUTHENTICATED_USER.getRolesInContext(self):
						self.message('is allowed with role %s !' % role)
						return 1
		#self.message('not allowed | roles : ' + `roles` + ' | perm : ' + `self.__ac_permissions__`)
		return 0

	def _create_current_row(self):
		"Called by PGObject.manage_afterAdd : add the row of self.tablename"
		if not self.has_key(self.tablename):
			self[self.tablename] = PRow(self.tablename, self.tablename, self.getUid())
			return 1
		return 0
	
	def _add_row(self, uid, table_name, id=None):
		if id is None:
			id = table_name
		row = PRow(id, table_name, uid)
		self[id] = row

	def add_row_from_pg(self, uid, table_name, id=None):
		"ajoute une row avec données ds la base"
		self._add_row(uid, table_name, id)
		self[table_name].update()

	def update(self, REQUEST=None):
		" <= Update all rows of pgobject from postgreql"
		for row in self.objectValues('Row'):
			row.update()
		self.title = self.get_row_attr('ztitle')
		self.reindex()
		return "update OK"
	
	_pgobject_update = update
	
	def commit(self, REQUEST):
		" => Update all rows of pgobject to postgreql"
			
		for row in self.objectValues('Row'):
			if not row._to_be_commited:
				continue
			self._p_changed = 1
			row.commit(REQUEST)
		return "commit OK"
	
	def insert(self):
		" => Insert all rows of pgobject to postgreql"

		for row in self.objectValues('Row'):
			row.insert()
		self.reindex()	
		return "insert OK"

	def _update_or_insert(self, instance):
		" Update or insert an object from the update function (PostgreSQL) "
		instance = self[instance.getId()] or self._add_object(instance)
		instance.update()
		return instance

	def _add_object(self, instance):
		" Add an objet (used by update_or_insert function) (PostgreSQL) "
		self.fetchone("select uid from %s where uid=%s" % (instance.tablename, instance.getUid()))
		self[instance.getId()] = instance
		return self[instance.getId()]

	def get_row_attr(self, attribute, tablename=None, meta_type=None):
		if meta_type and meta_type != self.meta_type:
			return ''
		tablename = tablename or self.tablename
		value = self[tablename][attribute]
		if value == None:
			return ''
		return value
		
	def getUid(self):
		"returns the value of uid in postgresql"
		return self.uid

	def reindex(self):
		"reindex catalog"
		self.parent_path = self.aq_parent.getPath()
		for key, value in self[self.tablename].items():
			setattr(self, 'pg_'+key, value)
		self.title = self.pg_ztitle or self.pg_zid
		if self.title and self.named_path[- len(self.title):] != self.title:
			self._set_named_path()
		return self.reindex_object()

	def get_named_path(self):
		" Construction of named path "
		return '%s/%s' % (self.aq_parent.get_named_path(), self.title)

	def _set_named_path(self):
		"save the named path"
		self.named_path = self.get_named_path()
		
	def _get_next_uid(self):
 		(val,) = self.fetchone("select nextval('object_uid_seq')")
 		return val
	
	def manage_delObjects(self, ids=[], REQUEST=None):
		"""Delete a subordinate object

		The objects specified in 'ids' get deleted.

		** THIS IN THE FUNCTION FROM OFS/ObjectManager.py **
		
		"""
		if type(ids) is type(''): ids=[ids]
		if not ids:
			return MessageDialog(title='No items specified',
				   message='No items were specified!',
				   action ='./manage_main',)
		try:	p=self._reserved_names
		except: p=()
		for n in ids:
			if n in p:
				return MessageDialog(title='Not Deletable',
					   message='<EM>%s</EM> cannot be deleted.' % escape(n),
					   action ='./manage_main',)
		while ids:
			id=ids[-1]
			v=self._getOb(id, self)

			if v.wl_isLocked():
				raise ResourceLockedError, (
					'Object "%s" is locked via WebDAV' % v.getId())

			if v is self:
				raise BadRequest, '%s does not exist' % escape(ids[-1])
			
			if 'delete_me' in dir(self[id]):
				self.notice('delete_me by manage_delObject on id %s' % id)
				self[id].delete_me(REQUEST)
			else:
				self._delObject(id)
			del ids[-1]
			
		if REQUEST is not None:
			return self.manage_main(self, REQUEST, update_menu=1)

	def delete_me(self, REQUEST, withRows=1):
		"Delete this object and its rows"
		self.warning('[pgobject.py(delete_me)] delete object %s in %s named %s' % (
			self.getId(), self.aq_parent.meta_type, self.aq_parent.getId()))

		if withRows:
			for row in self.objectValues('Row'):
				row['ref_statut'] = 1
				self.commit(REQUEST)
				# commit the row in delete_beforeDelete()
			
		for id in self.objectIds():
			if 'delete_me' in dir(self[id]):
				self[id].delete_me(REQUEST)
			else:
				self._delObject(id)
		self.aq_parent._delObject(self.getId())
		return REQUEST.RESPONSE.redirect('.')

	def all_real_meta_types(self):
		"Return list of meta_types instead of list of dicts 'all_meta_types'"
		meta_types = []
		if callable(self.all_meta_types):
			all = self.all_meta_types()
		else:
			all = self.all_meta_types
		for meta_type in all:
			meta_types.append(meta_type['name'])
		return meta_types
		

	def _copy(self, REQUEST, dict_values={}):
		" duplicate the row "
		uid = self._get_next_uid()
		row = self[self.tablename]
		row._copy(uid, dict_values, REQUEST)
		self.commit(REQUEST)
		self.reindex()
		return uid

	def sql_history(self, uid):
		" return all values of a previous pgobject "
		query = "SELECT * FROM %s WHERE uid=%s AND ref_statut!=1 " % (self.tablename, uid)
		return self.dictfetchone(query)

