# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import os
import time
import zipfile

from mozbuild.util import lock_file


class ZipFile(zipfile.ZipFile):
  """ Class with methods to open, read, write, close, list zip files.

  Subclassing zipfile.ZipFile to allow for overwriting of existing
  entries, though only for writestr, not for write.
  """
  def __init__(self, file, mode="r", compression=zipfile.ZIP_STORED,
               lock = False):
    if lock:
      assert isinstance(file, basestring)
      self.lockfile = lock_file(file + '.lck')
    else:
      self.lockfile = None

    if mode == 'a' and lock:
      # appending to a file which doesn't exist fails, but we can't check
      # existence util we hold the lock
      if (not os.path.isfile(file)) or os.path.getsize(file) == 0:
        mode = 'w'

    zipfile.ZipFile.__init__(self, file, mode, compression)
    self._remove = []
    self.end = self.fp.tell()
    self.debug = 0

  def writestr(self, zinfo_or_arcname, bytes):
    """Write contents into the archive.

    The contents is the argument 'bytes',  'zinfo_or_arcname' is either
    a ZipInfo instance or the name of the file in the archive.
    This method is overloaded to allow overwriting existing entries.
    """
    if not isinstance(zinfo_or_arcname, zipfile.ZipInfo):
      zinfo = zipfile.ZipInfo(filename=zinfo_or_arcname,
                              date_time=time.localtime(time.time()))
      zinfo.compress_type = self.compression
      # Add some standard UNIX file access permissions (-rw-r--r--).
      zinfo.external_attr = (0x81a4 & 0xFFFF) << 16L
    else:
      zinfo = zinfo_or_arcname

    # Now to the point why we overwrote this in the first place,
    # remember the entry numbers if we already had this entry.
    # Optimizations:
    # If the entry to overwrite is the last one, just reuse that.
    # If we store uncompressed and the new content has the same size
    # as the old, reuse the existing entry.

    doSeek = False # store if we need to seek to the eof after overwriting
    if self.NameToInfo.has_key(zinfo.filename):
      # Find the last ZipInfo with our name.
      # Last, because that's catching multiple overwrites
      i = len(self.filelist)
      while i > 0:
        i -= 1
        if self.filelist[i].filename == zinfo.filename:
          break
      zi = self.filelist[i]
      if ((zinfo.compress_type == zipfile.ZIP_STORED
           and zi.compress_size == len(bytes))
          or (i + 1) == len(self.filelist)):
        # make sure we're allowed to write, otherwise done by writestr below
        self._writecheck(zi)
        # overwrite existing entry
        self.fp.seek(zi.header_offset)
        if (i + 1) == len(self.filelist):
          # this is the last item in the file, just truncate
          self.fp.truncate()
        else:
          # we need to move to the end of the file afterwards again
          doSeek = True
        # unhook the current zipinfo, the writestr of our superclass
        # will add a new one
        self.filelist.pop(i)
        self.NameToInfo.pop(zinfo.filename)
      else:
        # Couldn't optimize, sadly, just remember the old entry for removal
        self._remove.append(self.filelist.pop(i))
    zipfile.ZipFile.writestr(self, zinfo, bytes)
    self.filelist.sort(lambda l, r: cmp(l.header_offset, r.header_offset))
    if doSeek:
      self.fp.seek(self.end)
    self.end = self.fp.tell()

  def close(self):
    """Close the file, and for mode "w" and "a" write the ending
    records.

    Overwritten to compact overwritten entries.
    """
    if not self._remove:
      # we don't have anything special to do, let's just call base
      r = zipfile.ZipFile.close(self)
      self.lockfile = None
      return r

    if self.fp.mode != 'r+b':
      # adjust file mode if we originally just wrote, now we rewrite
      self.fp.close()
      self.fp = open(self.filename, 'r+b')
    all = map(lambda zi: (zi, True), self.filelist) + \
        map(lambda zi: (zi, False), self._remove)
    all.sort(lambda l, r: cmp(l[0].header_offset, r[0].header_offset))
    # empty _remove for multiple closes
    self._remove = []

    lengths = [all[i+1][0].header_offset - all[i][0].header_offset
               for i in xrange(len(all)-1)]
    lengths.append(self.end - all[-1][0].header_offset)
    to_pos = 0
    for (zi, keep), length in zip(all, lengths):
      if not keep:
        continue
      oldoff = zi.header_offset
      # python <= 2.4 has file_offset
      if hasattr(zi, 'file_offset'):
        zi.file_offset = zi.file_offset + to_pos - oldoff
      zi.header_offset = to_pos
      self.fp.seek(oldoff)
      content = self.fp.read(length)
      self.fp.seek(to_pos)
      self.fp.write(content)
      to_pos += length
    self.fp.truncate()
    zipfile.ZipFile.close(self)
    self.lockfile = None
