# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2005-2010 Nexedi SA and Contributors. All Rights Reserved.
#                    Romain Courteaud <romain@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility 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
# guarantees 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.
#
##############################################################################

from AccessControl import ClassSecurityInfo
from DateTime import DateTime
from MySQLdb import ProgrammingError
from Products.ERP5Type import Permissions

class JIOAPIRevisionMixin:

  security = ClassSecurityInfo()

  security.declareProtected(Permissions.AccessContentsInformation,
                            'getJIOAPIRevision')
  def getJIOAPIRevision(self):
    """
    Return Object Revision
    """
    return self._getJIOAPIRevisionTuple()[0]

  def _unindexJIOAPIRevision(self):
    try:
      self.Base_zUnindexFromjIOAPIRevisionTable(uid=self.getUid())
    except ProgrammingError:
      # jio_api_revision table is not created
      pass

  def _getJIOAPIRevisionTuple(self):
    try:
      result = self.Base_zGetFromIOAPIRevisionTable(uid=self.getUid())
    except ProgrammingError:
      # jio_api_revision table is not created
      return None, None, None
    if result:
      return result[0].revision, result[0].hash, result[0].indexation_timestamp
    return None, None, None

  def _calculateHash(self):
    hash_method = self.getTypeBasedMethod("calculatejIOAPIRevisionHash")
    if not hash_method:
      return None
    return hash_method()

  security.declareProtected(Permissions.ManagePortal, 'updateJIOAPIRevision')
  def updateJIOAPIRevision(self):
    """
    Update jIO API Revision
    """
    indexation_timestamp = int(DateTime(self.getPortalObject().portal_catalog(
      uid=self.getUid(), select_list=('indexation_timestamp',)
    )[0].indexation_timestamp))

    calculated_hash = self._calculateHash()
    if not calculated_hash:
      self._unindexJIOAPIRevision()
      return

    stored_hash = None
    _, stored_hash, stored_timestamp = self._getJIOAPIRevisionTuple()
    stored_timestamp = int(DateTime(stored_timestamp))
    if stored_hash == calculated_hash:
      if stored_timestamp != indexation_timestamp:
        self.Base_zUpdateTimeStampjIOAPIRevisionTable(
          uid=self.getUid(),
          indexation_timestamp=indexation_timestamp,
        )
      return

    new_revision = self.Base_getNewjIOAPIRevision()
    self.Base_zUpdatejIOAPIRevisionTable(
      uid=self.getUid(),
      revision=new_revision,
      hash=calculated_hash,
      indexation_timestamp=indexation_timestamp,
    )
    return

  security.declareProtected(Permissions.AccessContentsInformation,
                            'checkJIOAPIRevisionConstraint')
  def checkJIOAPIRevisionConstraint(self, **kw):
    """
    Check is calculated Hash equals to the stored one
    Fixing is not offered as it needs to be centralised to avoid missing a new revision for an object
    """
    calculated_hash = self._calculateHash()
    _, stored_hash, _ = self._getJIOAPIRevisionTuple()
    if calculated_hash != stored_hash:
      return [self.Base_translateString(
        "Stored Hash ${stored_hash} difer from calculated hash ${calculated_hash}",
        mapping={
          "stored_hash": stored_hash,
          "calculated_hash": calculated_hash,
        }
      ),]
    return []