from hachoir_metadata.qt.dialog_ui import Ui_Form
from PyQt4.QtCore import SIGNAL
from PyQt4.QtCore import Qt
from PyQt4.QtGui import (QApplication, QDialog,
    QTableWidgetItem, QFileDialog, QMessageBox)
from sys import argv, exit
from os.path import basename, dirname
from hachoir_core import config
config.quiet = True

from hachoir_core.error import HACHOIR_ERRORS
from hachoir_core.cmd_line import unicodeFilename
from hachoir_parser import createParser
from hachoir_core.tools import makePrintable
from hachoir_metadata import extractMetadata
from hachoir_metadata.metadata import MultipleMetadata
from hachoir_core.i18n import initLocale, getTerminalCharset
from sys import argv, stderr, exit
from os import walk, getcwd
from os.path import join as path_join
from fnmatch import fnmatch
from datetime import datetime
import codecs

class CustomTableWidgetItem(QTableWidgetItem):
    def __init__(self, parent = None):
        super(CustomTableWidgetItem, self).__init__(parent)
        self.setFlags(Qt.ItemIsSelectable |Qt.ItemIsEnabled)

class MetadataError(Exception):
    def __init__(self, message):
        self.unicode_message = message
        bytes_message = message.encode("ASCII", "replace")
        Exception.__init__(self, bytes_message)

    def __unicode__(self):
        return self.unicode_message

class File:
    def __init__(self, filename, realname):
        self.name = filename
        if realname:
            self.realname = realname
        else:
            self.realname = filename
        try:
            self.parser = createParser(self.name, self.realname)
        except HACHOIR_ERRORS, err:
            raise MetadataError("Parser error: %s" % unicode(err))
        if not self.parser:
            raise MetadataError("Unable to parse the file: %s" % self.name)
        try:
            self.metadata = extractMetadata(self.parser)
        except HACHOIR_ERRORS, err:
            raise MetadataError("Metadata extraction error: %s" % unicode(err))
        if not self.metadata:
            file_type = self.parser.mime_type
            raise MetadataError("Unable to extract metadata from file of type %s" % file_type)

class Metadata(QDialog, Ui_Form):
    def __init__(self, application):
        QDialog.__init__(self)
        self.application = application
        self.files = {}
        self.setupWindow()
        self.current_dir = dirname(getcwd())

    def setupWindow(self):
        self.setupUi(self)
        self.connect(self.open_button, SIGNAL("clicked()"), self.open)
        self.connect(self.quit_button, SIGNAL("clicked()"), self.quit)
        self.connect(
            self.files_combo,
            SIGNAL("currentIndexChanged(const QString&)"),
            self.changeFile)
        self.metadata_table.horizontalHeader().hide()
        self.metadata_table.verticalHeader().hide()

    def open(self):
        filename = QFileDialog.getOpenFileName(
            self, #parent
            "Choose a file to open", #caption
            self.current_dir, #dir name
            "", #filter
            "Any type" #filter set
        )
        if not filename:
            return
        filename = unicode(filename)
        self.current_dir = dirname(filename)
        self.addFile(filename, change=True)

    def quit(self):
        self.application.quit()

    def fillList(self, file):
        table = self.metadata_table
        metadata = file.metadata
        groups = [metadata]
        if isinstance(metadata, MultipleMetadata):
            groups.extend(list(metadata.iterGroups()))
        total = 0
        for index, metadata in enumerate(groups):
            group_name = metadata.header
            metadata = [data for data in metadata if data.values]
            metadata.sort()
            if 0 < index:
                metadata.insert(0, group_name)
            groups[index] = metadata
            total += len(metadata)
        table.clear()
        table.setColumnCount(2)
        table.setRowCount(total)
        row = 0
        for metadata in groups:
            for data in metadata:
                if isinstance(data, (str, unicode)):
                    table.setItem(row, 0, CustomTableWidgetItem("-- group --"))
                    table.setItem(row, 1, CustomTableWidgetItem(data))
                    row += 1
                    continue
                title = data.description
                for item in data.values:
                    value = item.text
                    table.setItem(row, 0, CustomTableWidgetItem(title))
                    table.setItem(row, 1, CustomTableWidgetItem(value))
                    row += 1
        table.resizeColumnsToContents()

    def changeFile(self, name):
        name = unicode(name)
        file = self.files[name]
        self.fillList(file)

    def error(self, message):
        QMessageBox.warning(self, u"Metadata error", message)

    def addFile(self, filename, realname=None, change=False):
        try:
            file = File(filename, realname)
        except MetadataError, err:
            errmsg = unicode(err)
            self.error(errmsg)
            return
        name = basename(file.name)
        self.files[name] = file
        self.files_combo.addItem(name)
        if change:
            index = self.files_combo.count() - 1
            self.files_combo.setCurrentIndex(index)

def main():
    app = QApplication(argv)
    metadata = Metadata(app)
    for filename in argv[1:]:
        realname = filename
        filename = unicodeFilename(filename)
        metadata.addFile(filename, realname)
    metadata.show()
    exitcode = app.exec_()
    exit(exitcode)

if __name__ == "__main__":
    main()

