/* ****************************************************************************
  This file is part of Lokalize

  Copyright (C) 2007-2014 by Nick Shaforostoff <shafff@ukr.net>

  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) version 3 or any later version
  accepted by the membership of KDE e.V. (or its successor approved
  by the membership of KDE e.V.), which shall act as a proxy
  defined in Section 14 of version 3 of the license.

  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, see <http://www.gnu.org/licenses/>.

**************************************************************************** */

#ifndef EDITORTAB_H
#define EDITORTAB_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "pos.h"
#include "lokalizesubwindowbase.h"

#include <QHash>

#ifndef NOKDE
namespace Sonnet{class Dialog;}
namespace Sonnet{class BackgroundChecker;}

#include <kxmlguiclient.h>

class KFind;
class KReplace;
class KActionCategory;
#endif

class Project;
class Catalog;
class EditorView;
class MergeView;
class CatalogView;
class MsgCtxtView;
class AltTransView;
namespace GlossaryNS{class GlossaryView;}



struct EditorState
{
public:
    EditorState(): entry(0){}
    EditorState(const EditorState& s):dockWidgets(s.dockWidgets), filePath(s.filePath), entry(0) {}
    ~EditorState(){}

    QByteArray dockWidgets;
    QString filePath;
    QString mergeFilePath;
    int entry;
    //int offset;
};


/**
 * @short Editor tab
 *
 * This class can be called a dispatcher for one message catalog.
 *
 * It is accessible via Lokalize.currentEditor() from kross scripts and via
 * '/ThisIsWhatYouWant/Editor/# : org.kde.Lokalize.Editor' from qdbusviewer
 *
 * @author Nick Shaforostoff <shafff@ukr.net>
 */
class EditorTab: public LokalizeSubwindowBase2
{
    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "org.kde.Lokalize.Editor")
    //qdbuscpp2xml -m -s editortab.h -o org.kde.lokalize.Editor.xml
#define qdbuscpp2xml

public:
    EditorTab(QWidget* parent, bool valid=true);
    ~EditorTab();


    //interface for LokalizeMainWindow
    void hideDocks();
    void showDocks();
    QString currentFilePath();
    void setFullPathShown(bool);
    void setProperCaption(QString,bool);//reimpl to remove ' - Lokalize'
public slots:
    void setProperFocus();
public:
    bool queryClose();
    EditorState state();
#ifndef NOKDE
    KXMLGUIClient* guiClient(){return (KXMLGUIClient*)this;}
    QString dbusObjectPath();
    int dbusId(){return m_dbusId;}
    QObject* adaptor(){return m_adaptor;}
#endif

    //wrapper for cmdline handling
    void mergeOpen(QString mergeFilePath);

    bool fileOpen(QString filePath=QString(), QString suggestedDirPath=QString(), bool silent=false);
public slots:
    //for undo/redo, views
    void gotoEntry(DocPosition pos,int selection=0);
#ifdef qdbuscpp2xml
    Q_SCRIPTABLE void gotoEntry(int entry){gotoEntry(DocPosition(entry));}
    Q_SCRIPTABLE void gotoEntryForm(int entry,int form){gotoEntry(DocPosition(entry,form));}
    Q_SCRIPTABLE void gotoEntryFormOffset(int entry,int form, int offset){gotoEntry(DocPosition(entry,form,offset));}
    Q_SCRIPTABLE void gotoEntryFormOffsetSelection(int entry,int form, int offset, int selection){gotoEntry(DocPosition(entry,form,offset),selection);}

    Q_SCRIPTABLE QString currentEntryId();
    Q_SCRIPTABLE int currentEntry(){return m_currentPos.entry;}
    Q_SCRIPTABLE int currentForm(){return m_currentPos.form;}
    Q_SCRIPTABLE QString selectionInTarget();
    Q_SCRIPTABLE QString selectionInSource();

    Q_SCRIPTABLE void setEntryFilteredOut(int entry, bool filteredOut);
    Q_SCRIPTABLE void setEntriesFilteredOut(bool filteredOut);

    Q_SCRIPTABLE int entryCount();
    Q_SCRIPTABLE QString entrySource(int entry, int form);
    Q_SCRIPTABLE QString entryTarget(int entry, int form);
    Q_SCRIPTABLE void setEntryTarget(int entry, int form, const QString& content);
    Q_SCRIPTABLE int entryPluralFormCount(int entry);
    Q_SCRIPTABLE bool entryReady(int entry);
    Q_SCRIPTABLE void addEntryNote(int entry, const QString& note);
    Q_SCRIPTABLE void addTemporaryEntryNote(int entry, const QString& note);

    Q_SCRIPTABLE void addAlternateTranslation(int entry, const QString& translation);
    Q_SCRIPTABLE void addTemporaryAlternateTranslation(int entry, const QString& translation);

    Q_SCRIPTABLE QString currentFile(){return currentFilePath();}
    Q_SCRIPTABLE QByteArray currentFileContents();
    Q_SCRIPTABLE QString sourceLangCode();
    Q_SCRIPTABLE QString targetLangCode();

    Q_SCRIPTABLE void attachAlternateTranslationFile(const QString& path);
    Q_SCRIPTABLE void openSyncSource(QString path){mergeOpen(path);}
    Q_SCRIPTABLE void reloadFile();
#endif
    Q_SCRIPTABLE bool saveFile(const QString& filePath=QString());
    Q_SCRIPTABLE bool saveFileAs();
    Q_SCRIPTABLE void close(){return parent()->deleteLater();}
    Q_SCRIPTABLE void gotoNextUnfiltered();
    Q_SCRIPTABLE void gotoPrevUnfiltered();
    Q_SCRIPTABLE void gotoFirstUnfiltered();
    Q_SCRIPTABLE void gotoLastUnfiltered();
    Q_SCRIPTABLE void gotoNext();
    Q_SCRIPTABLE void gotoPrev();
    Q_SCRIPTABLE void gotoFirst();
    Q_SCRIPTABLE void gotoLast();

    Q_SCRIPTABLE void mergeIntoOpenDocument();

    Q_SCRIPTABLE bool findEntryBySourceContext(const QString& source, const QString& ctxt);

#ifndef NOKDE
    Q_SCRIPTABLE bool isValid(){return m_valid;}
    Q_SCRIPTABLE void setSrcFileOpenRequestAccepted(bool a){m_srcFileOpenRequestAccepted=a;}
#endif

private slots:
#ifndef NOKDE
    void highlightFound(const QString &,int,int);//for find/replace
    void highlightFound_(const QString &,int,int);//for find/replace
#endif

    void lookupSelectionInTranslationMemory();

    //statusbar indication
    void numberOfFuzziesChanged();
    void numberOfUntranslatedChanged();
    //fuzzy, untr [statusbar] indication
    void msgStrChanged();
    //modif [caption] indication
    void setModificationSign();
    void updateCaptionPath();

    //gui
    void switchForm(int);

    void undo();
    void redo();
#ifndef NOKDE
    void findNext();
    void findPrev();
    void find();

    void replace();
    void replaceNext();//internal
    void doReplace(const QString&,int,int,int);//internal
    void cleanupReplace();//internal
#endif

//     void selectAll();
//     void deselectAll();
//     void clear();
//     void search2msgstr();
//     void plural2msgstr();

    void gotoEntry();

    void gotoPrevFuzzyUntr();
    bool gotoNextFuzzyUntr(const DocPosition& pos=DocPosition());
    void gotoNextFuzzy();
    void gotoPrevFuzzy();
    void gotoNextUntranslated();
    void gotoPrevUntranslated();

    void toggleApprovementGotoNextFuzzyUntr();
    void setApproveActionTitle();


#ifndef NOKDE
    void spellcheck();
    void spellcheckNext();
    void spellcheckShow(const QString&,int);
    void spellcheckReplace(QString,int,const QString&);
    void spellcheckStop();
    void spellcheckCancel();
#endif

    void gotoNextBookmark();
    void gotoPrevBookmark();

    void displayWordCount();

    void openPhasesWindow();

    void defineNewTerm();

    void initLater();
    void showStatesMenu();
    void setState(QAction*);
    void dispatchSrcFileOpenRequest(const QString& srcPath, int line);
    void indexWordsForCompletion();

    void fileAutoSaveFailedWarning(const QString&);

protected:
    void paintEvent(QPaintEvent* event);
    
private:
    void setupAccel();
    void setupActions();
    void setupStatusBar();

    void findNext(const DocPosition& startingPos);
    void replaceNext(const DocPosition&);

private:
    Project* m_project;
    Catalog* m_catalog;

    EditorView* m_view;
    QAction* m_approveAndGoAction;
    QAction* m_approveAction;
    QAction* m_stateAction; //is = m_approveAction ifndef NOKDE

    DocPosition m_currentPos;
    DocPosition _searchingPos; //for find/replace
    DocPosition _replacingPos;
    DocPosition _spellcheckPos;
    DocPosition _spellcheckStartPos;

#ifndef NOKDE
    Sonnet::BackgroundChecker* m_sonnetChecker;
    Sonnet::Dialog* m_sonnetDialog;
    int m_spellcheckStartUndoIndex;
    bool m_spellcheckStop:1;
#endif

    bool m_currentIsApproved:1; //for statusbar animation
    bool m_currentIsUntr:1;  //for statusbar animation

    bool m_fullPathShown:1;

#ifndef NOKDE
    bool m_doReplaceCalled:1;//used to prevent non-clean catalog status
    KFind* m_find;
    KReplace* m_replace;
#endif

    //BEGIN views
    MergeView* m_syncView;
    MergeView* m_syncViewSecondary;
    CatalogView* m_transUnitsView;
    MsgCtxtView* m_notesView;
    AltTransView* m_altTransView;
    //END views


    QString _captionPath;

    bool m_srcFileOpenRequestAccepted;

    //BEGIN dbus
#ifndef NOKDE
    bool m_valid;
    QObject* m_adaptor;
    int m_dbusId;
    static QList<int> ids;
#endif
    //END dbus

signals:
    void tmLookupRequested(DocPosition::Part, const QString&);
    void tmLookupRequested(const QString& source, const QString& target);

    Q_SCRIPTABLE void srcFileOpenRequested(const QString& srcPath, int line);

    void fileOpenRequested(const QString& filePath, const QString& str, const QString& ctxt);

    //emitted when mainwindow is closed or another file is opened
    void fileClosed();
    Q_SCRIPTABLE void fileClosed(const QString& path);
    Q_SCRIPTABLE void fileSaved(const QString& path);
    Q_SCRIPTABLE void fileAboutToBeClosed();//old catalog is still accessible
    Q_SCRIPTABLE void fileOpened();

    Q_SCRIPTABLE void entryDisplayed();
    void signalNewEntryDisplayed(const DocPosition&);
    void signalEntryWithMergeDisplayed(bool,const DocPosition&);
    void signalFirstDisplayed(bool);
    void signalLastDisplayed(bool);

    void signalEquivTranslatedEntryDisplayed(bool);
    void signalApprovedEntryDisplayed(bool);

    void signalFuzzyEntryDisplayed(bool);
    void signalPriorFuzzyAvailable(bool);
    void signalNextFuzzyAvailable(bool);

    void signalPriorUntranslatedAvailable(bool);
    void signalNextUntranslatedAvailable(bool);

    void signalPriorFuzzyOrUntrAvailable(bool);
    void signalNextFuzzyOrUntrAvailable(bool);

    // merge mode signals gone to the view
    //NOTE move these to catalog tree view?
    void signalPriorBookmarkAvailable(bool);
    void signalNextBookmarkAvailable(bool);
    void signalBookmarkDisplayed(bool);

    Q_SCRIPTABLE void xliffFileOpened(bool);
};

#endif
