"""Provide the class IdxItem which represents an item in the index.
"""

import os.path
import hashlib
from photo.exif import Exif
from photo.geo import GeoPosition


def _checksum(fname, hashalg):
    """Calculate hashes for a file.
    """
    if not hashalg:
        return {}
    m = { h:hashlib.new(h) for h in hashalg }
    chunksize = 8192
    with open(fname, 'rb') as f:
        while True:
            chunk = f.read(chunksize)
            if not chunk:
                break
            for h in hashalg:
                m[h].update(chunk)
    return { h: m[h].hexdigest() for h in hashalg }


class IdxItem(object):

    def __init__(self, data=None, filename=None, basedir=None, hashalg=['md5']):
        self.filename = None
        self.tags = []
        if data is not None:
            # Compatibility with legacy index file formats.
            if 'md5' in data:
                data['checksum'] = {'md5': data['md5']}
                del data['md5']
            if 'createdate' in data:
                data['createDate'] = data['createdate']
                del data['createdate']
            self.__dict__.update(data)
        elif filename is not None:
            self.filename = filename
            if basedir is not None:
                filename = os.path.join(basedir, filename)
            self.checksum = _checksum(filename, hashalg)
            exifdata = Exif(filename)
            self.createDate = exifdata.createDate
            self.orientation = exifdata.orientation
            self.gpsPosition = exifdata.gpsPosition
        if self.gpsPosition:
            self.gpsPosition = GeoPosition(self.gpsPosition)
        self.tags = set(self.tags)

    def as_dict(self):
        d = self.__dict__.copy()
        d['tags'] = list(d['tags'])
        d['tags'].sort()
        if d['gpsPosition']:
            d['gpsPosition'] = d['gpsPosition'].as_dict()
        return d

@@ -715,60 +715,141 @@
     
-self.filename = None%0A        self.tags = %5B%5D%0A
+if data is not None:%0A            self.filename = data.get('filename')%0A            self.checksum = data.get('checksum', %7B%7D)%0A  
         
 if d
@@ -848,68 +848,79 @@
     
+  
 if 
-data is not None:%0A            # Compatibility with
+not self.checksum and 'md5' in data:%0A                #
  legacy
+: old
  ind
@@ -937,40 +937,82 @@
 rmat
-s.%0A            if 'md5' in data:
+ used to have a 'md5'%0A                # attribute, rather then 'checksum'.
 %0A   
@@ -1028,22 +1028,21 @@
     
-data%5B'
+self.
 checksum
 '%5D =
@@ -1041,20 +1041,17 @@
 ksum
-'%5D = %7B
+%5B
 'md5'
-:
+%5D =
  dat
@@ -1058,19 +1058,17 @@
 a%5B'md5'%5D
-%7D%0A 
+%0A
         
@@ -1075,41 +1075,91 @@
     
-   del data%5B'md5'%5D%0A            if
+self.createDate = data.get('createDate')%0A            if self.createDate is None and
  'cr
@@ -1193,21 +1193,26 @@
         
-data%5B
+# legacy: 
 'createD
@@ -1215,25 +1215,28 @@
 ateDate'
-%5D = data%5B
+ used to be 
 'created
@@ -1231,33 +1231,39 @@
  be 'createdate'
-%5D
+ in old
 %0A               
@@ -1267,68 +1267,240 @@
     
-del data%5B'createdate'%5D%0A            self.__dict__.update(data
+# index file format.%0A                self.createDate = data%5B'createdate'%5D%0A            self.orientation = data.get('orientation')%0A            self.gpsPosition = data.get('gpsPosition')%0A            self.tags = set(data.get('tags', %5B%5D)
 )%0A  
@@ -1909,24 +1909,54 @@
 gpsPosition%0A
+            self.tags = set()%0A
         if s
@@ -2037,144 +2037,269 @@
 on)%0A
+%0A
     
-    self.tags = set(self.tags)%0A%0A    def as_dict(self):%0A        d = self.__dict__.copy()%0A        d%5B'tags'%5D = list(d%5B'tags'%5D)%0A
+def as_dict(self):%0A        d = %7B%0A            'filename': self.filename,%0A            'checksum': self.checksum,%0A            'createDate': self.createDate,%0A            'orientation': self.orientation,%0A            'gpsPosition': self.gpsPosition,%0A    
         
 d%5B't
@@ -2298,24 +2298,44 @@
     
-d%5B
 'tags'
-%5D.
+: 
 sort
-()
+ed(self.tags),%0A        %7D
 %0A   

Set each attribute explicitely when initializing an IdxItem from data.