"""File revision management.

"""

"""GAM Google Drive file, permission, shared drive, and label management."""

import re

from gam.cmd.drive.core import _getDriveFileNameFromId, _validateUserGetFileIDs, getDriveFileEntity

from gamlib import api as API
from gamlib import settings as GC
from gamlib import gapi as GAPI
from gamlib import state as GM
from gamlib import msgs as Msg
from gam.util.api_call import callGAPI, callGAPIpages
from gam.util.args import (
    OrderBy,
    StartEndTime,
    getArgument,
    getBoolean,
    getInteger,
    getString,
    getStringReturnInList,
    getTimeOrDeltaFromNow,
)
from gam.util.csv_pf import (
    CSVPrintFile,
    flattenJSON,
    getFieldsList,
    getItemFieldsFromFieldsList,
    showJSON,
)
from gam.util.display import (
    entityActionFailedWarning,
    entityActionNotPerformedWarning,
    entityActionPerformed,
    entityDoesNotHaveItemWarning,
    entityNumEntitiesActionNotPerformedWarning,
    entityPerformActionNumItems,
    entityPerformActionNumItemsModifier,
    printEntity,
    userDriveServiceNotEnabledWarning,
)
from gam.util.entity import getEntityArgument, getEntitySelection, getEntitySelector
from gam.util.errors import missingArgumentExit, unknownArgumentExit
from gam.util.output import _stripControlCharsFromName, setSysExitRC
from gam.constants import AND_ME_IN_OWNERS, AND_NOT_ME_IN_OWNERS, NO_ENTITIES_FOUND_RC

from gam.var import Act, Cmd, Ent, Ind

APPLICATION_VND_GOOGLE_APPS = 'application/vnd.google-apps.'
MIMETYPE_GA_DOCUMENT = f'{APPLICATION_VND_GOOGLE_APPS}document'
MIMETYPE_GA_DRAWING = f'{APPLICATION_VND_GOOGLE_APPS}drawing'
MIMETYPE_GA_FILE = f'{APPLICATION_VND_GOOGLE_APPS}file'
MIMETYPE_GA_FOLDER = f'{APPLICATION_VND_GOOGLE_APPS}folder'
MIMETYPE_GA_FORM = f'{APPLICATION_VND_GOOGLE_APPS}form'
MIMETYPE_GA_FUSIONTABLE = f'{APPLICATION_VND_GOOGLE_APPS}fusiontable'
MIMETYPE_GA_JAM = f'{APPLICATION_VND_GOOGLE_APPS}jam'
MIMETYPE_GA_MAP = f'{APPLICATION_VND_GOOGLE_APPS}map'
MIMETYPE_GA_PRESENTATION = f'{APPLICATION_VND_GOOGLE_APPS}presentation'
MIMETYPE_GA_SCRIPT = f'{APPLICATION_VND_GOOGLE_APPS}script'
MIMETYPE_GA_SCRIPT_JSON = f'{APPLICATION_VND_GOOGLE_APPS}script+json'
MIMETYPE_GA_SHORTCUT = f'{APPLICATION_VND_GOOGLE_APPS}shortcut'
MIMETYPE_GA_3P_SHORTCUT = f'{APPLICATION_VND_GOOGLE_APPS}drive-sdk'
MIMETYPE_GA_SITE = f'{APPLICATION_VND_GOOGLE_APPS}site'
MIMETYPE_GA_SPREADSHEET = f'{APPLICATION_VND_GOOGLE_APPS}spreadsheet'
ME_IN_OWNERS = "'me' in owners"
ME_IN_OWNERS_AND = ME_IN_OWNERS + " and "
NOT_ME_IN_OWNERS = "not " + ME_IN_OWNERS
NOT_ME_IN_OWNERS_AND = NOT_ME_IN_OWNERS + " and "
WITH_ANY_FILE_NAME = "name = '{0}'"
WITH_MY_FILE_NAME = ME_IN_OWNERS_AND + WITH_ANY_FILE_NAME
WITH_OTHER_FILE_NAME = NOT_ME_IN_OWNERS_AND + WITH_ANY_FILE_NAME
ROOT = 'root'
ORPHANS = 'Orphans'
SHARED_WITHME = 'SharedWithMe'
SHARED_DRIVES = 'SharedDrives'

def getRevisionsEntity():
  revisionsEntity = {'list': [], 'dict': None, 'count': None, 'time': None, 'range': None}
  startEndTime = StartEndTime()
  entitySelector = getEntitySelector()
  if entitySelector:
    entityList = getEntitySelection(entitySelector, False)
    if isinstance(entityList, dict):
      revisionsEntity['dict'] = entityList
    else:
      revisionsEntity['list'] = entityList
  else:
    myarg = getString(Cmd.OB_DRIVE_FILE_REVISION_ID, checkBlank=True)
    mycmd = myarg.lower()
    if mycmd == 'id':
      revisionsEntity['list'] = getStringReturnInList(Cmd.OB_DRIVE_FILE_REVISION_ID)
    elif mycmd[:3] == 'id:':
      revisionsEntity['list'] = [myarg[3:]]
    elif mycmd == 'ids':
      revisionsEntity['list'] = getString(Cmd.OB_DRIVE_FILE_REVISION_ID).replace(',', ' ').split()
    elif mycmd[:4] == 'ids:':
      revisionsEntity['list'] = myarg[4:].replace(',', ' ').split()
    elif mycmd in {'first', 'last', 'allexceptfirst', 'allexceptlast'}:
      revisionsEntity['count'] = (mycmd, getInteger(minVal=1))
    elif mycmd in {'before', 'after'}:
      dateTime, _, _ = getTimeOrDeltaFromNow(True)
      revisionsEntity['time'] = (mycmd, dateTime)
    elif mycmd == 'range':
      startEndTime.Get(mycmd)
      revisionsEntity['range'] = (mycmd, startEndTime.startDateTime, startEndTime.endDateTime)
    else:
      revisionsEntity['list'] = [myarg]
  return revisionsEntity

def _selectRevisionIds(drive, fileId, origUser, user, i, count, j, jcount, revisionsEntity):
  if revisionsEntity['list']:
    return revisionsEntity['list']
  if revisionsEntity['dict']:
    if not GM.Globals[GM.CSV_SUBKEY_FIELD]:
      return revisionsEntity['dict'][fileId]
    return revisionsEntity['dict'][origUser][fileId]
  try:
    results = callGAPIpages(drive.revisions(), 'list', 'revisions',
                            throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.BAD_REQUEST, GAPI.REVISIONS_NOT_SUPPORTED],
                            fileId=fileId, fields='nextPageToken,revisions(id,modifiedTime)',
                            pageSize=GC.Values[GC.DRIVE_MAX_RESULTS])
  except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
          GAPI.badRequest, GAPI.revisionsNotSupported) as e:
    entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER_ID, fileId], str(e), j, jcount)
    return []
  except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
    userDriveServiceNotEnabledWarning(user, str(e), i, count)
    return []
  numRevisions = len(results)
  if numRevisions == 0:
    return []
  if revisionsEntity['count']:
    countType = revisionsEntity['count'][0]
    count = revisionsEntity['count'][1]
    revisionIds = [revision['id'] for revision in results]
    if countType == 'first':
      if count >= numRevisions:
        return revisionIds
      return revisionIds[:count]
    if countType == 'last':
      if count >= numRevisions:
        return revisionIds
      return revisionIds[-count:]
    if countType == 'allexceptfirst':
      if count >= numRevisions:
        return []
      return revisionIds[count:]
# count: allexceptlast
    if count >= numRevisions:
      return []
    return revisionIds[:-count]
  revisionIds = []
  if revisionsEntity['time']:
    dateTime = revisionsEntity['time'][1]
    count = 0
    if revisionsEntity['time'][0] == 'before':
      for revision in results:
        modifiedDateTime = arrow.get(revision['modifiedTime'])
        if modifiedDateTime >= dateTime:
          break
        revisionIds.append(revision['id'])
        count += 1
      if count >= numRevisions:
        return revisionIds[:-1]
      return revisionIds
# time: after
    for revision in results:
      modifiedDateTime = arrow.get(revision['modifiedTime'])
      if modifiedDateTime >= dateTime:
        revisionIds.append(revision['id'])
        count += 1
    if count >= numRevisions:
      return revisionIds[1:]
    return revisionIds
# range
  startDateTime = revisionsEntity['range'][1]
  endDateTime = revisionsEntity['range'][2]
  count = 0
  for revision in results:
    modifiedDateTime = arrow.get(revision['modifiedTime'])
    if modifiedDateTime >= startDateTime:
      if modifiedDateTime >= endDateTime:
        break
      revisionIds.append(revision['id'])
      count += 1
  if count >= numRevisions:
    return revisionIds[1:]
  return revisionIds

# gam <UserTypeEntity> delete filerevisions <DriveFileEntity> select <DriveFileRevisionIdEntity> [previewdelete]
#	[showtitles] [doit] [max_to_delete <Number>]
def deleteFileRevisions(users):
  fileIdEntity = getDriveFileEntity()
  revisionsEntity = None
  previewDelete = showTitles = doIt = False
  maxToProcess = 1
  while Cmd.ArgumentsRemaining():
    myarg = getArgument()
    if myarg == 'select':
      revisionsEntity = getRevisionsEntity()
    elif myarg == 'previewdelete':
      previewDelete = True
    elif myarg == 'showtitles':
      showTitles = True
    elif myarg == 'doit':
      doIt = True
    elif myarg in {'maxtodelete', 'maxtoprocess'}:
      maxToProcess = getInteger(minVal=0)
    else:
      unknownArgumentExit()
  if not revisionsEntity:
    missingArgumentExit('select <DriveFileRevisionIdEntity>')
  i, count, users = getEntityArgument(users)
  for user in users:
    i += 1
    origUser = user
    user, drive, jcount = _validateUserGetFileIDs(user, i, count, fileIdEntity)
    if jcount == 0:
      continue
    j = 0
    for fileId in fileIdEntity['list']:
      j += 1
      fileName = fileId
      entityType = Ent.DRIVE_FILE_OR_FOLDER_ID
      if showTitles:
        fileName, entityType, _ = _getDriveFileNameFromId(drive, fileId)
      revisionIds = _selectRevisionIds(drive, fileId, origUser, user, i, count, j, jcount, revisionsEntity)
      kcount = len(revisionIds)
      if kcount == 0:
        entityNumEntitiesActionNotPerformedWarning([Ent.USER, user, entityType, fileName], Ent.DRIVE_FILE_REVISION, kcount,
                                                   Msg.NO_ENTITIES_MATCHED.format(Ent.Plural(Ent.DRIVE_FILE_REVISION)), j, jcount)
        setSysExitRC(NO_ENTITIES_FOUND_RC)
        continue
      if not previewDelete:
        if maxToProcess and kcount > maxToProcess:
          entityNumEntitiesActionNotPerformedWarning([Ent.USER, user, entityType, fileName], Ent.DRIVE_FILE_REVISION, kcount,
                                                     Msg.COUNT_N_EXCEEDS_MAX_TO_PROCESS_M.format(kcount, Act.ToPerform(), maxToProcess), j, jcount)
          continue
        if not doIt:
          entityNumEntitiesActionNotPerformedWarning([Ent.USER, user, entityType, fileName], Ent.DRIVE_FILE_REVISION, kcount,
                                                     Msg.USE_DOIT_ARGUMENT_TO_PERFORM_ACTION, j, jcount)
          continue
        entityPerformActionNumItems([Ent.USER, user, entityType, fileName], kcount, Ent.DRIVE_FILE_REVISION, j, jcount)
      else:
        entityPerformActionNumItemsModifier([Ent.USER, user, entityType, fileName], kcount, Ent.DRIVE_FILE_REVISION, Msg.PREVIEW_ONLY, j, jcount)
      Ind.Increment()
      k = 0
      for revisionId in revisionIds:
        k += 1
        if not previewDelete:
          try:
            callGAPI(drive.revisions(), 'delete',
                     throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.BAD_REQUEST, GAPI.REVISION_NOT_FOUND, GAPI.REVISION_DELETION_NOT_SUPPORTED,
                                                                   GAPI.CANNOT_DELETE_ONLY_REVISION, GAPI.REVISIONS_NOT_SUPPORTED],
                     fileId=fileId, revisionId=revisionId)
            entityActionPerformed([Ent.USER, user, entityType, fileName, Ent.DRIVE_FILE_REVISION, revisionId], k, kcount)
          except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
                  GAPI.badRequest, GAPI.revisionDeletionNotSupported, GAPI.cannotDeleteOnlyRevision, GAPI.revisionsNotSupported) as e:
            entityActionFailedWarning([Ent.USER, user, entityType, fileName], str(e), j, jcount)
          except GAPI.revisionNotFound:
            entityDoesNotHaveItemWarning([Ent.USER, user, entityType, fileName, Ent.DRIVE_FILE_REVISION, revisionId], k, kcount)
          except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
            userDriveServiceNotEnabledWarning(user, str(e), i, count)
            break
        else:
          entityActionNotPerformedWarning([Ent.USER, user, entityType, fileName, Ent.DRIVE_FILE_REVISION, revisionId], Msg.PREVIEW_ONLY, k, kcount)
      Ind.Decrement()

REVISIONS_FIELDS_CHOICE_MAP = {
  'keepforever': 'keepForever',
  'published': 'published',
  'publishauto': 'publishAuto',
  'publishedoutsidedomain': 'publishedOutsideDomain'
  }
# gam <UserTypeEntity> update filerevisions <DriveFileEntity> select <DriveFileRevisionIdEntity> [previewupdate]
#	[published [<Boolean>]] [publishauto [<Boolean>]] [publishedoutsidedomain [<Boolean>]]
#	[keepforever [<Boolean>]}
#	[showtitles] [doit] [max_to_update <Number>]
def updateFileRevisions(users):
  fileIdEntity = getDriveFileEntity()
  revisionsEntity = None
  previewUpdate = showTitles = doIt = False
  maxToProcess = 1
  body = {}
  while Cmd.ArgumentsRemaining():
    myarg = getArgument()
    if myarg == 'select':
      revisionsEntity = getRevisionsEntity()
    elif myarg in REVISIONS_FIELDS_CHOICE_MAP:
      body[REVISIONS_FIELDS_CHOICE_MAP[myarg]] = getBoolean()
    elif myarg == 'previewupdate':
      previewUpdate = True
    elif myarg == 'showtitles':
      showTitles = True
    elif myarg == 'doit':
      doIt = True
    elif myarg in {'maxtoupdate', 'maxtoprocess'}:
      maxToProcess = getInteger(minVal=0)
    else:
      unknownArgumentExit()
  if not revisionsEntity:
    missingArgumentExit('select <DriveFileRevisionIdEntity>')
  i, count, users = getEntityArgument(users)
  for user in users:
    i += 1
    origUser = user
    user, drive, jcount = _validateUserGetFileIDs(user, i, count, fileIdEntity)
    if jcount == 0:
      continue
    j = 0
    for fileId in fileIdEntity['list']:
      j += 1
      fileName = fileId
      entityType = Ent.DRIVE_FILE_OR_FOLDER_ID
      if showTitles:
        fileName, entityType, _ = _getDriveFileNameFromId(drive, fileId)
      revisionIds = _selectRevisionIds(drive, fileId, origUser, user, i, count, j, jcount, revisionsEntity)
      kcount = len(revisionIds)
      if kcount == 0:
        entityNumEntitiesActionNotPerformedWarning([Ent.USER, user, entityType, fileName], Ent.DRIVE_FILE_REVISION, kcount,
                                                   Msg.NO_ENTITIES_MATCHED.format(Ent.Plural(Ent.DRIVE_FILE_REVISION)), j, jcount)
        setSysExitRC(NO_ENTITIES_FOUND_RC)
        continue
      if not previewUpdate:
        if maxToProcess and kcount > maxToProcess:
          entityNumEntitiesActionNotPerformedWarning([Ent.USER, user, entityType, fileName], Ent.DRIVE_FILE_REVISION, kcount,
                                                     Msg.COUNT_N_EXCEEDS_MAX_TO_PROCESS_M.format(kcount, Act.ToPerform(), maxToProcess), j, jcount)
          continue
        if not doIt:
          entityNumEntitiesActionNotPerformedWarning([Ent.USER, user, entityType, fileName], Ent.DRIVE_FILE_REVISION, kcount,
                                                     Msg.USE_DOIT_ARGUMENT_TO_PERFORM_ACTION, j, jcount)
          continue
        entityPerformActionNumItems([Ent.USER, user, entityType, fileName], kcount, Ent.DRIVE_FILE_REVISION, j, jcount)
      else:
        entityPerformActionNumItemsModifier([Ent.USER, user, entityType, fileName], kcount, Ent.DRIVE_FILE_REVISION, Msg.PREVIEW_ONLY, j, jcount)
      Ind.Increment()
      k = 0
      for revisionId in revisionIds:
        k += 1
        if not previewUpdate:
          try:
            callGAPI(drive.revisions(), 'update',
                     throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.BAD_REQUEST, GAPI.REVISION_NOT_FOUND, GAPI.REVISIONS_NOT_SUPPORTED],
                     fileId=fileId, revisionId=revisionId, body=body)
            entityActionPerformed([Ent.USER, user, entityType, fileName, Ent.DRIVE_FILE_REVISION, revisionId], k, kcount)
          except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
                  GAPI.badRequest, GAPI.revisionsNotSupported) as e:
            entityActionFailedWarning([Ent.USER, user, entityType, fileName], str(e), j, jcount)
          except GAPI.revisionNotFound:
            entityDoesNotHaveItemWarning([Ent.USER, user, entityType, fileName, Ent.DRIVE_FILE_REVISION, revisionId], k, kcount)
          except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
            userDriveServiceNotEnabledWarning(user, str(e), i, count)
            break
        else:
          entityActionNotPerformedWarning([Ent.USER, user, entityType, fileName, Ent.DRIVE_FILE_REVISION, revisionId], Msg.PREVIEW_ONLY, k, kcount)
      Ind.Decrement()

def _selectRevisionResults(results, fileId, origUser, revisionsEntity, previewDelete):
  numRevisions = len(results)
  if numRevisions == 0:
    return results
  if revisionsEntity['count']:
    countType = revisionsEntity['count'][0]
    count = revisionsEntity['count'][1]
    if countType == 'first':
      if count >= numRevisions:
        if previewDelete:
          return results[:-1]
        return results
      return results[:count]
    if countType == 'last':
      if count >= numRevisions:
        if previewDelete:
          return results[1:]
        return results
      return results[-count:]
    if countType == 'allexceptfirst':
      if count >= numRevisions:
        return []
      return results[count:]
# count: allexceptlast
    if count >= numRevisions:
      return []
    return results[:-count]
  if revisionsEntity['time']:
    dateTime = revisionsEntity['time'][1]
    count = 0
    if revisionsEntity['time'][0] == 'before':
      for revision in results:
        modifiedDateTime = arrow.get(revision['modifiedTime'])
        if modifiedDateTime >= dateTime:
          break
        count += 1
      if count >= numRevisions:
        if previewDelete:
          return results[:-1]
        return results
      return results[:count]
# time: after
    for revision in results:
      modifiedDateTime = arrow.get(revision['modifiedTime'])
      if modifiedDateTime >= dateTime:
        break
      count += 1
    if count == 0:
      if previewDelete:
        return results[1:]
      return results
    if count >= numRevisions:
      return []
    return results[count:]
  if revisionsEntity['range']:
    startDateTime = revisionsEntity['range'][1]
    endDateTime = revisionsEntity['range'][2]
    count = 0
    selectedResults = []
    for revision in  results:
      modifiedDateTime = arrow.get(revision['modifiedTime'])
      if modifiedDateTime >= startDateTime:
        if modifiedDateTime >= endDateTime:
          break
        selectedResults.append(revision)
        count += 1
    if count >= numRevisions:
      if previewDelete:
        return selectedResults[1:]
    return selectedResults
# revisionsIds
  selectedResults = []
  if revisionsEntity['dict']:
    if not GM.Globals[GM.CSV_SUBKEY_FIELD]:
      revisionIds = revisionsEntity['dict'][fileId]
    else:
      revisionIds = revisionsEntity['dict'][origUser][fileId]
  else:
    revisionIds = revisionsEntity['list']
  return [revision for revision in results if revision['id'] in revisionIds]

FILEREVISIONS_FIELDS_CHOICE_MAP = {
  'filesize': 'size',
  'id': 'id',
  'keepforever': 'keepForever',
  'lastmodifyinguser': 'lastModifyingUser',
  'lastmodifyingusername': 'lastModifyingUser.displayName',
  'md5checksum': 'md5Checksum',
  'mimetype': 'mimeType',
  'modifieddate': 'modifiedTime',
  'modifiedtime': 'modifiedTime',
  'originalfilename': 'originalFilename',
  'pinned': 'keepForever',
  'published': 'published',
  'publishauto': 'publishAuto',
  'publishedoutsidedomain': 'publishedOutsideDomain',
  'size': 'size',
  }

FILEREVISIONS_TIME_OBJECTS = {'modifiedTime'}

def _showRevision(revision, i=0, count=0):
  printEntity([Ent.DRIVE_FILE_REVISION, revision['id']], i, count)
  Ind.Increment()
  showJSON(None, revision, ['id'], timeObjects=FILEREVISIONS_TIME_OBJECTS)
  Ind.Decrement()

DRIVE_REVISIONS_INDEXED_TITLES = ['revisions']

# gam <UserTypeEntity> show filerevisions <DriveFileEntity>
#	[select <DriveFileRevisionIDEntity>]
#	[previewdelete] [showtitles]
#	[<RevisionsFieldName>*|(fields <RevisionsFieldNameList>)]
#	(orderby <DriveFileOrderByFieldName> [ascending|descending])*
#	[stripcrsfromname]
# gam <UserTypeEntity> print filerevisions <DriveFileEntity> [todrive <ToDriveAttribute>*]
#	[select <DriveFileRevisionIDEntity>]
#	[previewdelete] [showtitles] [oneitemperrow]
#	[<RevisionsFieldName>*|(fields <RevisionsFieldNameList>)]
#	(orderby <DriveFileOrderByFieldName> [ascending|descending])*
#	[stripcrsfromname]
def printShowFileRevisions(users):
  csvPF = CSVPrintFile(['Owner', 'id']) if Act.csvFormat() else None
  fieldsList = []
  fileIdEntity = getDriveFileEntity()
  revisionsEntity = None
  oneItemPerRow = previewDelete = showTitles = stripCRsFromName = False
  OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
  while Cmd.ArgumentsRemaining():
    myarg = getArgument()
    if csvPF and myarg == 'todrive':
      csvPF.GetTodriveParameters()
    elif myarg == 'select':
      revisionsEntity = getRevisionsEntity()
    elif csvPF and myarg == 'oneitemperrow':
      oneItemPerRow = True
      if csvPF:
        csvPF.AddTitles('revision.id')
    elif myarg == 'orderby':
      OBY.GetChoice()
    elif myarg == 'previewdelete':
      previewDelete = True
    elif myarg == 'showtitles':
      showTitles = True
      if csvPF:
        csvPF.AddTitles('name')
    elif myarg == 'stripcrsfromname':
      stripCRsFromName = True
    elif getFieldsList(myarg, FILEREVISIONS_FIELDS_CHOICE_MAP, fieldsList, initialField='id'):
      pass
    else:
      unknownArgumentExit()
  if fieldsList:
    fields = getItemFieldsFromFieldsList('revisions', fieldsList)
  else:
    fields = '*'
  i, count, users = getEntityArgument(users)
  for user in users:
    i += 1
    origUser = user
    user, drive, jcount = _validateUserGetFileIDs(user, i, count, fileIdEntity,
                                                  entityType=[Ent.DRIVE_FILE_OR_FOLDER, None][csvPF is not None],
                                                  orderBy=OBY.orderBy)
    if jcount == 0:
      continue
    Ind.Increment()
    j = 0
    for fileId in fileIdEntity['list']:
      j += 1
      fileName = fileId
      entityType = Ent.DRIVE_FILE_OR_FOLDER_ID
      if showTitles:
        fileName, entityType, _ = _getDriveFileNameFromId(drive, fileId, not csvPF)
        if stripCRsFromName:
          fileName = _stripControlCharsFromName(fileName)
      try:
        results = callGAPIpages(drive.revisions(), 'list', 'revisions',
                                throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.BAD_REQUEST, GAPI.REVISIONS_NOT_SUPPORTED],
                                fileId=fileId, fields=fields, pageSize=GC.Values[GC.DRIVE_MAX_RESULTS])
      except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
              GAPI.badRequest, GAPI.revisionsNotSupported) as e:
        entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER_ID, fileId], str(e), j, jcount)
        continue
      except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
        userDriveServiceNotEnabledWarning(user, str(e), i, count)
        break
      if revisionsEntity:
        results = _selectRevisionResults(results, fileId, origUser, revisionsEntity, previewDelete)
      if not csvPF:
        kcount = len(results)
        entityPerformActionNumItems([entityType, fileName], kcount, Ent.DRIVE_FILE_REVISION, j, jcount)
        Ind.Increment()
        k = 0
        for revision in results:
          k += 1
          _showRevision(revision, k, kcount)
        Ind.Decrement()
      elif results:
        if oneItemPerRow:
          for revision in results:
            row = {'Owner': user, 'id': fileId}
            if showTitles:
              row['name'] = fileName
            csvPF.WriteRowTitles(flattenJSON({'revision': revision}, flattened=row, timeObjects=FILEREVISIONS_TIME_OBJECTS))
        else:
          if showTitles:
            csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId, 'name': fileName}, timeObjects=FILEREVISIONS_TIME_OBJECTS))
          else:
            csvPF.WriteRowTitles(flattenJSON({'revisions': results}, flattened={'Owner': user, 'id': fileId}, timeObjects=FILEREVISIONS_TIME_OBJECTS))
    Ind.Decrement()
  if csvPF:
    if oneItemPerRow:
      csvPF.SetSortTitles(['Owner', 'id', 'name', 'revision.id'])
    else:
      csvPF.SetSortTitles(['Owner', 'id', 'revisions'])
      csvPF.SetIndexedTitles(DRIVE_REVISIONS_INDEXED_TITLES)
    csvPF.writeCSVfile('Drive File Revisions')

def _stripMeInOwners(query):
  if not query:
    return query
  query = query.replace(ME_IN_OWNERS_AND, '')
  query = query.replace(AND_ME_IN_OWNERS, '')
  return query.replace(ME_IN_OWNERS, '').strip()

def _stripNotMeInOwners(query):
  if not query:
    return query
  query = query.replace(NOT_ME_IN_OWNERS_AND, '')
  query = query.replace(AND_NOT_ME_IN_OWNERS, '')
  return query.replace(NOT_ME_IN_OWNERS, '').strip()

def _updateAnyOwnerQuery(query):
  query = _stripNotMeInOwners(query)
  return _stripMeInOwners(query)

