from locale import strcoll
from Products.CMFCore import CMFCorePermissions
from Products.CMFCore.utils import getToolByName
from AccessControl import ClassSecurityInfo
from Acquisition import aq_parent, aq_inner

from Products.ATContentTypes.content.base import updateActions
from Products.ATContentTypes.content.topic import ATTopic, IGNORED_FIELDS
from Products.ATContentTypes.interfaces import IATTopic
from Products.ATContentTypes.types.criteria import _criterionRegistry
from Products.ATContentTypes.permission import ChangeTopics, AddTopics
from Products.CMFCore.permissions import View
from Products.ATContentTypes.content.topic import ATTopicSchema
from Products.ATContentTypes.interfaces import IATTopicSearchCriterion, IATTopicSortCriterion
from Products.Archetypes.public import *
from config import *
from Products.CMFPlone.PloneBatch import Batch
from Products.ATContentTypes.config import TOOLNAME
from StringIO import StringIO
from csv import DictWriter
import csv

qTopic_schema = ATTopicSchema.copy() + Schema((
          StringField("catalog",
                       default = "portal_catalog",
                       vocabulary = "getCatalogList",
                       widget = SelectionWidget(label="Catalog",
                                       label_msgid="label_catalog",
                                       description="Select catalog to query",
                                       description_msgid="description_catalog")
          ),
          BooleanField("showHeader",
                      schemata = "export",
                      default = 1,
                      widget = BooleanWidget(label="Print field headers",
                                             label_msgid="label_print_headers",
                                             description="Check if headers need to be printed",
                                             description_msgid="description_print_headers")
          ),
          StringField("delimiter",
                      default = ";",
                      schemata = "export",
                      widget = StringWidget(label="Values delimiter",
                                            label_msgid="label_delimiter",
                                            description="Select delimiter to be used in CSV",
                                            description_msgid="description_delimiter",
                                            size = 4)
          ),
          ))
qTopic_schema["customViewFields"].schemata = "export"
qTopic_schema["customViewFields"].vocabulary = "listMetaDataFields"
qTopic_schema["customViewFields"].default=("id","getFullName","getEmail")

class qTopic(ATTopic):
    """A topic folder"""
    meta_type      = "qTopic"
    portal_type    = "qTopic"
    archetype_name = "qTopic"
    typeDescription= ("qTopic is the same topic but with "+
                      "option of catlog selection")
    typeDescMsgId  = "description_edit_topic"

    schema = qTopic_schema
    security       = ClassSecurityInfo()
    actions = updateActions(ATTopic,
        (
        {
        "id"          : "export_csv",
        "name"        : "Export in CSV",
        "action"      : "string:${folder_url}/result_csv",
        "permissions" : (CMFCorePermissions.View,)
        },
       )
    )

    def getCatalogList(self):
        """ return list of catalog ids
        """
        at_tool = getToolByName(self, "archetype_tool")
        catalogs = at_tool.getCatalogsInSite()
        return  DisplayList(zip(catalogs, catalogs))

    security.declareProtected(ChangeTopics, "criteriaByIndexId")
    def criteriaByIndexId(self, indexId):
        """ get createrias by index """
        catalog_tool = getToolByName(self, self.getCatalog())
        indexObj = catalog_tool.Indexes[indexId]
        results = _criterionRegistry.criteriaByIndex(indexObj.meta_type)
        return results

    security.declareProtected(View, 'allowedCriteriaForField')
    def allowedCriteriaForField(self, field, display_list=False):
        """ Return all valid criteria for a given field.  Optionally include
            descriptions in list in format [(desc1, val1) , (desc2, val2)] for
            javascript selector."""
        tool = getToolByName(self, self.getCatalog())
        criteria = _criterionRegistry.listTypes()
        allowed = [crit for crit in criteria
                                if crit in self.criteriaByIndexId(field)]
        if display_list:
            flat = []
            for a in allowed:
                desc = _criterionRegistry[a].shortDesc
                flat.append((a,desc))
            allowed = DisplayList(flat)
        return allowed

    security.declareProtected(ChangeTopics, "listFields")
    def listFields(self):
        """Return a list of fields from portal_catalog.
        """
        tool = getToolByName(self, TOOLNAME)
        return tool.getEnabledFields(catalog_name=self.getCatalog())

    security.declareProtected(ChangeTopics, 'listAvailableFields')
    def listAvailableFields(self):
        """Return a list of available fields for new criteria.
        """
        return self.listFields()
    
    security.declareProtected(View, 'listMetaDataFields')
    def listMetaDataFields(self, exclude=True):
        """Return a list of metadata fields from portal_catalog.
        """
        tool = getToolByName(self, TOOLNAME)
        catalog_name=self.getCatalog()
        return tool.getMetadataDisplay(exclude,catalog_name=catalog_name)

    security.declareProtected(CMFCorePermissions.View, "queryCatalog")
    def queryCatalog(self, REQUEST=None, batch=False, b_size=None,
                                                    full_objects=False, **kw):
        """Invoke the catalog using our criteria to augment any passed
            in query before calling the catalog.
        """
        if REQUEST is None:
            REQUEST = getattr(self, 'REQUEST', {})
        b_start = REQUEST.get('b_start', 0)

        q = self.buildQuery()
        if q is None:
            # empty query - do not show anything
            if batch:
                return Batch([], 20, int(b_start), orphan=0)
            return []
        # Allow parameters to further limit existing criterias
        for k,v in q.items():
            if kw.has_key(k):
                arg = kw.get(k)
                if isinstance(arg, (ListType,TupleType)) and isinstance(v, (ListType,TupleType)):
                    kw[k] = [x for x in arg if x in v]
                elif isinstance(arg, StringType) and isinstance(v, (ListType,TupleType)) and arg in v:
                    kw[k] = [arg]
                else:
                    kw[k]=v
            else:
                kw[k]=v
        #kw.update(q)
        pcatalog = getToolByName(self, self.getCatalog())
        limit = self.getLimitNumber()
        max_items = self.getItemCount()
        # Batch based on limit size if b_szie is unspecified
        if max_items and b_size is None:
            b_size = int(max_items)
        else:
            b_size = 20
        if limit and max_items and self.hasSortCriterion():
            # Sort limit helps Zope 2.6.1+ to do a faster query
            # sorting when sort is involved
            # See: http://zope.org/Members/Caseman/ZCatalog_for_2.6.1
            kw.setdefault('sort_limit', max_items)
        __traceback_info__ = (self, kw,)
        results = pcatalog.searchResults(REQUEST, **kw)
        if full_objects and not limit:
            results = [b.getObject() for b in results]
        if batch:
            batch = Batch(results, b_size, int(b_start), orphan=0)
            return batch
        if limit:
            if full_objects:
                return [b.getObject() for b in results[:max_items]]
            return results[:max_items]
        return results

    def toCSV(self, fields, data):
        dialect = csv.excel()
        dialect.delimiter = self.getDelimiter()
        buffer = StringIO()
        writer = DictWriter(buffer, fieldnames=fields, dialect=dialect)
	if self.getShowHeader():
            writer.writerow(dict(zip(fields, fields)))
        writer.writerows(data)
        return buffer.getvalue()


registerType(qTopic, PROJECTNAME)

def modify_fti(fti):
    """Remove folderlisting action
    """
    actions = []
    fti['allowed_content_types'] = ('qTopic',)
    fti['filter_content_types'] = 1
    for action in fti["actions"]:
        if action["id"] == "folderlisting":
                action["visible"] = False
                #actions.append(action)
    #fti["actions"] = tuple(actions)
