/* This file is part of libhud-qt
 * Copyright 2013 Canonical Ltd.
 *
 * libhud-qt is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3,
 * as published by the Free Software Foundation.
 *
 * libhud-qt is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranties of
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef UBUNTU_HUD_ACTION_H
#define UBUNTU_HUD_ACTION_H

#include <QObject>
#include <QString>
#include <QStringList>

#include "parameter.h"

namespace Ubuntu {
namespace HUD {
    class Action;
    class Context;
}
}

class Ubuntu::HUD::Action : public QObject
{
    Q_OBJECT
    Q_DISABLE_COPY(Action)

    Q_PROPERTY(QString identifier
               READ identifier
               WRITE setIdentifier
               NOTIFY identifierChanged)

    Q_PROPERTY(QString label
               READ label
               WRITE setLabel
               NOTIFY labelChanged)

    Q_PROPERTY(QString description
               READ description
               WRITE setDescription
               NOTIFY descriptionChanged)

    Q_PROPERTY(QString keywords
               READ keywords
               WRITE setKeywords
               NOTIFY keywordsChanged)

    Q_PROPERTY(bool isBackgroundAction
               READ isBackgroundAction
               WRITE setIsBackgroundAction
               NOTIFY isBackgroundActionChanged)

    Q_PROPERTY(bool enabled
               READ enabled
               WRITE setEnabled
               NOTIFY enabledChanged)

    Q_PROPERTY(QString commitLabel
               READ commitLabel
               WRITE setCommitLabel
               NOTIFY commitLabelChanged)

    Q_PROPERTY(bool hasLivePreview
               READ hasLivePreview
               WRITE setHasLivePreview
               NOTIFY hasLivePreviewChanged)
    Q_PROPERTY(bool hasNoPreview
               READ hasNoPreview
               WRITE setHasNoPreview
               NOTIFY hasNoPreviewChanged)

    Q_PROPERTY(bool requiresPreview
               READ requiresPreview
               WRITE setRequiresPreview
               NOTIFY requiresPreviewChanged)

    class Private;

public:
    explicit Action(QObject *parent = 0);
    virtual ~Action();

    /*! unique identifier for the action */
    virtual QString identifier() const;
    virtual void setIdentifier(const QString &identifier);

    /*! user visible label of the action */
    virtual QString label() const;

    virtual void setLabel(const QString &label);

    /*!
     * additional small snippet to describe the action
     * pref. max 8 words or something
     *
     * the snippet will have any punctuations removed
     */
    virtual QString description() const;
    virtual void setDescription(const QString &description);

    /*!
     * List of strings of keywords for this action. The keywords will be visible
     * in the help page and are taken into consideration when searching the HUD.
     *
     * Do we need to link parameters to keywords also? As for example if the user
     * wants to colorify an image with sepia color then we would have keyword
     * "Sepia" for action "Colorify" with appropriate default parameters?
     *
     * Keywords can contain spaces.
     *
     * The format is "Keyword 1;Keyword 2;Keyword 3"
     *
     * \warning maybe they should?
     *
     * Do we need separate list of "other known names" which would not show up
     * in the Help page?
     */
    virtual QString keywords() const;
    virtual void setKeywords(QString keywords);

    /*!
     * this action is marked to be a specific background action and should
     * receive a higher score than the normal actions when the application is
     * in the background
     */
    virtual bool isBackgroundAction() const;
    virtual void setIsBackgroundAction(bool value);

    /*!
     * the action is either insensitive or invisible
     *
     * action list -> invisible
     * toolbar -> insensitive
     */
    virtual bool enabled() const;
    virtual void setEnabled(bool value);

    /*! label to show in the commit button */
    virtual QString commitLabel() const;
    virtual void setCommitLabel(const QString &label);

    /*! preview is done live */
    virtual bool hasLivePreview() const;
    virtual void setHasLivePreview(bool value);

    /*! the action can't be previewed */
    virtual bool hasNoPreview() const;
    virtual void setHasNoPreview(bool value);

    /*!
     * the action requires either live preview or if that is not available then
     * a additional preview step has to be shown in the HUD
     */
    virtual bool requiresPreview() const;
    virtual void setRequiresPreview(bool value);

    /*!
     * if the action has multiple values to manipulate then each of them will
     * be defined here
     */
    virtual QList<Parameter *> parameters();
    virtual void addParameter(Parameter *parameter);
    virtual void removeParameter(Parameter *parameter);


public slots:
    void trigger() const;

signals:

    /*! fired when user activates the action */
    void triggered() const;

    void identifierChanged(const QString &identifier);

    void labelChanged(const QString &label);

    void descriptionChanged(const QString &description);

    void keywordsChanged(QString keywords);

    void isBackgroundActionChanged(bool value);

    void enabledChanged(bool value);

    void commitLabelChanged(const QString &label);
    void hasLivePreviewChanged(bool value);
    void hasNoPreviewChanged(bool value);
    void requiresPreviewChanged(bool value);

    void parameterAdded(Ubuntu::HUD::Parameter *parameter);
    void parameterRemoved(Ubuntu::HUD::Parameter *parameter);
    void parametersChanged();

    void started();
    void cancelled();
    void resetted();

protected:
    void _actionDescription(void **desc);

private:
    friend class Ubuntu::HUD::Context;
    void magic(void **desc, void *gactionlist);

private:
    Private *d;
};

#endif // UBUNTU_HUD_ACTION_H
