#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# === This file is part of Calamares - <https://calamares.io> ===
#
#   SPDX-FileCopyrightText: 2016-2017 Teo Mrnjavac <teo@kde.org>
#   SPDX-FileCopyrightText: 2017 Alf Gaida <agaida@siduction.org>
#   SPDX-License-Identifier: GPL-3.0-or-later
#
#   Calamares is Free Software: see the License-Identifier above.
#

import platform

from PythonQt.QtGui import *
import PythonQt.calamares as calamares

# WARNING: the Calamares PythonQt API is considered EXPERIMENTAL as of
# Calamares 2.5. It comes with no promise or commitment to API stability.


# Set up translations.
# You may skip this if your Calamares module has no user visible strings.
# DO NOT install _ into the builtin namespace because each module loads
# its own catalog.
# DO use the gettext class-based API and manually alias _ as described in:
# https://docs.python.org/3.5/library/gettext.html#localizing-your-module
import gettext
import inspect
import os
_filename = inspect.getframeinfo(inspect.currentframe()).filename
_path = os.path.dirname(os.path.abspath(_filename))

_ = gettext.gettext

# Example Python ViewModule.
# A Python ViewModule is a Python program which defines a ViewStep class.
# One UI module ==> one ViewStep.
# This class must be marked with the @calamares_module decorator. A
# ViewModule may define other classes, but only one may be decorated with
# @calamares_module. Such a class must conform to the Calamares ViewStep
# interface and functions as the entry point of the module.
# A ViewStep manages one or more "wizard pages" through methods like
# back/next, and reports its status through isNextEnabled/isBackEnabled/
# isAtBeginning/isAtEnd. The whole UI, including all the pages, must be
# exposed as a single QWidget, returned by the widget function.
#
# For convenience, both C++ and PythonQt ViewSteps are considered to be
# implementations of ViewStep.h. Additionally, the Calamares PythonQt API
# allows Python developers to keep their identifiers more Pythonic on the
# Python side. Thus, all of the following are considered valid method
# identifiers in a ViewStep implementation: isNextEnabled, isnextenabled,
# is_next_enabled.


@calamares_module
class DummyPythonQtViewStep:
    def __init__(self):
        # Importing PythonQt.QtGui provides access to most Qt widget classes.
        self.main_widget = QFrame()

        self.main_widget.setLayout(QVBoxLayout())

        label = QLabel()
        self.main_widget.layout().addWidget(label)

        accumulator = "\nCalamares+PythonQt running embedded Python " +\
                      platform.python_version()
        label.text = accumulator

        btn = QPushButton()

        # Python strings can be used wherever a method wants a QString. Python
        # gettext translations can be used seamlessly as well.
        btn.setText(_("Click me!"))
        self.main_widget.layout().addWidget(btn)

        # The syntax for signal-slot connections is very simple, though
        # slightly different from the C++ equivalent. There are no SIGNAL and
        # SLOT macros, and a signal can be connected to any Python method
        # (without a special "slot" designation).
        btn.connect("clicked(bool)", self.on_btn_clicked)

    def on_btn_clicked(self):
        self.main_widget.layout().addWidget(QLabel(_("A new QLabel.")))

    def prettyName(self):
        return _("Dummy PythonQt ViewStep")

    def isNextEnabled(self):
        return True  # The "Next" button should be clickable

    def isBackEnabled(self):
        return True  # The "Back" button should be clickable

    def isAtBeginning(self):
        # True means the currently shown UI page is the first page of this
        # module, thus a "Back" button click will not be handled by this
        # module and will cause a skip to the previous ViewStep instead
        # (if any). False means that the present ViewStep provides other UI
        # pages placed logically "before" the current one, thus a "Back" button
        # click will be handled by this module instead of skipping to another
        # ViewStep. A module (ViewStep) with only one page will always return
        # True here.
        return True

    def isAtEnd(self):
        # True means the currently shown UI page is the last page of this
        # module, thus a "Next" button click will not be handled by this
        # module and will cause a skip to the next ViewStep instead (if any).
        # False means that the present ViewStep provides other UI pages placed
        # logically "after" the current one, thus a "Next" button click will
        # be handled by this module instead of skipping to another ViewStep.
        # A module (ViewStep) with only one page will always return True here.
        return True

    def jobs(self):
        # Returns a list of objects that implement Calamares::Job.
        return [DummyPQJob("Dummy PythonQt job reporting for duty")]

    def widget(self):
        # Returns the base QWidget of this module's UI.
        return self.main_widget

    def retranslate(self, locale_name):
        # This is where it gets slightly weird. In most desktop applications we
        # shouldn't need this kind of mechanism, because we could assume that
        # the operating environment is configured to use a certain language.
        # Usually the user would change the system-wide language in a settings
        # UI, restart the application, done.
        # Alas, Calamares runs on an unconfigured live system, and one of the
        # core features of Calamares is to allow the user to pick a language.
        # Unfortunately, strings in the UI do not automatically react to a
        # runtime language change. To get UI strings in a new language, all
        # user-visible strings must be retranslated (by calling tr() in C++ or
        # _() in Python) and reapplied on the relevant widgets.
        # When the user picks a new UI translation language, Qt raises a QEvent
        # of type LanguageChange, which propagates through the QObject
        # hierarchy. By catching and reacting to this event, we can show
        # user-visible strings in the new language at the right time.
        # The C++ side of the Calamares PythonQt API catches the LanguageChange
        # event and calls the present method. It is then up to the module
        # developer to add here all the needed code to load the module's
        # translation catalog for the new language (which is separate from the
        # main Calamares strings catalog) and reapply any user-visible strings.
        calamares.utils.debug("PythonQt retranslation event "
                              "for locale name: {}".format(locale_name))

        # First we load the catalog file for the new language...
        try:
            global _
            _t = gettext.translation('dummypythonqt',
                                     localedir=os.path.join(_path, 'lang'),
                                     languages=[locale_name])
            _ = _t.gettext
        except OSError as e:
            calamares.utils.debug(e)
            pass

        # ... and then we can call setText(_("foo")) and similar methods on
        # the relevant widgets here to reapply the strings.

# An example Job class. Implements Calamares::Job. For method identifiers, the
# same rules apply as for ViewStep. No decorators are necessary here, because
# only the ViewStep implementation is the unique entry point, and a module can
# have any number of jobs.


class DummyPQJob:
    def __init__(self, my_msg):
        self.my_msg = my_msg

    def pretty_name(self):
        return _("The Dummy PythonQt Job")

    def pretty_description(self):
        return _("This is the Dummy PythonQt Job. "
                 "The dummy job says: {}").format(self.my_msg)

    def pretty_status_message(self):
        return _("A status message for Dummy PythonQt Job.")

    def exec(self):
        # As an example, we touch a file in the target root filesystem.
        rmp = calamares.global_storage['rootMountPoint']
        os.system("touch {}/calamares_dpqt_was_here".format(rmp))
        calamares.utils.debug("the dummy job says {}".format(self.my_msg))
        return {'ok': True}
