# -*- 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 Globals import HTMLFile

from Products.PimenTechLibCommon.pgmlgraph import *
from Products.PimenTechLibCommon.pgobject import *
from Products.PimenTechLibCommon.pgentitymap import *

from Products.ZPsycopgDA import DA
from Products.ZCatalog.ZCatalog import *
from Products.ZCTextIndex.ZCTextIndex import ZCTextIndex

import DateTime

import Zope

def manage_addPgRoot(self, id, connection_id, REQUEST=None):
	"Add a AppRoot to a folder."
	cr = PgRoot(id, connection_id)
	self._setObject(id, cr)
	if REQUEST is not None:
		return self.manage_main(self, REQUEST)

try:
	manage_addPgRootForm = HTMLFile('dtml/PgRootAdd', globals())
except:
	pass


class PgRoot(PgObject, PGEntityMap):
	" PgRoot class "

	meta_type = 'PgRoot'

	def __init__(self, id, connection_id):
		" PgClass init "
		PgObject.__init__(self, id, connection_id, uid=1)
		PGEntityMap.__init__(self, id, "")

	def commitZodb(self):
		get_transaction().commit()
		Zope.DB.cacheMinimize(4)
		Zope.DB.cacheFullSweep(4)
		self.message('ZODB commit')
		
	def _set_pgmlgraph(self, filename):
		" Add or update pgmlgraph"
		
		id = 'pgmlgraph'
		if id in self.objectIds():
			self._delObject(id)
		pgmlgraph = PgmlGraph('pgmlgraph', 'PgmlGraph',
							  idSequence = 'uid SERIAL PRIMARY KEY',
							  usePostgreSqlIsa = 1, usePostgreSqlConstraints = 0,
							  refDefault = '0', useIndices = 1)
		self._setObject(id, pgmlgraph)
		pgmlgraph = self[id]
		file = open(filename)
		pgmlgraph.readFile(file)
		pgmlgraph.simplify()

	def _set_globals(self):
		" Add globals values : globals module must be in zope python path"
		
		str_path = 'globals'
		objects = self.aq_chain[:-1]
		for object in objects:
			if object.getId():
				str_path += '_' + object.getId()
		globals = __import__(str_path)
		reload(globals)
		for name in dir(globals):
			value = globals.__dict__[name]
			if name[:1] != '_' and name != 'os':
				self._set_property(name, value)

		self._getPath = ''
		objects.reverse()
		for object in objects:
			if hasattr(object, 'getId') and object.getId():
				self._getPath += '/%s' % object.getId()

		return "set_globals : OK"

	def _set_catalog(self, indexes):
		" Add or update ZCatalog "
		if 'Catalog' in self.objectIds():
			self._delObject('Catalog')
		zc = ZCatalog('Catalog')
		self._setObject(zc.id, zc)
		zc = self['Catalog']
			
		for (index, type, extra) in indexes:
			zc.manage_addIndex(index, type, extra)
	
	def get_index_list_from_tables(self, tables= ('object', )):
		"build index list from named tables"
		d = {}
		l = [
			('id',            'FieldIndex',   None),
			('meta_type',     'FieldIndex',   None),
			('path',          'PathIndex',    None),
			]
		for tablename in tables:
			for field in self.pgmlgraph[tablename].object.get_fields():
				try:
					d[field] = self.pgmlgraph[tablename][field]['type']
				except:
					raise "%s %s" % (tablename, field)
		for field, typ in d.items():
			field = 'pg_' + field
			if typ in ('date', 'datetime', 'timestamp'):
				l.append( (field, 'DateIndex', None) )
			else:
				l.append( (field, 'FieldIndex', None) )
		return l

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

		# Load globals
		self._set_globals()

		# Load PostgreSQL graph
		self._set_pgmlgraph(self.ZOPEPRODUCTSDIR+'/'+self.ZOPEPRODUCT+'/'+self.APPLICATION+'.pgml')
		
		# Postgresql connection
		connection = DA.Connection(self.connection_id, '',
								   'host=%s user=%s password=%s dbname=%s port=%s' % (
			self.DBHOST, self.DBUSER, self.DBPWD, self.DBNAME, self.DBPORT),
								   1, 1)
		self._setObject(self.connection_id, connection)

	
	def set_user(self, login, pwd, roles, domains=0):
		" Add a user "
		self.warning("Add or change user '%s'" % login )
		if self.acl_users.getUser(login):
			return self.acl_users._changeUser(login, pwd, pwd, roles, domains)
		else:
			return self.acl_users._addUser(login, pwd, pwd, roles, domains)
		
	
	def del_user(self, login):
		" Remove a user "
		self.warning("Delete user '%s'" % login)
		self.acl_users._delUsers((login,))

		
	def _set_property(self, name, value, type='string'):
		"""
		shortcut to PropertyManager methods.
		_set_property do a setattr and fill the _property dict,
		usable in manage_propertiesForm tab
		"""
		if self.hasProperty(name):
			self._updateProperty(name, value)
		else:
			self._setProperty(name, value, type)

	def get_named_path(self):
		" Construction of named path : nothing on root app "
		return ''
	
	def app_aq_chain(self, object, REQUEST):
		" Path of objects if rights "
		out = []
		objects = object.aq_chain[:-1]
		objects.reverse()
		start = None
		for object in objects:
			if object == self:
				start = 1
			if start and REQUEST['AUTHENTICATED_USER'].has_permission('View',object):
				out.append((object.getId(), object))
		return out

	def get_uid_from_first_meta_type(self, object, meta_type):
		" return uid of first meta_type found in aq_chain "
		objects = object.aq_chain[:-1]
		objects.reverse()
		for o in objects:
			if o.meta_type == meta_type:
				return o.getUid()
		self.error("pgroot.py(get_uid_from_first_meta_type) : no depatment found")
		return 0
	
	def get_ref_author(self, request_or_login, meta_type='User Folder'):
		" Give the ref from the login "
		request_type = 'REQUEST'
		if type(request_or_login) == type(''):
			login = request_or_login
			request_type = 'string'
		else:
			login = request_or_login.AUTHENTICATED_USER.getUserName()
		cat = self.Catalog(pg_login=login, meta_type=meta_type)
		if len(cat) > 1:
			self.error("[pgroot] login '%s' non unique" % login)
			return -1
		elif len(cat) == 0:
			if request_type == 'REQUEST' and not request_or_login.AUTHENTICATED_USER.has_role('Manager'):
				self.warning("[pgroot] no login '%s' found" % login)
			return -2
		else:
			obj = cat[0].getObject()
			if obj.meta_type == 'UserId':
				return obj.pg_ref_personne_physique
			else:
				return obj.getUid()

	def get_object_from_id(self, id):
		" Return the object from id "
		cat = self.Catalog(id=id)
		if len(cat) > 1:
			self.error("[pgroot] id '%s' non unique" % id)
			return 0
		elif len(cat) == 0:
			self.error("[pgroot] no id '%s'" % id)
			return 0
		else:
			return cat[0].getObject()
	
	def get_next_uid(self):
		"next uid sequence"
		(val,) = self.fetchone("select nextval('object_uid_seq')")
		return val

	def get_root_app(self):
		return self

	###
	### HTML methods -> create a new object ?
	###
	def html_form_select(self, tablename, selectname, selectuid=None, init=(0, None), title=None, testfunc=None, extra=""):
		" create a html select from pgentities "
		txt = '<select name="%s"%s>\n' % (selectname, extra)
		if init and init[1]:
			txt += '  <option value="%s">%s</option>\n' % (init)
		if title:
			txt += '  <option disabled="disabled">- %s -</option>\n' % title
		for (uid, ztitle) in self.ztitle_entities(tablename):
			if uid == 0:
				continue
			# if testfunc exists, check the testfunc :
			if testfunc and not testfunc(uid):
				continue
			txt += '  <option value="%d"' % uid
			if uid == selectuid:
				txt += ' selected="selected"'
			txt += '>%s</option>\n' % ztitle
		txt += '</select>\n'
		return txt
	def html_form_radio(self):
		pass
	def html_form_checkbox(self):
		pass
	def html_label(self, name, value=None, classoption=None):
		" create a html label "
		txt = '<span class="label %s">%s : </span>' % ((classoption or ''), name)
		if value == 0:
			txt += '-'
		if value:
			txt += '%s' % value
		txt += '\n'
		return txt

