#!/usr/bin/env python
# -*- coding: utf-8 -*-

#    Copyright (C) 2008-2010 Ivan Garcia <contact@ivangarcia.org>
#    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 3 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.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import bisect  # not available on S60
import os
import core.modules.utils as utils

try:
    from hashlib import md5
    new_hash = md5
except ImportError:
    # Pre-2.5 Python has no hashlib module.
    import md5
    new_hash = md5.new

import traceback

def getDictHash(fpath):
    if fpath.endswith('.dict.dz'):
        fpath = fpath.split('.dict.dz',1)[0] + '.ifo'
    elif fpath.endswith('.dct.dz'):
        fpath = fpath.split('.dct.dz',1)[0] + '.ifo'
    elif fpath.endswith('.idx'):
        fpath = fpath.split('.idx',1)[0] + '.ifo'
#    elif fpath.endswith('.ifo'):
#        fpath = fpath.rstrip('.ifo')
    return new_hash(open(fpath,mode='rb').read()).hexdigest()

class DictFormatError(Exception):
     def __init__(self, value):
         self.value = value
     def __str__(self):
         return repr(self.value)

class DictionaryType(object):
    """ Main Dictionary Class """

    def __init__(self, dictionary=None):
        """Initialize variables and load dictionary if requested"""
        self.__keys = []
        self.__dict = {}
        self.encoding = 'UTF-8'
        self.version = 'unknown'
        self.__filepath = None
        self.__hash = None

        if dictionary is not None:
            if isinstance(dictionary, DictionaryType):
                self.__dict = dictionary.__dict.copy()
                self.__keys = dictionary.__keys[:]
            elif isinstance(dictionary, str) or isinstance(dictionary, unicode):
                #if os.path.isfile(dictionary):
                #if it points to a file, determine which format is encoded and load that file using the specific Dictionary subclass
                #print "Loading %s" % dictionary
                self.__filepath = dictionary
                self.load(self.__filepath)

                try:
                        self.__hash = new_hash(file(self.__filepath,mode='rb').read()).hexdigest()
                except:
                    traceback.print_exc()
                    pass
            else:
                self.__dict = dict(dictionary).copy()
                self.__keys = sorted(self.__dict.keys())

    def getAt(self, index):
        try:
                return self[self.keys()[index]]
        except IndexError:
                return None
        except Exception, e:
                traceback.print_exc()

    def setAt(self, index,  value):
        self[self.keys()[index]] = value

    def __getitem__(self, key):
        if isinstance(key, int):
            word = self.__dict.keys()[key]
            n_key = self.__keys[key]
            return (n_key, self.__dict[n_key])
        return (key, self.__dict[key])

    def __setitem__(self, key, value):
        if key not in self.__dict:
            bisect.insort_left(self.__keys, key)
        self.__dict[key] = value

    def __delitem__(self, key):
        i = bisect.bisect_left(self.__keys, key)
        del self.__keys[i]
        del self.__dict[key]

    def get(self, key, value=None):
        return self.__dict.get(key, value)

    def setdefault(self, key, value):
        if key not in self.__dict:
            bisect.insort_left(self.__keys, key)
        return self.__dict.setdefault(key, value)

    def pop(self, key, value=None):
        if key not in self.__dict:
            return value
        i = bisect.bisect_left(self.__keys, key)
        del self.__keys[i]
        return self.__dict.pop(key, value)

    def popitem(self):
        item = self.__dict.popitem()
        i = bisect.bisect_left(self.__keys, item[0])
        del self.__keys[i]
        return item

    def has_key(self, key):
        return key in self.__dict

    def __contains__(self, key):
        return key in self.__dict

    def __len__(self):
        return len(self.__dict)

    def keys(self):
        return self.__keys

    def values(self):
        return [self.__dict[key] for key in self.__keys]

    def items(self):
        return [(key, self.__dict[key]) for key in self.__keys]

    def __iter__(self):
        return iter(self.__keys)

    def iterkeys(self):
        return iter(self.__keys)

    def itervalues(self):
        for key in self.__keys:
            yield self.__dict[key]

    def iteritems(self):
        for key in self.__keys:
            yield key, self.__dict[key]

    def copy(self):
            dictionary = DictionaryType()
            dictionary.__keys = self.__keys[:]
            dictionary.__dict = self.__dict.copy()
            return dictionary

    def clear(self):
            self.__keys = []
            self.__dict = {}

    def getVersion(self):
        return self.version

    def getName(self):
        return self.getFileName()

    def getHash(self):
        return self.__hash

    def getFileName(self):
        return os.path.basename(self.__filepath)

    def getFilePath(self):
        return self.__filepath

    def setFilePath(self, filepath):
        self.__filepath = filepath

    def getUniqueId(self):
        return self.getHash()

    def save(self, filePath):
        pass

    def getWords(self):
        return self.__keys

    def getTypeStr(self):
        return ""

class Definition(object):

    def __init__(self, content, comments=None, encoding="utf-8"):
#        print "%r, %r" % (content, type(content))
        try:
            self.__content = content.decode(encoding)
        except:
            self.__content = content
#        print "%r, %r" % (self.__content, type(self.__content))
        self.__comments = comments

    def __repr__(self):
        return "Definition <(%r, %r)>"% (self.__content, self.__comments)

    def content(self):
        return self.__content

    def comments(self):
        return self.__comments
