# Copyright (C) 2009 Canonical Ltd
#
# 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 St, Fifth Floor, Boston, MA 02110-1301  USA

import os, sys, time
from PyQt4 import QtCore, QtGui


# TODO: define this in it's own class once stable
_SCREENSHOTS_SCRIPT = """# command-list
echo generating screenshots
sleep 1
snap-window welcome
#open-location ..
#sleep 4
#snap-page repository
#open-location .
#sleep 2
#snap-page workingtree
snap-menu File
snap-menu Open_Recent
snap-menu Edit
snap-menu View
snap-menu Bazaar
snap-menu Start
snap-menu Collaborate
snap-menu Explore
snap-menu Work
snap-menu Bookmarks
snap-menu Tools
snap-menu Settings
snap-menu Configuration
snap-menu Ignores
snap-menu Help
sleep 2
exit
"""

class ScriptEngine(object):

    def run(self, script_name, context):
        print "running script %s" % (script_name,)
        if script_name == ':screenshots:':
            compiled_script = self._parse_script(_SCREENSHOTS_SCRIPT)
        else:
            raise AssertionError("unknown internal script %s" %
                (script_name,))
        self._run_compiled_script(compiled_script, context)

    def _parse_script(self, text):
        # The first line of the script defines the language.
        lines = text.splitlines()
        if lines[0] != "# command-list":
            raise AssertionError("unknown script identifier '%s'" % (lines[0],))

        # For now, a compiled script is a list of (command, args) tuples.
        # When we need something more advanced, support QtScript say.
        commands = []
        for line in lines[1:]:
            line = line.rstrip()
            if line == '' or line [0] == '#':
                # Skip comments and blank lines
                continue
            commands.append(self._parse_command(line))
        return commands

    def _parse_command(self, line):
        # split into command and arguments
        # TODO: support parsing of args with embedded spaces
        parts = line.split(' ')
        if len(parts) == 1:
            return (parts[0], None)
        else:
            return (parts[0], parts[1:])

    def _run_compiled_script(self, script, context):
        for command, args in script:
            # TODO: map to context.do_command(*args)
            if command == 'echo':
                self._do_echo(context, args)
            elif command == 'exit':
                self._do_exit(context, args)
            elif command == 'open-location':
                self._do_open_location(context, args)
            elif command == 'sleep':
                self._do_sleep(context, args)
            elif command == 'snap-menu':
                self._do_snap_menu(context, args)
            elif command == 'snap-page':
                self._do_snap_page(context, args)
            elif command == 'snap-window':
                self._do_snap_window(context, args)
            else:
                raise AssertionError("unknown command '%s'" % (command,))

    def _do_echo(self, context, args):
        # Output arguments
        print "%s" % ' '.join(args)

    def _do_exit(self, context, args):
        # This is heavy handed but less aggressive methods aren't working
        print "exiting"
        sys.exit(0)

    def _do_open_location(self, context, args):
        location = args[0]
        print "opening %s" % (location,)
        context.open_location(location)

    def _do_sleep(self, context, args):
        # Pause for a number of seconds
        secs = int(args[0])
        print "sleeping for %d seconds" % (secs,)
        sleep_countdown = secs
        while sleep_countdown > 0:
            QtGui.QApplication.processEvents()
            time.sleep(1)
            sleep_countdown -= 1

    def _do_snap_menu(self, context, args):
        # Snapshot a menu
        menu_name = args[0]
        menu_obj = context.ui.__dict__["menu_%s" % (menu_name,)]
        menu_obj.show()
        pixmap = QtGui.QPixmap.grabWidget(menu_obj)
        self._save_snapfile(pixmap, 'menu', menu_name)

    def _save_snapfile(self, pixmap, category, id, dest='explorer-snapshots'):
        if not os.path.exists(dest):
            os.mkdir(dest)
        filename = os.path.join(dest, "%s-%s.png" % (category, id))
        pixmap.save(filename)
        print "saved %s" % (filename,)

    def _do_snap_page(self, context, args):
        # Snapshot the current page
        name = args[0]
        widget = context.location_views.currentWidget()
        widget.window().show()
        pixmap = QtGui.QPixmap.grabWidget(widget)
        self._save_snapfile(pixmap, 'page', name)

    def _do_snap_window(self, context, args):
        # Snapshot a window
        # TODO: get the window border rendering
        window_name = args[0]
        window = context.window()
        window.show()
        pixmap = QtGui.QPixmap.grabWidget(window)
        self._save_snapfile(pixmap, 'window', window_name)
