#!/usr/bin/python
# -*- coding: utf-8 -*-
# ===========================================================================
# eXe
# Copyright 2011-2012, Pedro Peña Pérez
#
# 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 2 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 os
import sys
import optparse
import json
import logging

# Make it so we can import our own nevow and twisted etc.
if os.name == 'posix':
    sys.path.insert(0, '/usr/share/exe')

# Try to work even with no python path
try:
    from exe.application import Application
except ImportError, error:
    if str(error) == "No module named exe.application":
        exePath = os.path.abspath(sys.argv[0])
        exeDir = os.path.dirname(exePath)
        pythonPath = os.path.split(exeDir)[0]
        sys.path.insert(0, pythonPath)
        from exe.application import Application
    else:
        import traceback
        traceback.print_exc()
        sys.exit(1)
from exe.export.cmdlineexporter import CmdlineExporter
from exe.importers.cmdlineimporter import CmdlineImporter
from exe.engine.package import Package
from exe.engine.path import Path, TempDirPath


class CustomHelpFormatter(optparse.IndentedHelpFormatter):
    def format_usage(self, usage):
        return usage


class CustomOptionParser(optparse.OptionParser):
    def set_usage(self, usage):
        self.usage = usage

    def print_help(self, f=None):
        if f is None:
            f = sys.stdout
        f.write(self.format_help())


def prepareParser():
    usage = _(u"%prog, the commandline version of eXe.\n\
Usage: %prog [options] input_file [output_file]\n\nTo show \
help:\n%prog -h").encode(sys.stdout.encoding)
    parser = CustomOptionParser(usage=usage, formatter=CustomHelpFormatter())

    parser.add_option("-s", "--set",
                      action="store", type='string', dest='set_options', metavar='field=value,<field=value>...',
                      help=_(u"Set ELP field values. Example: -s style=Default,root.title='Root Node'").encode(sys.stdout.encoding))

    group = optparse.OptionGroup(parser,
                     _(u"Set ELP field values options").encode(sys.stdout.encoding),
                     _(u"Once you have chosen Set ELP field values option using '-s <values>' or \
    '--set <values>', it's possible to configure the following options:").encode(sys.stdout.encoding))

    group.add_option("-w", "--write_package",
                    action="store_true", dest="set_options_write",
                    help=_(u"Write field values to ELP").encode(sys.stdout.encoding))

    parser.add_option_group(group)

    parser.add_option("-r", "--report",
                      action="store_true", dest='report',
                      help=_(u"Generates resource info report to text <output_file> \
from <input_file> elp package").encode(sys.stdout.encoding))

    parser.add_option("-l", "--checker_logfile",
                      dest='checker_logfile',
                      metavar='LOGFILE')

    parser.add_option("-x", "--export",
                  action="store", dest="x", metavar="format",
                  choices=['xml', 'scorm12', 'scorm2004',
                           'ims', 'website', 'webzip', 'singlepage',
                           'xliff', 'epub3'],
                  help=_(u"Export <input_file> elp package to optional \
<output_file> on one of the given formats: xml, scorm12, scorm2004, ims, \
website, webzip, singlepage, xliff or epub3.").encode(sys.stdout.encoding))
    parser.add_option("-i", "--import",
                  action="store", dest="i", metavar="format",
                  choices=['xml', 'xliff'],
                  help=_(u"Import to <output_file> elp package, <input_file> \
in one of the given formats: xml or xliff.")\
.encode(sys.stdout.encoding))
    parser.add_option("-f", "--force",
                  action="store_true", dest="f",
                  help=_(u"Force overwrite of <output_file>").encode(sys.stdout.encoding))
    parser.add_option("--editable",
                     action="store_true",
                     dest="editable",
                     help=_(u"Add the required files to generate a export editable by \
eXeLearning").encode(sys.stdout.encoding),
                     default=False)

    group = optparse.OptionGroup(parser,
                        _(u"XLIFF export options").encode(sys.stdout.encoding),
                        _(u"Once you have chosen XLIFF export option using '-x xliff' or \
'--export xliff', it's possible to configure the following export options:").encode(sys.stdout.encoding))
    group.add_option("--no-copy-source",
                     action="store_false",
                     dest="copy",
                     help=_(u"Don't copy source in target").encode(sys.stdout.encoding),
                     default=True)
    group.add_option("--wrap-cdata",
                     action="store_true",
                     dest="wrap",
                     help=_(u"Wrap fields in CDATA").encode(sys.stdout.encoding),
                     default=False)
    parser.add_option_group(group)

    group = optparse.OptionGroup(parser,
                        _(u"XLIFF import options").encode(sys.stdout.encoding),
                        _(u"Once you have chosen XLIFF import option using  '-i xliff' \
or '--import xliff', it's possible to configure the following import options:").encode(sys.stdout.encoding))
    group.add_option("--from-source",
                     action="store_true",
                     dest="from_source",
                     help=_(u"Import from source language").encode(sys.stdout.encoding),
                     default=False)
    parser.add_option_group(group)

    group = optparse.OptionGroup(parser,
                        _(u"SCORM export options").encode(sys.stdout.encoding),
                        _(u"Once you have chosen one SCORM export option using '-x scorm12' or \
'-x scorm2004' or 'x agrega', it's possible to configure the following export options:").encode(sys.stdout.encoding))
    group.add_option("--single-page",
                     action="store_true",
                     dest="single",
                     help=_(u"Include Single Page export file").encode(sys.stdout.encoding),
                     default=False)
    group.add_option("--website",
                     action="store_true",
                     dest="website",
                     help=_(u"Include Web Site export files").encode(sys.stdout.encoding),
                     default=False)
    parser.add_option_group(group)

    return parser

if __name__ == "__main__":
    application = Application()
    application.loadConfiguration()
    optparse._ = application.config.locales[application.config.locale].gettext

    parser = prepareParser()
    options, args = parser.parse_args()

    if options.x and options.i:
        parser.error(_(u'Options --export and --import are mutually \
exclusive.').encode(sys.stdout.encoding))
    if not options.x and not options.i and not options.set_options and not options.report:
        parser.error(_(u'No --export, --import, --set or --report option supplied.')\
.encode(sys.stdout.encoding))

    if not args:
        parser.error(_(u'No file input supplied.').encode(sys.stdout.encoding))

    inputf = args[0]
    try:
        outputf = args[1]
    except IndexError:
        outputf = None

    if len(args) > 2:
        parser.error(_(u'Bad number of arguments supplied').encode(sys.stdout.encoding))

    if options.checker_logfile:
        logfile = Path(options.checker_logfile)
        if logfile.abspath().dirname().exists():
            handler = logging.FileHandler(logfile.abspath(), 'a+')
            handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
            logging.getLogger('exe.engine.checker').addHandler(handler)

    tempdir = TempDirPath()
    if options.set_options:
        try:
            path = Path(inputf)
            path.copy(tempdir)
            inputf = tempdir / path.basename()
            pkg = Package.load(inputf)
            if not pkg:
                error = _(u"Invalid input package")
                raise Exception(error.encode(sys.stdout.encoding))
            set_options = options.set_options.split(',')
            for set_option in set_options:
                name, value = set_option.split('=')
                names = name.split('.')
                obj = pkg
                try:
                    value = json.loads(value)
                except:
                    pass
                for name in names[:-1]:
                    obj = getattr(obj, name)
                name = names[-1]
                setattr(obj, name, value)
            pkg.save()
            if options.set_options_write:
                inputf.move(path)
                inputf = path
        except:
            print _(u"exe_do: error: Unable to set values from '%s'.\nThe \
error was:") % (path)
            print sys.exc_value
            exit()

    if options.report:
        options.x = 'report'

    if options.x:
        x = CmdlineExporter(application.config, {"export": options.x,
                                                 "overwrite": options.f,
                                                 "copy-source": options.copy,
                                                 "wrap-cdata": options.wrap,
                                                 "single-page": options.single,
                                                 "website": options.website,
                                                 "editable": options.editable})
        try:
            outputf = x.do_export(inputf, outputf)
            print _(u"Successfully exported '%s' from '%s'.") % (outputf, \
inputf)
        except:
            print _(u"exe_do: error: Unable to export from '%s'.\nThe \
error was:") % (inputf)
            print sys.exc_value
    if options.i:
        i = CmdlineImporter(application.config, {"import": options.i,
                                                 "from-source": options.from_source})
        try:
            outputf = i.do_import(inputf, outputf)
            print _(u"File '%s' successfully imported to '%s'.") % (inputf, \
outputf)
        except:
            print _(u"exe_do: error: Unable to import '%s'.\nThe \
error was:") % (inputf)
            print unicode(sys.exc_value)
