#!/usr/local/bin/python2.7
# -*- coding: utf-8 -*-


import json, sys, os, shutil

from optparse import OptionParser
from glob import glob

def convert_ini_files():
    from puddlestuff.constants import CONFIGDIR, SAVEDIR
    
    config_files = [
        'puddletag.conf', 'combos', 
        'gensettings', 'menus', 'shortcuts', 
        'tagpanel', 'tagsources.conf',
        'function_settings', 'user_shortcuts', 'view_all_fields',
    ]

    data_files = glob(os.path.join(SAVEDIR, 'actions/*')) + \
        glob(os.path.join(SAVEDIR, 'masstagging/*'))

    files = [os.path.join(CONFIGDIR, fn) for fn in config_files] + data_files

    for fn in files:
        if os.path.exists(fn):
            settings_to_json(fn)

def settings_to_json(filename):
    data = open(filename, 'r').read()

    try:
        json.loads(data)
        return #Valid json so already converted.
    except:
        pass

    try:
        config_data = json.dumps(dict(ConfigObj(filename)), indent=2)
        fo = open(filename, 'w')
        fo.write(config_data)
        fo.close()
    except:
        pass

def _migrate_action_shortcut_filenames():
    from puddlestuff.constants import SAVEDIR, ACTIONDIR
    filename = os.path.join(ACTIONDIR, 'action_shortcuts')
    if not os.path.exists(filename):
        return
    with open(filename, 'r') as fo:
        data = json.loads(fo.read());
    
    old_dir = os.path.join(os.getenv('HOME'), '.puddletag', 'actions')
    for key, shortcut in data.iteritems():
        shortcut['filenames'] = [z.replace(old_dir, ACTIONDIR) for z in shortcut['filenames']]

    with open(filename, 'w') as fo:
        fo.write(json.dumps(data, indent=2))

def migrate_settings():
    from puddlestuff.constants import CONFIGDIR, SAVEDIR
    for dirpath in [CONFIGDIR, SAVEDIR]:
        if not os.path.exists(dirpath):
            os.makedirs(dirpath)

    old_dir = os.path.join(os.getenv('HOME'), '.puddletag')
    if (os.path.exists(old_dir)):
        dirnames = [
            'plugins', 'actions', 'masstagging', 'mp3tag_sources', 'translations']
        
        for dirname in dirnames:
            src = os.path.join(old_dir, dirname)
            dest = os.path.join(SAVEDIR, dirname)
            if os.path.exists(src) and not os.path.exists(dest):
                os.rename(src, os.path.join(SAVEDIR, dirname))

        for filename in os.listdir(old_dir):
            dest = os.path.join(CONFIGDIR, filename)
            if (not os.path.exists(dest)):
                src = os.path.join(old_dir, filename)
                shutil.move(src, dest)

        shutil.rmtree(old_dir)

    _migrate_action_shortcuts()
    convert_ini_files()
    _migrate_action_shortcut_filenames()

def _migrate_action_shortcuts():
    from puddlestuff.constants import SAVEDIR, ACTIONDIR
    from puddlestuff.puddleobjects import PuddleConfig
    filename = os.path.join(SAVEDIR, 'actions', 'action_shortcuts')

    if not os.path.exists(filename):
        return
        
    try:
        cparser = PuddleConfig(filename)
    except:
        # Already converted to json. Nothing to do.
        return None

    for section in sorted(cparser.sections()):
        if section.startswith('Shortcut'):
            filenames = []
            for filename in cparser.get(section, 'filenames', []):
                filenames.append(os.path.join(ACTIONDIR, os.path.basename(filename)))
            cparser.set(section, 'filenames', filenames)

def check_libs():
    """Check for required libs.

    If some not found, show/print a message.
    Exit if requirements aren't met."""
    _libs = [('mutagen', '(usually python-mutagen or just mutagen)',
            'http://code.google.com/p/mutagen/'),
         ('configobj', '(usually python-configobj)',
            'http://code.google.com/p/configobj/'),
         ('pyparsing', '(python-pyparsing or python-parsing in most distros)',
            'http://pyparsing.wikispaces.com/'),
         ('PyQt4', '(python-qt4 usually)',
            'http://www.riverbankcomputing.co.uk/software/pyqt/intro')]

    found = True
    errors = []
    msg = "Error: The %s module wasn't found. Please check that it's installed " \
            "properly. Download it from your distro's repository" \
            " %s or directly from %s \n"
    for lib in _libs:
        try:
            __import__(lib[0])
        except ImportError:
            print (msg % lib)
            errors.append(msg % lib)
            found = False

    msg = "Error: %s module wasn't found. %s. Please check that it's " \
        "installed properly. You can download it from your distro's " \
        "repository (%s), or download directly from %s.\n"

    try:
        if not found:
            from PyQt4.QtGui import QApplication, QMessageBox
            app = QApplication([])
            QMessageBox.critical(None, 'puddletag', '\n'.join(errors))
    except:
        pass
    
    if not found:
        sys.exit(1)

def create_log():
    """Creates a log file. Redirects sys.stderr sys.stdout output to it."""
    join = os.path.join
    rename = os.rename
    exists = os.path.exists

    from puddlestuff.constants import SAVEDIR
    if not os.path.exists(SAVEDIR):
        os.mkdir(SAVEDIR)

    for i in reversed(range(1, 5)):
        filename = join(SAVEDIR, 'log%d.log' % i)
        if exists(filename):
            rename(filename, join(SAVEDIR, 'log%d.log' % (i + 1)))

    log_file = join(SAVEDIR, 'log.log')
    if exists(log_file):
        rename(log_file, join(SAVEDIR, 'log1.log'))

    f = open(log_file, 'w')
    sys.stdout = StdOut(sys.stdout.write, f.write)
    sys.stderr = StdOut(sys.stderr.write, f.write)

def init(options, qapp):
    """Initializes things that need to be initialized.

    Parses command line options. Loads Translations. Sets fontsize."""

    if options.version:
        #It's already printed.
        exit()

    #create_log()
    if options.debug:        
        logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)

    load_language(qapp, options.langfile)

    if options.fontsize:
        try:
            size = int(options.fontsize)
            font = qapp.font()
            font.setPointSize(size)
            app.setFont(font)
        except IndexError:
            print 'No fontsize specified.'
        except ValueError:
            print 'Invalid fontsize specified.'

def load_language(qapp, langfile=None):
    """Loads the language file to be used by puddletag.

    app => QApplication object.
    langfile => If None, then the last option the user chose will be used.
                Should be a path to a Qt translation file (.qm)."""
    TRANSDIR = puddlestuff.constants.TRANSDIR

    global translators #Needs to live throughout app.
    translators = []

    if langfile:
        if not langfile.endswith('.qm'):
            print translate('Defaults', 'Invalid translation file.')
            langargs = None
        else:
            langargs = os.path.basename(langfile), os.path.dirname(langfile)
    else:
        langargs = None

    if not langargs:
        cparser = PuddleConfig()
        lang = cparser.get('main', 'lang', u'auto')
        langs = get_languages([TRANSDIR])

        if lang != 'auto':
            if lang in langs:
                f = langs[lang]
                langargs = os.path.basename(f), os.path.dirname(f)

        if not langargs and lang != 'default':
            locale = unicode(QLocale.system().name())
            if locale in langs:
                f = langs[locale]
                langargs = os.path.basename(f), os.path.dirname(f)

    if langargs and langargs != 'default':
        translator = QTranslator()
        translator.load("qt_" + QLocale.system().name(),
             QLibraryInfo.location(QLibraryInfo.TranslationsPath))
        translators.append(translator)

        if 'puddletag_' in langargs[0]:
            translator = QTranslator()
            locale = langargs[0][len('puddletag_'):-len('.qm')]
            translator.load("qt_" + locale,
                QLibraryInfo.location(QLibraryInfo.TranslationsPath))
            print "Locale: " + locale
            translators.append(translator)

        translator = QTranslator()
        if translator.load(*langargs):
            translators.append(translator)

    elif langargs != 'default':
        translator = QTranslator()
        translator.load("qt_" + QLocale.system().name(),
             QLibraryInfo.location(QLibraryInfo.TranslationsPath))
        print "Locale: " + unicode(QLocale.system().name())
        translators.append(translator)

    else:
        print "Loading default (ie. no) translation."

    for t in reversed(translators):
        qapp.installTranslator(t)
    puddlestuff.constants.trans_strings()
    puddlestuff.puddleobjects.trans_imagetypes()

def parse_cmd_options():
    usage = "Usage: %prog [options] [directory path]"
    parser = OptionParser(usage=usage)
    
    parser.add_option("--langfile", dest="langfile",
        default='',
        help="Path to a translation (.qm) file.", metavar="LANGFILE")
    parser.add_option("--fontsize", type='float',
        dest="fontsize", help="Default fontsize to use (in points).")
    parser.add_option("-d", "--debug", action="store_true",
        dest="debug", default=False, help="Show (useless) debug messages.")
    parser.add_option("-v", "--version", action="store_true",
        dest="version", default=False, help="Show version info and exit.")

    return parser.parse_args()

def print_info():
    """Print program info."""
    from puddlestuff import version_string, changeset
    if changeset:
        print translate('Defaults', 'puddletag Version: %1, Changeset: %2').arg(
            version_string).arg(changeset)
    else:
        print translate('Defaults', 'puddletag Version: %s' % version_string)

class StdOut(object):
    """Class to redirect stdout/in/err."""
    def __init__(self, old_write, new_write):
        """old_write should be the original sys.stdout.out
        new_write is a function is what sys.stdout.out will be replaced with.

        Text will be passed to both functions."""
        self._old_write = old_write
        self._new_write = new_write

    def write(self, text):

        self._old_write(text)
        try:
            self._new_write(text)
        except:
            pass


if __name__ == '__main__':
    check_libs()
    from PyQt4.QtGui import QApplication, QPixmap, QSplashScreen, QIcon
    from PyQt4.QtCore import (pyqtRemoveInputHook, QTranslator,
        QLibraryInfo, QLocale)
    import pdb, logging
    from configobj import ConfigObj
    pyqtRemoveInputHook()

    #Load puddletag modules.
    from puddlestuff import resource #Needs to be first as other modules use it.
    import puddlestuff.constants

    migrate_settings()
    from puddlestuff.puddleobjects import get_languages, PuddleConfig
    from puddlestuff.translations import translate

    #Init.
    print_info()
    app = QApplication(sys.argv)
    options, filenames = parse_cmd_options()
    init(options, app)

    #Depends on init being called first.
    from puddlestuff.puddletag import MainWin
    from puddlestuff.puddlesettings import load_gen_settings

    app.setWindowIcon(QIcon(":/appicon.png"))
    pixmap = QPixmap(':/puddlelogo.png')
    app.setOrganizationName("Puddle Inc.")
    app.setApplicationName("puddletag")

    splash = QSplashScreen(pixmap)
    splash.show()
    app.processEvents()
    win = MainWin()
    splash.close()
    win.setVisible(True)
    app.processEvents()

    #Check if dirnames passed on command line.
    if filenames:
        dirname = filenames[0]
        if dirname and os.path.exists(dirname):
            win.openDir(dirname, False)
    elif load_gen_settings([('&Load last folder at startup', False)])[0][1]:
        if win._lastdir and os.path.exists(win._lastdir[0]):
            win.openDir(win._lastdir[0], False)
    app.exec_()