/*!
    \page tutorial2.html
    \title Tutorial 2 - The "Buttons" plugin
    \brief This plugin demonstrates the usage of events and actions.
    \ingroup tutorials
    

    In the second tutorial we make our own first plugin with the name \b {"Buttons"}. We will use this name for the naming concentions of the filenames. 
    
    \section1 Topics
    This tutorial will show you how to:
    \list
        \li \unicode{0x25B6} Start with a new \l{DevicePlugin}{Plugin}
        \li \unicode{0x25B6} Implement an \l{Action}
        \li \unicode{0x25B6} Implement an \l{Event}
    \endlist

    In order to getting started with the new \b {"Button"} plugin we use the \b {"Minimal"} plugin as template and start from there. Make a copy of the minimal folder and name the new folder \b buttons-diy. In this case \b{buttons-diy} because the folder \b buttons already exits from the \tt plugin-template repository.
    
    \section1 Create the basic structure
    \code
        $cp -rv minimal/ buttons-diy/

        ‘minimal/’ -> ‘buttons-diy/’
        ‘minimal/plugins.pri’ -> ‘buttons-diy/plugins.pri’
        ‘minimal/minimal.pro’ -> ‘buttons-diy/minimal.pro’
        ‘minimal/devicepluginminimal.json’ -> ‘buttons-diy/devicepluginminimal.json’
        ‘minimal/minimal.pro.user’ -> ‘buttons-diy/minimal.pro.user’
        ‘minimal/devicepluginminimal.h’ -> ‘buttons-diy/devicepluginminimal.h’
        ‘minimal/devicepluginminimal.cpp’ -> ‘buttons-diy/devicepluginminimal.cpp’
    \endcode
    
    \note Delete the \tt minimal.pro.user file if there is any.
    
    Now we can rename the files using the plugin name convention:
    \code
        $ cd buttons-diy/

        $ mv minimal.pro buttons.pro
        $ mv devicepluginminimal.h devicepluginbuttons.h
        $ mv devicepluginminimal.cpp devicepluginbuttons.cpp
        $ mv devicepluginminimal.json devicepluginbuttons.json
    \endcode
    
    \section2 Change the \tt buttons.pro
    Open the \tt buttons.pro file with the \e {Qt Creator} and open that file in the editor:

    \code
        include(plugins.pri)

        TARGET = $$qtLibraryTarget(nymea_devicepluginminimal)

        message("Building $$deviceplugin$${TARGET}.so")

        SOURCES += \
            devicepluginminimal.cpp \

        HEADERS += \
            devicepluginminimal.h \

    \endcode
    
    \list 1
        \li Change the \tt TARGET name form \tt nymea_devicepluginminimal \unicode{0x2192} \tt nymea_devicepluginbuttons
        \li Change the SOURCES file from \tt devicepluginminimal.cpp \unicode{0x2192} \tt devicepluginbuttons.cpp
        \li Change the HEADERS file from \tt devicepluginminimal.h \unicode{0x2192} \tt devicepluginbuttons.h
    \endlist

    Your file sould look now like this:
    \code
        include(plugins.pri)

        TARGET = $$qtLibraryTarget(nymea_devicepluginbuttons)

        message("Building $$deviceplugin$${TARGET}.so")

        SOURCES += \
            devicepluginbuttons.cpp \

        HEADERS += \
            devicepluginbuttons.h \
    \endcode
    
    If you save the file, the header and source file should appear in the project structure of the \e {Qt Creator}.

    \section2 Change the \tt devicepluginbuttons.h
    Open the \tt devicepluginbuttons.h file.
    
    \code
        #ifndef DEVICEPLUGINMINIMAL_H
        #define DEVICEPLUGINMINIMAL_H

        #include "plugin/deviceplugin.h"
        #include "devicemanager.h"

        class DevicePluginMinimal : public DevicePlugin
        {
            Q_OBJECT

            Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginminimal.json")
            Q_INTERFACES(DevicePlugin)

        public:
            explicit DevicePluginMinimal();

            DeviceManager::HardwareResources requiredHardware() const override;
            DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
        };

        #endif // DEVICEPLUGINMINIMAL_H
    \endcode
    
    \list 1
        \li Change the \tt {#ifndef}, \tt {#define} and \tt #define name from \tt DEVICEPLUGINMINIMAL_H \unicode{0x2192} \tt DEVICEPLUGINBUTTONS_H
        \li Change the class name form \tt DevicePluginMinimal \unicode{0x2192} \tt DevicePluginButtons
        \li Change in the \tt Q_PLUGIN_METADATA line the \tt FILE parameter from \tt "devicepluginminimal.json" \unicode{0x2192} \tt "devicepluginbuttons.json" to set \l{The Plugin JSON file}.
        \li Change the constructor name from \tt DevicePluginMinimal \unicode{0x2192} \tt DevicePluginButtons
    \endlist

    Your file sould look now like this:
    \code
        #ifndef DEVICEPLUGINBUTTONS_H
        #define DEVICEPLUGINBUTTONS_H

        #include "plugin/deviceplugin.h"
        #include "devicemanager.h"

        class DevicePluginButtons : public DevicePlugin
        {
            Q_OBJECT

            Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginbuttons.json")
            Q_INTERFACES(DevicePlugin)

        public:
            explicit DevicePluginButtons();

            DeviceManager::HardwareResources requiredHardware() const override;
            DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
        };

        #endif // DEVICEPLUGINBUTTONS_H
    \endcode

    \section2 Change the \tt devicepluginbuttons.cpp

    Open the \tt devicepluginbuttons.cpp file.
    
    \code
        #include "devicepluginminimal.h"
        #include "plugininfo.h"

        DevicePluginMinimal::DevicePluginMinimal()
        {
        }

        DeviceManager::HardwareResources DevicePluginMinimal::requiredHardware() const
        {
            return DeviceManager::HardwareResourceNone;
        }

        DeviceManager::DeviceSetupStatus DevicePluginMinimal::setupDevice(Device *device)
        {
            Q_UNUSED(device)
            qCDebug(dcMinimal) << "Hello word! Setting up a new device:" << device->name();
            qCDebug(dcMinimal) << "The new device has the DeviceId" << device->id().toString();
            qCDebug(dcMinimal) << device->params();

            return DeviceManager::DeviceSetupStatusSuccess;
        }
    \endcode
    
    \list 1
        \li Change the \tt {#include "devicepluginminimal.h"} \unicode{0x2192} \tt {#include "devicepluginbuttons.h"}
        \li Change in each method implementation the \tt DevicePluginMinimal \unicode{0x2192} \tt DevicePluginButtons namespace.
        \li Change each \tt {qCDebug(dcMinimal)} \unicode{0x2192} \tt {qCDebug(dcButtons)}, you will see later why.
    \endlist
        
    Your file sould look now like this:
    
    \code
        #include "devicepluginbuttons.h"
        #include "plugininfo.h"

        DevicePluginButtons::DevicePluginButtons()
        {
        }

        DeviceManager::HardwareResources DevicePluginButtons::requiredHardware() const
        {
            return DeviceManager::HardwareResourceNone;
        }

        DeviceManager::DeviceSetupStatus DevicePluginButtons::setupDevice(Device *device)
        {
            Q_UNUSED(device)
            qCDebug(dcButtons) << "Hello word! Setting up a new device:" << device->name();
            qCDebug(dcButtons) << "The new device has the DeviceId" << device->id().toString();
            qCDebug(dcButtons) << device->params();

            return DeviceManager::DeviceSetupStatusSuccess;
        }
    \endcode

    The basic structure of our new \l{DevicePlugin} is finished. You may recognize that the \tt {plugininfo.h} file does not exist yet. You have to build the plugin to generate that file. Each time you change \l{The Plugin JSON file} this file will be new generated.

    \section2 Change the \tt devicepluginbuttons.json
    
    Our new plugin will have the name \b {Buttons}, the corresponding logging categorie will be \tt dcButtons (defined from the \e {idName}). There will be one new \l{DeviceClass} with the name \b {Simple Button}. This \l{DeviceClass} will have one \l{EventType} and one \l{ActionType}.

    The current \tt devicepluginbuttons.json should still look like this:
    \code
        {
            "name": "Minimal plugin",
            "idName": "Minimal",
            "id": "6878754a-f27d-4007-a4e5-b030b55853f5",
            "vendors": [
                {
                    "name": "Minimal vendor",
                    "idName": "minimal",
                    "id": "3897e82e-7c48-4591-9a2f-0f56c55a96a4",
                    "deviceClasses": [
                        {
                            "deviceClassId": "7014e5f1-5b04-407a-a819-bbebd11fa372",
                            "idName": "minimal",
                            "name": "Minimal device",
                            "createMethods": ["user"],
                            "paramTypes": [
                                {
                                    "name": "name",
                                    "type": "QString",
                                    "defaultValue": "Simple button device default name"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    \endcode
    
    Now we change \l{The Plugin JSON file} for our new plugin:
    \list 1
        \li Set the plugin \e name to \b Buttons 
        \li Set the plugin \e idName to \b Buttons (used for logging category name -> \e {dcButtons}) 
        \li Use \b {\tt uuidgen} to create a new UUID. Replace the old plugin \e id with the new one.
        \li Set the vendor \e name to \b {Button vendor} 
        \li Set the vendor \e idName to \b buttons (used for VendorId variable definition in the \tt plugininfo.h -> \e buttonsVendorId})
        \li Use \b {\tt uuidgen} to create a new UUID. Replace the old vendor \e id with the new one.
        \li Use \b {\tt uuidgen} to create a new UUID. Replace the old DeviceClassId \e id with the new one. 
        \li Set the device class \e idName to \b simpleButton (used for DeviceClassId variable definition in the \tt plugininfo.h -> \e simpleButtonDeviceClassId})
        \li Set the device class \e name to \b {Simple Button}
        \li The \e createMethod is still the same: \b user 
        \li This single \l ParamType called \b name should be in every single DeviceClass to allow the user to give a custom name to a \l{Device}. Just change the defaultValue for the name to \b {Simple button device default name}.   
    \endlist

    Your device should now look like this (with your own UUIDs):
    \code
        {
            "name": "Buttons",
            "idName": "Buttons",
            "id": "7bfd3af5-7983-4540-9398-d14085d069f4",
            "vendors": [
                {
                    "name": "Button vendor",
                    "idName": "buttons",
                    "id": "fd2ae067-2c3d-4332-9c4b-ee0af653bcaf",
                    "deviceClasses": [
                        {
                            "deviceClassId": "73bb670b-e7a3-40da-bd6f-3260f017ec80",
                            "idName": "simpleButton",
                            "name": "Simple Button",
                            "createMethods": ["user"],
                            "paramTypes": [
                                {
                                    "name": "name",
                                    "type": "QString",
                                    "defaultValue": "Simple button device default name"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    \endcode

    Now the basic structure is finished and we have a new \l{DevicePlugin}, a new \l{Vendor} and a new \l{DeviceClass}. 

    Now we have to add an \l{ActionType} which will called \b press and gives the user the possibility to press this button device (see \l{The ActionType definition})

    \list 1
        \li Use \b {\tt uuidgen} to create a new UUID for this \l{ActionType}.
        \li Set the \e idName of this \l{ActionType} to \b pressSimpleButton (used for ActionTypeId variable definition in the \tt plugininfo.h -> \e pressSimpleButtonActionTypeId})
        \li Set the \e name of this \l{ActionType} to \b {press the button}
    \endlist
    \code
        "actionTypes": [
            {
                "id": "64c4ced5-9a1a-4858-81dd-1b5c94dba495",
                "idName": "pressSimpleButton",
                "name": "press the button"
            }
        ]
    \endcode
    
    Now we have to add an \l{EventType} which will be emitted when the button was pressed. 

    \list 1
        \li Use \b {\tt uuidgen} to create a new UUID for this \l{EventType}.
        \li Set the \e idName of this \l{EventType} to \b simpleButtonPressed (used for EventTypeId variable definition in the \tt plugininfo.h -> \e simpleButtonPressedEventTypeId})
        \li Set the \e name of this \l{EventType} to \b {button pressed}
    \endlist

    \code
        "eventTypes": [
            {
                "id": "f9652210-9aed-4f38-8c19-2fd54f703fbe",
                "idName": "simpleButtonPressed",
                "name": "button pressed"
            }
        ]
    \endcode

    \code
        {
            "name": "Buttons",
            "idName": "Buttons",
            "id": "7bfd3af5-7983-4540-9398-d14085d069f4",
            "vendors": [
                {
                    "name": "Button vendor",
                    "idName": "buttons",
                    "id": "fd2ae067-2c3d-4332-9c4b-ee0af653bcaf",
                    "deviceClasses": [
                        {
                            "deviceClassId": "73bb670b-e7a3-40da-bd6f-3260f017ec80",
                            "idName": "simpleButton",
                            "name": "Simple Button",
                            "createMethods": ["user"],
                            "paramTypes": [
                                {
                                    "name": "name",
                                    "type": "QString",
                                    "defaultValue": "Simple button device default name"
                                }
                            ],
                            "actionTypes": [
                                {
                                    "id": "64c4ced5-9a1a-4858-81dd-1b5c94dba495",
                                    "idName": "pressSimpleButton",
                                    "name": "press the button"
                                }
                            ],
                            "eventTypes": [
                                {
                                    "id": "f9652210-9aed-4f38-8c19-2fd54f703fbe",
                                    "idName": "simpleButtonPressed",
                                    "name": "button pressed"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    \endcode
    
    Rebuild the entire project to generate the new \tt {plugininfo.h}. You need to call the \underline{Rebuild all} command in the \e {Qt Creator} to take over the changes in the \tt plugininfo.h .
    
    If you make a syntax error in the JSON file, you will get a build error with the position of the syntax error in the JSON file. Now your definitions should be in the plugininfo.h file and ready to use in the plugin source code. 

    You will see in the build output following section:    
    \code
        /usr/bin/nymea-generateplugininfo ../buttons-diy/devicepluginbuttons.json plugininfo.h
        ../buttons-diy/devicepluginbuttons.json -> plugininfo.h
         --> generate plugininfo.h
        PluginId for plugin "Buttons" = 7bfd3af5-7983-4540-9398-d14085d069f4
        define VendorId ButtonsVendorId = fd2ae067-2c3d-4332-9c4b-ee0af653bcaf
        define DeviceClassId simpleButtonDeviceClassId = 73bb670b-e7a3-40da-bd6f-3260f017ec80
        define logging category: "dcButtons"
         --> generated successfully "plugininfo.h"
         --> generate extern-plugininfo.h
         --> generated successfully "extern-plugininfo.h"
    \endcode
    
    This shows you how the \tt{plugininfo.h} and \tt{extern-plugininfo.h} will be generated. As you can see the UUID definitions and the logging category were definend for the \b {Buttons} plugin.

    Once the build step is finished, you can take a look at that file (curser in line \tt {#include "plugininfo.h"} and press \tt F2)

    Your \tt plugininfo.h should now look like this (with your own UUIDs):
    \code
        #ifndef PLUGININFO_H
        #define PLUGININFO_H
        #include "typeutils.h"
        #include <QLoggingCategory>

        // Id definitions
        PluginId pluginId = PluginId("7bfd3af5-7983-4540-9398-d14085d069f4");
        VendorId buttonsVendorId = VendorId("fd2ae067-2c3d-4332-9c4b-ee0af653bcaf");
        DeviceClassId simpleButtonDeviceClassId = DeviceClassId("73bb670b-e7a3-40da-bd6f-3260f017ec80");
        ActionTypeId pressSimpleButtonActionTypeId = ActionTypeId("64c4ced5-9a1a-4858-81dd-1b5c94dba495");
        EventTypeId simpleButtonPressedEventTypeId = EventTypeId("f9652210-9aed-4f38-8c19-2fd54f703fbe");

        // Loging category
        Q_DECLARE_LOGGING_CATEGORY(dcButtons)
        Q_LOGGING_CATEGORY(dcButtons, "Buttons")

        #endif // PLUGININFO_H
    \endcode 
    
  \section1 Writing the plugin
    
    Now we have our basic for starting to implement the new plugin. If you install the current plugin, you would already see the plugin implementation in \tt nymea-cli, but it would do nothing because we have not implemented yet the code.

    \section2 The \tt executeAction method
     
    Every plugin with \l{Action}{Actions} needs the \l{DevicePlugin::executeAction()} method which should be overridden in your own plugin.

    \code
    DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
    \endcode

    Here is the implemented method:
    \code
        // Check the DeviceClassId for "Simple Button"
        if (device->deviceClassId() == simpleButtonDeviceClassId ) {

            // check if this is the "press" action
            if (action.actionTypeId() == pressSimpleButtonActionTypeId) {

                qCDebug(dcButtons) << "Simple button" << device->paramValue("name").toString() << "was pressed";

                // Emit the "button pressed" event
                Event event(simpleButtonPressedEventTypeId, device->id());
                emit emitEvent(event);

                return DeviceManager::DeviceErrorNoError;
            }
            return DeviceManager::DeviceErrorActionTypeNotFound;
        }
    \endcode
    
    When a user or the \l {nymeaserver::RuleEngine}{RuleEngine} calls the executeAction method, our plugin will first check if the \l DeviceClassId matches, then the \l ActionTypeId. If both are correct, we can emit our \l Event to show that the simple button \l Device was pressed.   

    You can see in the implementation that a new \l{Event} will be generated in nymea. This is the way how you emit an Event for a device.

    \section1 Test the plugin
    Rebuild the whole project to make shore all changes are registered and install the plugin (see \l{Install the plugin}{Tutorial 1 - Install the plugin}).

    \list 1    
        \li Start nymea with following command:

            \code
                $ nymead -n -d Buttons
            \endcode

        \li Start nymea-cli and add the a new \b {"Simple Button"} devcice. Give an appropriate name like \b {Test button}.
        \li Use nymea-cli to execute the \b {press the button} action: 

            \tt "Devices" \unicode{0x2192} \tt {"Execute an action"} \unicode{0x2192} \tt {"Your device name (Simple Button)"} \unicode{0x2192} \tt {press the button}

    \endlist
    
    \code
        ...

        Connection: Tcp server: new client connected: "127.0.0.1"
        Buttons: Simple button "Test button" was pressed
        RuleEngine: got event: Event(EventTypeId: "{f9652210-9aed-4f38-8c19-2fd54f703fbe}", 
                    DeviceId"{967d4c50-7cc5-4114-865a-822c64a1e7ce}") "Simple Button" 
                    QUuid ("{f9652210-9aed-4f38-8c19-2fd54f703fbe}")

    \endcode

    Now you have successfully implemented you first DeviceClass, which has an \l Action and an \l Event and can be used together with the \l {nymeaserver::RuleEngine}{RuleEngine}.

    Now you can take a look at \l{Tutorial 3 - The "Power Button" device}.

*/ 


