/******************************************************************************
 *  Copyright (C) 2005-2018 by                                                *
 *    Bjoern Erik Nilsen (bjoern.nilsen@bjoernen.com),                        *
 *    Fredrik Berg Kjoelstad (fredrikbk@hotmail.com),                         *
 *    Ralf Lange (ralf.lange@longsoft.de)                                     *
 *                                                                            *
 *  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.,                                           *
 *  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                 *
 ******************************************************************************/

#ifndef FRONTEND_H
#define FRONTEND_H

#include "domain/domainfacade.h"
#include "frontends/viewfacade.h"
#include "technical/preferencestool.h"
#include "technical/grabber/grabberresolution.h"
#include "technical/grabber/imagegrabberdevice.h"

#include <QtCore/QString>
#include <QtCore/QVector>
#include <QtGui/QImage>

typedef QPair<QString, QStringList> ExternalCommand;

class PreferencesTool;
class DomainFacade;
class ViewFacade;
class ImageGrabberDevice;

/**
 * The frontend interface to be used by the implemented frontend.
 *
 * @author Bjoern Erik Nilsen & Fredrik Berg Kjoelstad
*/
class Frontend
{
public:

    /**
     * @brief V4L2 grabber enable default for new installations
     */
    const static bool V4L2GRABBERDEFAULT = true;

    /**
     * @brief V4L2 controller enable default for new installations
     */
    const static bool V4L2CONTROLLERDEFAULT = true;

    /**
     * @brief MediaFoundation grabber enable default for new installations
     */
    const static bool MEDIAFOUNDATIONGRABBERDEFAULT = true;

    /**
     * @brief MesiaFoundation controller enable default for new installations
     */
    const static bool MEDIAFOUNDATIONCONTROLLERDEFAULT = true;

    /**
     * @brief GPhoto2 grabber enable default for new installations
     */
    const static bool GPHOTO2GRABBERDEFAULT = false;

    /**
     * @brief GPhoto2 controller enable default for new installations
     */
    const static bool GPHOTO2CONTROLLERDEFAULT = false;

    /**
     * @brief Destructor
     */
    virtual ~Frontend() {}

    /**
     * Abstract function for starting the application through the frontend.
     * @param argc the argc argument from the environment through main.
     * @param argv the argv arguments from the environment through main.
     * @return the return status on exit
     */
    virtual int run(int argc, char **argv) = 0;

    /**
     * Abstract function for geting the domain facade.
     * @return the domain facade.
     */
    virtual DomainFacade* getProject() = 0;

    /**
     * Abstract function for geting the view facade.
     * @return the view facade.
     */
    virtual ViewFacade* getView() = 0;

    /**
     * Abstract function for geting the preferences tool.
     * @return the preferences tool.
     */
    virtual PreferencesTool* getPreferences() = 0;

    /**
     * Abstract function for getting the application directory
     * @return the application directory name string
     */
    virtual const QString getUserDirName() = 0;

    /**
     * Abstract function for getting the temporary directory
     * @return the temporary directory name string
     */
    virtual const QString getTempDirName() = 0;

    /**
     * Abstract function for getting the application directory
     * @return the application directory name string
     */
    virtual const QString getApplicationDirName() = 0;

    /**
     * Abstract function for getting the binary directory
     * @return the binary directory name string
     */
    virtual const QString getBinDirName() = 0;

    /**
     * Abstract function for getting the manual directory
     * @return the manual directory name string
     */
    virtual const QString getManualDirName() = 0;

    /**
     * Abstract function for getting the translations directory
     * @return the translations directory name string
     */
    virtual const QString getTranslationsDirName() = 0;

    /**
     * Abstract function for getting the graphics directory
     * @return the graphics directory name string
     */
    virtual const QString getGraphicsDirName() = 0;

    /**
     * Abstract function for getting the icons directory
     * @return the icons directory name string
     */
    virtual const QString getIconsDirName() = 0;

    /**
     * Abstract function for getting the pictures directory
     * @return the pictures directory name string
     */
    virtual const QString getPicturesDirName() = 0;

    /**
     * Abstract function for getting the sounds directory
     * @return the sounds directory name string
     */
    virtual const QString getSoundsDirName() = 0;

    /**
     * Abstract function for getting the sounds directory
     * @return the sounds directory name string
     */
    virtual const QString getStylesDirName() = 0;

    /**
     * Abstract function for getting all possible GUI languages
     * @return A vector with all languages
     */
    virtual const QVector<QString> getLanguages() = 0;

    /**
     * Abstract function for getting all possible GUI locales
     * @return A vector with all locales
     */
    virtual const QVector<QString> getLocales() = 0;

    /**
     * A new language is selected in the preferences menu.
     * @param newIndex New selected index.
     */
    virtual void changeLanguage(int newIndex) = 0;

    /**
     * A new capture button function is selected in the preferences menu.
     * @param newFunction New selected function.
     */
    virtual void changeCaptureButtonFunction(int newFunction) = 0;

    /**
     * Get the status of the vertical lines of the grid.
     * @return The new state of the grid.
     */
    virtual bool getVerticalGrid() = 0;

    /**
     * Set the status of the vertical lines of the grid.
     * @param newState The new state of the grid.
     */
    virtual void setVerticalGrid(bool newState) = 0;

    /**
     * Get the number of vertical lines of the grid.
     * @return The new number of lines.
     */
    virtual int getVerticalSpin() = 0;

    /**
     * Set the number of vertical lines of the grid.
     * @param newSpin The new number of lines.
     */
    virtual void setVerticalSpin(int newSpin) = 0;

    /**
     * Get the status of the horizontal lines of the grid.
     * @return The new state of the grid.
     */
    virtual bool getHorizontalGrid() = 0;

    /**
     * Set the status of the horizontal lines of the grid.
     * @param newState The new state of the grid.
     */
    virtual void setHorizontalGrid(bool newState) = 0;

    /**
     * Get the number of horizontal lines of the grid.
     * @return The new number of lines.
     */
    virtual int getHorizontalSpin() = 0;

    /**
     * Set the number of horizontal lines of the grid.
     * @param newSpin The new number of lines.
     */
    virtual void setHorizontalSpin(int newSpin) = 0;

    /**
     * Get the RGB value of the color of the grid lines.
     * @param r The red component of the color's RGB value.
     * @param g The green component of the color's RGB value.
     * @param b The blue component of the color's RGB value.
     * @param a The alpha-channel component of the color's RGB value.
     */
    virtual void getGridColorRGB(int *r, int *g, int *b, int *a) = 0;

    /**
     * Set the RGB value of the color of the grid lines.
     * @param r The red component of the color's RGB value.
     * @param g The green component of the color's RGB value.
     * @param b The blue component of the color's RGB value.
     * @param a The alpha-channel component of the color's RGB value.
     */
    virtual void setGridColorRGB(int r, int g, int b, int a) = 0;

    /**
     * Get the status of the signal feature.
     * @return The new state of the signal feature.
     */
    virtual bool getSignal() = 0;

    /**
     * Set the status of the signal feature.
     * @param newState The new state of the signal feature.
     */
    virtual void setSignal(bool newState) = 0;

    /**
     * Abstract function for displaying progress on timeconsuming operations.
     * @param infoText the text to display to the user
     * @param numOperations the number of calculated operations to do
     */
    virtual void showProgress(const QString &infoText, unsigned int numOperations = 0) = 0;

    /**
     * Abstract function for hiding the progress info.
     */
    virtual void hideProgress() = 0;

    /**
     * Abstract function for updating the progress.
     * @param numOperationsDone the number of operations done
     */
    virtual void updateProgress(int numOperationsDone) = 0;

    /**
     * Abstract function for increase the progress.
     */
    virtual void increaseProgress() = 0;

    /**
     * Abstract function to display a message in the status bar.
     * @param message the message to display.
     * @param timeout the timeout for the message in mili-seconds.
     */
    virtual void showMessage(const QString &message, int timeout = 0) = 0;

    /**
     * Abstract function to remove any temporary message being shown in the status bar.
     */
    virtual void clearMessage() = 0;

    /**
     * Abstract function for changing the information to display to the user
     * @param infoText the text to display to the user
     */
    virtual void setProgressInfo(const QString infoText) = 0;

    /**
     * Abstract function for changing the prozess id in the status bar
     * @param id the id to display in the status bar
     */
    virtual void setProjectID(const QString id) = 0;

    /**
     * Abstract function for changing the scene id in the status bar
     * @param id the id to display in the status bar
     */
    virtual void setSceneID(const QString id) = 0;

    /**
     * Abstract function for changing the take id in the status bar
     * @param id the id to display in the status bar
     */
    virtual void setTakeID(const QString id) = 0;

    /**
     * Abstract function for changing the exposure id in the status bar
     * @param id the id to display in the status bar
     */
    virtual void setExposureID(const QString id) = 0;

    /**
     * Abstract function for checking if the user has aborted the operation
     * (eg pressed cancel)
     * @return true if the the operation is aborted, false otherwise
     */
    virtual bool isOperationAborted() = 0;

    /**
     * Abstract function for processing GUI events. This is useful on timeconsuming
     * operations which aren't running in separate processes or threads.
     */
    virtual void processEvents() = 0;

    /**
     * Abstract function for asking the user a yes/no question.
     * @param title title of the message dialog
     * @param question the question to ask
     * @return 0 if the user answer yes, 1 if no
     */
    virtual int askQuestion(const QString title, const QString &question) = 0;

    /**
     * Abstract function for informating the user.
     * @param title title of the message dialog
     * @param info the information for the user
     */
    virtual void showInformation(const QString title, const QString &info) = 0;

    /**
     * Abstract function for warning the user.
     * @param title title of the message dialog
     * @param warning the warning for the user
     */
    virtual void showWarning(const QString title, const QString &warning) = 0;

    /**
     * Abstract function for signaling a critical state to the user.
     * @param title title of the message dialog
     * @param message the message for the user
     */
    virtual void showCritical(const QString title, const QString &message) = 0;

    /**
     * Abstract function to run a external command
     * @param command command to run
     * @param arguments arguments for the command
     * @return return value of the command
     */
    virtual int runExternalCommand(const QString &command, const QStringList &arguments) = 0;

    /**
     * Abstract function to run several external commands
     * @param commands commands with arguments to run
     * @return return value of the command
     */
    virtual int runExternalCommands(const QList<ExternalCommand> &commands) = 0;

    /**
     * Abstract function to turns on the webcamera/video import mode.
     */
    virtual bool startGrabber() = 0;

    /**
     * Abstract function to checks if the grabber is inited.
     * @return true if it is inited, false otherwise
     */
    virtual bool isGrabberInited() = 0;

    /**
     * Abstract function to turns off the webcamera/video import mode.
     */
    virtual void stopGrabber() = 0;

    /**
     * Abstract function to get the possible video devices.
     * @return Vector with the devices.
     */
    virtual const QVector<ImageGrabberDevice*> getDevices() = 0;

    /**
     * Abstract function to get one video devices.
     * @arg deviceIndex The index of the device.
     * @return The video devices.
     */
    virtual ImageGrabberDevice *getDevice(int deviceIndex) = 0;

    /**
     * Abstract function to get the possible video device names.
     * @return Vector with the device names.
     */
    virtual const QVector<QString> getDeviceNames() = 0;

    /**
     * Abstract function to get the possible resolution names
     * of the video device.
     * @arg deviceIndex The index of the device.
     * @return Vector with the resolution names.
     */
    virtual const QVector<QString> getResolutionNames(int deviceIndex) = 0;

    /**
     * Abstract function to get the live image from the image grabber.
     * @return live image.
     */
    virtual const QImage getLiveImage() = 0;

    /**
     * Abstract function to get the raw image from the image grabber.
     * @return raw image.
     */
    virtual const QImage getRawImage() = 0;

    /**
     * Function for performing the redraw with the next frame of the animation.
     * @arg exposureIndex Index of the next frame
     */
    virtual void nextAnimationFrame(int exposureIndex) = 0;

    /**
     * Register the directory for external change monitoring.
     * @param directory the directory to listen for changes in.
     */
    virtual void addDirectoryToMonitoring(const QString &directory) = 0;

    /**
     * Remove the directory from external change monitoring.
     * @param directory the directory to remove.
     */
    virtual void removeDirectoryFromMonitoring(const QString &directory) = 0;

    /**
     * Remove all directories from external change monitoring.
     */
    virtual void removeAllDirectoriesFromMonitoring() = 0;

    /**
     * Register the file for external change monitoring.
     * @param file the file to listen for changes in.
     */
    virtual void addFileToMonitoring(const QString &file) = 0;

    /**
     * Remove the file from external change monitoring.
     * @param file the file to remove.
     */
    virtual void removeFileFromMonitoring(const QString &file) = 0;

    /**
     * Remove all files from external change monitoring.
     */
    virtual void removeAllFilesFromMonitoring() = 0;

    /**
     * Test function for debugging purposes
     */
    virtual void test(QWidget *parentWidget, int level) = 0;

    /**
     * Create all temporary application directories (temp, trash, packer)
     */
    virtual void makeApplicationDirectories() = 0;

    /**
     * Remove all temporary application directories (temp, trash, packer)
     */
    virtual void removeApplicationDirectories() = 0;

    /**
     * Remove all temporary application files
     */
    virtual void removeApplicationFiles() = 0;

    /**
     * Set a new state to the tool bar.
     * @param newState the new tool bar state.
     */
    virtual void setToolBarState(int newState) = 0;

    /**
     * Open the online help in the default internet browser
     * @param anchor The anchor in the manual to go to after the manual is opend
     */
    virtual void openOnlineHelp(const QString &anchor) = 0;

    /**************************************************************************
     * Project preferences
     **************************************************************************/

    /**
     * Get the recording mode.
     * @return The recording mode.
     */
    virtual int getRecordingMode() = 0;

    /**
     * Set the recording mode.
     * @param mode The new recording mode.
     */
    virtual void setRecordingMode(int mode) = 0;

    /**
     * Get the unit mode.
     * @return The unit mode.
     */
    virtual int getUnitMode() = 0;

    /**
     * Set the unit mode.
     * @param mode The new unit mode.
     */
    virtual void setUnitMode(int mode) = 0;

    /**
     * Get the unit count.
     * @return The unit count.
     */
    virtual int getUnitCount() = 0;

    /**
     * Set the unit count.
     * @param count The new unit count.
     */
    virtual void setUnitCount(int count) = 0;

    /**
     * Get the beep checkbox state.
     * @brief getBeepState
     * @return The actual beep checkbox state
     */
    virtual bool getBeepState() = 0;

    /**
     * Set the beep checkbox state.
     * @brief setBeepState
     * @param state The new beep checkbox state.
     */
    virtual void setBeepState(bool state) = 0;

    /**
     * Get the beep unit count.
     * @return The beep unit count.
     */
    virtual int getBeepCount() = 0;

    /**
     * Set the beep unit count.
     * @param count The new beep unit count.
     */
    virtual void setBeepCount(int count) = 0;

    /**
     * Get the video source index.
     * @return video source index
     */
    virtual int getVideoSource() = 0;

    /**
     * Set the video resolution index.
     * @param index Index of the new video resolution
     * @return true if the new index is set, false else.
     */
    virtual bool setResolution(int index) = 0;

    /**
     * Get the video resolution index.
     * @return video resolution index
     */
    virtual int getResolution() = 0;

    /**
     * Get the video resolution object.
     * @param index Index of the new video resolution
     * @return video resolution object
     */
    virtual const GrabberResolution getResolution(int index) = 0;

    /**
     * Set the video source index.
     * @param index Index of the new video source
     * @return true if the new index is set, false else.
     */
    virtual bool setVideoSource(int index) = 0;

    /**
     * Convert all images of the current project to a new image file format.
     * @param newFormat The new format of the images.
     * @param newQuality The new quality value of the images.
     * @return true if all images are converted to the new image format.
     */
    virtual bool convertImages(int newFormat, int newQuality) = 0;

    /**
     * Get the mix mode.
     * @return The mix mode.
     */
    virtual int getMixMode() = 0;

    /**
     * Set the mix mode.
     * @param mode The new mix mode.
     */
    virtual void setMixMode(int mode) = 0;

    /**
     * Get the mix count.
     * @return The mix count.
     */
    virtual int getMixCount() = 0;

    /**
     * Set the mix count.
     * @param count The new mix count.
     */
    virtual void setMixCount(int count) = 0;

    /**
     * Get the overlay intensity value.
     * @return The overlay intensity value.
     */
    virtual int getOverlayIntensity() = 0;

    /**
     * Set the overlay intensity value of the project.
     * @param overlay The new overlay intensity value.
     */
    virtual void setOverlayIntensity(int overlay) = 0;

    /**************************************************************************
     * Other
     **************************************************************************/

    /**
     * Test function for debugging purposes
     */
    virtual void testMainWidget() = 0;

};

#endif
