/**
© Florian Joncour, 2013-2018 florian@zetta-sys.com

Ce logiciel est un programme informatique faisant interface à la bibliothèque
Perspective3D, un outil de modélisation 3D à partir de vues orthographiques 2D.

Ce logiciel est régi par la licence CeCILL-C soumise au droit français et
respectant les principes de diffusion des logiciels libres. Vous pouvez
utiliser, modifier et/ou redistribuer ce programme sous les conditions
de la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA
sur le site "http://www.cecill.info".

En contrepartie de l'accessibilité au code source et des droits de copie,
de modification et de redistribution accordés par cette licence, il n'est
offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,
seule une responsabilité restreinte pèse sur l'auteur du programme,  le
titulaire des droits patrimoniaux et les concédants successifs.

A cet égard  l'attention de l'utilisateur est attirée sur les risques
associés au chargement,  à l'utilisation,  à la modification et/ou au
développement et à la reproduction du logiciel par l'utilisateur étant
donné sa spécificité de logiciel libre, qui peut le rendre complexe à
manipuler et qui le réserve donc à des développeurs et des professionnels
avertis possédant  des  connaissances  informatiques approfondies.  Les
utilisateurs sont donc invités à charger  et  tester  l'adéquation  du
logiciel à leurs besoins dans des conditions permettant d'assurer la
sécurité de leurs systèmes et ou de leurs données et, plus généralement,
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.

Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
pris connaissance de la licence CeCILL-C, et que vous en avez accepté les
termes.
**/

/* Objet: Fenêtre principale. */

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFile>
#include <QDir>
#include <QFileDialog>
#include <QMessageBox>
#include <QPointF>
#include <QRectF>
#include <QPoint>
#include <QLabel>
#include <QPlainTextEdit>
#include <QTabWidget>
#include <QShortcut>
#include <QGraphicsRectItem>

#include "API/perspective_api.h"

#include "dialogfichiers.h"
#include "automate.h"
#include "animeQt.h"

#ifdef DEBUG
#include <QDebug>
#endif

#define AFFICHE_SELECTION_COULEUR_SOLIDE_PANORAMIQUE

#ifdef SUPPORT_VISION2D
#define ExtensionsImagesImport "*.bmp *.png *.jpg *.jpeg *.tga *.gif"
#endif // SUPPORT_VISION2D

#define ExtensionsFichiersImport3D "*.stl"

class BarreOutils2D;
class Documentation;
class Parametres;
class GestionnaireScripts;
class Scene2D;
class Th_Perspective;
class Th_ImportSTL3D;
class Interface3d;
struct ProprietesPlan_t;
class Vue2D;
class QToolButton;
class WExecCommandes;
class MainWindow;
class clMAJ;

namespace Ui { class MainWindow; }

class MainWindow : public QMainWindow
{
        Q_OBJECT
    public:
        explicit MainWindow(Perspective3D::i18n::lang_p3d_t lang_p3d, const QString &chemin_zetta6, bool gen_mod_auto, const QString &nfichier, int id_style=1, QWidget *parent = 0);
        ~MainWindow();

        Q_DISABLE_COPY(MainWindow)

        const Perspective3D::PScene3D* ModeleCourant() const; /* Renvoi le modèle 3D courant (en fonction de l'onglet en cours d'utilisation). */
        void defIconeStatus(const char *icone);
        bool Ouvre_Script(QString nfichier = QString()); /* Ouvre et exécute un script. */

        void ArretAnimationsAutomate();

    private:
        bool GereGenerationBarreOutils();
        void defIconeOnglet(int id_onglet, const Perspective3D::PImage &image);
        bool ValideBarreOutils2D() const;
        bool Contexte2D(int index) const;
        bool Contexte2D() const;
        void PasseContexte2D();
        bool CliqueWidget(QWidget *w, int sommeil_post=-1, bool ignore_etat_animation=false);
        bool CliqueMenuContextuel(QAction *action, int sommeil_post=-1, bool ignore_etat_animation=false);
        bool CliqueSousMenuContextuel(QMenu *sous_menu, QAction *action, int sommeil_post=-1, bool ignore_etat_animation=false);
        bool CliqueAction(QAction *action);
        void Ferme_plan(bool reinit_console=false, bool supprime_precedent_historique=true); /* Ferme le fichier de plan en cours. */
        TypesFichiers Ouvrir(const QString &nfichier, bool autorise_scripts=true, bool regen_plan=false);

#ifdef SUPPORT_VISION2D
        QString DialogOuvrir(const QString &format_type=tr("Fichiers compatibles (*.dxf " ExtensionsImagesImport " *." ExtensionScriptsAutomate " " ExtensionsFichiersImport3D ");;Plan DXF (*.dxf);;Images (" ExtensionsImagesImport ");;Script Zetta6 (*." ExtensionScriptsAutomate ");;Solide 3D (" ExtensionsFichiersImport3D ")"));
#else
        QString DialogOuvrir(const QString &format_type=tr("Fichiers compatibles (*.dxf *." ExtensionScriptsAutomate " " ExtensionsFichiersImport3D ");;Plan DXF (*.dxf);;Script Zetta6 (*." ExtensionScriptsAutomate ");;Solide 3D (" ExtensionsFichiersImport3D ")"));
#endif // SUPPORT_VISION2D

        QString DialogEnregistrer(const QString &chemin_dest, const QString &format_type, QString *select_type_fichier);
        bool Ouvre_dxf(QString nfichier = QString(), bool regen_plan=false); /* Ouvre le fichier dxf donné en argument. Si il est nul, on ouvre une boite de dialogue pour demander un chemin d'accès. */
        bool Ouvre_dxf_int(const QString &nfichier, bool regen_plan=false);

        bool Ouvre_STL_2D(const QString &nfichier, bool regen_plan=false); /* Ouvre un fichier STL et l'importe en tant que solide 3D. */
        bool Ouvre_STL_3D(const QString &nfichier, bool bloquant=false);

#ifdef SUPPORT_VISION2D
        bool Ouvre_Image(QString nfichier);
        bool Ouvre_Image_int(QString nfichier);
        bool MesgErreurVision2D(const Perspective3D::resultat_vision2d_t resultat_v2d);
        void EnregistrePlan2D();
        void ForceModeEdition(bool etat);
        void PermutteModeEdition2D();
#endif // SUPPORT_VISION2D

        void MAJ_IconeOnglet2D();
        int EnvoiElementsPerspective3D(Perspective3D::Perspective *perspective, Perspective3D::vues2D_t vue, const QGraphicsRectItem *rect, bool mode_interne=true);
        void ChargeRectConfig(Perspective3D::vues2D_t vues);
        void AfficheMesgStatus(const QString &s, unsigned int tempo_s=5); /* Affiche un message temporaire dans la barre de status */
        void PeupleMenuOuvrir();
        void ChargeOrigine(Perspective3D::vues2D_t vue);
        bool Generation3D(Perspective3D::ParametresPerspective &parametres_p3d, qreal param1=-1, bool supprime_vues=false);
        void MasqueConsole();
        void AfficheConsole(bool fermeture_auto=false);
        void AjoutConsole(const QString &txt, bool affichage_console=true);
        void FermeOnglet(int index, bool arret_script=true);
        bool FermeOnglet3D(int index);
        void defFichierPrecedentConfig(const QString &nfichier);

        bool ArretTimer(int *id);

        Interface3d *Interface3DCourante() const;
        /* Renvoi l'instance d'interface pour suivant l'onglet. Renvoi un pointeur nul si invalide */
        Perspective3D::Perspective *PerspectiveCourantNonConst() const;
        const Perspective3D::Perspective* PerspectiveCourant() const; /* Renvoi l'instance Perspective suivant l'onglet. */

        void GereFenetre(bool restaure=false);

        const std::string &ChargeShaderInterface3D(Interface3d *interface3d, unsigned int contexte=PGL::CONTEXTE_MODELE);
        /* Charge les shaders dans une interface 3D (sélection en fonction du contexte). Renvoi le contenu du rapport de compilation (vide si tout s'est bien passé). */

        bool AppliqueShadersInterface3D(Interface3d *interface3d, bool modele, bool post);
        /* Applique les shaders d'après la configuration à destination de l'interface 3D donnée en argument. */

        void NouvelleVue3D(Th_Perspective *th_p, bool mode_2d=false, bool supprime_vues=false);
        /* Ouvre et paramètre un onglet de vue 3D pour le fil d'exécution Perspective3D qui vient d'être lancé. */

        void NouvelleVue3D(Th_ImportSTL3D *th_import, const QString &fichier_plan);
        /* Ouvre et paramètre un onglet de vue 3D. */

        //Interface3d *lanceInterface3D();
        void FermeVues3D(bool manuel);

        void GenOutilsBarreOnglets();
        void GereOutilsBarreOnglets();

        bool Init;
        int id_timer_init;
        Ui::MainWindow *ui;

        Documentation *Aide;

        Th_Automate automate;
        Interpreteur interpreteur;

        QComboBox *cmb_tolerance;
        QMenu *menu_historique;
        QMenu MenuContextuel2D;
        QStringList ListeHistorique;
        QToolButton *bouton_ouvrir;
        BarreOutils2D *barreoutils2d;

        QWidget *widget_outils_barre_onglets;
        QWidget *widget_outils_2d_onglets;
        QWidget *widget_outils_3d_onglets;
        QToolBar *barre_outils_widget_onglets;
        QToolBar *barre_outils_2d_widget_onglets;
        QToolBar *barre_outils_3d_widget_onglets;
        QToolBar *barre_outils_quit_widget_onglets;
        QComboBox *cmb_type_affichage_widget_onglets;

#ifdef AFFICHE_SELECTION_COULEUR_SOLIDE_PANORAMIQUE
        QComboBox *cmb_couleurs_scenes_widget_onglets;
#endif // AFFICHE_SELECTION_COULEUR_SOLIDE_PANORAMIQUE

        AnimationQt animation;
        GestionnaireScripts *GestionScripts;

        Parametres *parametres;
        bool exec_import;
        Perspective3D::PScene2D *persp_scene_2D;
        QString plan_courant;
        QString fichier_insert_tempo;
        int id_timer_fichier_insert;
        Vue2D *vue2D;
        Scene2D *scene2D;
        unsigned int compteur_entites_scene2d;

        bool masque_console;
        QWidget *widget_console;
        QPlainTextEdit *console;
#ifdef SUPPORT_VISION2D
    #ifdef DEBUG
        Perspective3D::Vision *vision_2d;
    #endif
        QWidget *widget_edition_2d;
#endif // SUPPORT_VISION2D

        std::vector<Interface3d *> *ListeVues3D;
        unsigned int OngletFixe;

        QWidget *widget_barre_status;
        QHBoxLayout *layout_barre_status;
        WExecCommandes *w_exec_commandes;
        QLabel *label_barre_status_0;
        QLabel *label_barre_status_1;
        QLabel *label_barre_status_2;
        QLabel *label_barre_status_centre;
        QLabel *label_barre_status_maj;

        clMAJ *controle_mise_a_jour;

        const QString &fichier_demarrage;
        const QString &chemin_installation;

        int id_feuille_style;
        bool gen_modele_demarrage;
        QVector<QShortcut *>ListeRaccourcis;
        int tempo_affiche_console;
        int id_tempo_affiche_console;
        int tempo_affiche_mesg_status;
        int id_tempo_affiche_mesg_status;

    private slots:
        void timerEvent(QTimerEvent *ev);
        void showEvent(QShowEvent *ev);
        void closeEvent(QCloseEvent *ev);

        void keyPressEvent(QKeyEvent *ev);
        void keyReleaseEvent(QKeyEvent *ev);

        void ControleVersionServeur(const QString &version_serveur);
        void ExecCommandeInterpreteur(const QString &cmd);

        void InsertFichier(const QString &nfichier);
//        void TexteConsole_ev();
        void GereIconesOutils2D(bool verrouille=false);
        void ImprimeModele();
        void AfficheConfigAffichage3D(int);
        bool ExecGenerationModele(bool supprime_vues);
        void NouvelleScene2D();
        void defTexteStatusCoords(const QString &s); /* Défini le texte dans la barre de status (coordonnées). */
        void defTexteStatusInfo(const QString &s); /* Défini le texte dans la barre de status (informations). */

        void ExportImageModele();
        void SelectionModeAffichage3D(int);
        void SelectionCouleur3D(int);
        void SelectionCouleurPersp3D(int);

#ifdef SUPPORT_GIF
        void EnregistreAnimationModele();
#endif // SUPPORT_GIF

#ifdef SUPPORT_VISION2D
        void NouveauTraceVision2D(const QList<QPoint>&, const QPointF &);
        void DoubleClicScene2D(bool mode);
#endif // SUPPORT_VISION2D

        void EnregistreModele(const QString &chemin_fichier, TypesFichiers type_fichier=TypesFichiers::NUL);
        void EnregistreModele();
        void EnregistreModele_2D();

        void GenPatron();
        void EnregistreScript(const ProprietesPlan_t &proprietes_plan, const Perspective3D::Perspective &perspective);
        bool ExportScriptPlan(const QString &chemin, const Perspective3D::PScene2D &scene);
        void FinGeneration(int id_onglet);

#ifdef SUPPORT_VISION2D
        void Annuler();
        void Restaurer();
#endif

        void GereIconeGestionnaireScripts(bool etat);

        void OuvrirGenerique(); /* Lance la boite de dialogue et ouvre un fichier */

        void ExecLigne_Automate(int id, bool autorise_animation);
        void Message_Automate(const QString &message, bool message_utilisateur);
        void Diction_Automate(const QString &message, int langue);
        void CadrageVue_Automate(bool animation);
        void Confirmation_Automate(const QString &message);
        void ReinitInterface_Automate(bool uniquement_2d);
        void OuvrirFichier_Automate(const QString &chemin_fichier);
        void FermeFichier_Automate();
        void Onglet2D_Automate();
        void Onglet3D_Automate(int id);
        void Anime3D_Automate();
        void DefVue_Automate(Perspective3D::vues2D_t vue, const QRectF &rect);
        void DefOrigine_Automate(Perspective3D::vues2D_t vue, const QPointF &point);
        void Generation_Automate(Perspective3D::ParametresPerspective parametres_p3d, bool attend_exec, qreal param1=-1);
        void ForceConfig_Automate(const Perspective3D::ParametresPerspective &parametres_p3d);
        void FermeGeneration_Automate();
        void FinScript_Automate();
        void Export3D_Automate(const QString &nom_fichier);

        void TraceGroupe_Automate();
        void TraceLigne_Automate(qreal x1, qreal y1, qreal x2, qreal y2, QRgb couleur);
        void TraceCourbe_Automate(qreal centre_x, qreal centre_y, qreal longueur, qreal hauteur, qreal angle1, qreal angle2, qreal rotation, QRgb couleur);
        void TraceTexte_Automate(const QString &str, qreal origine_x, qreal origine_y, qreal hauteur_texte, qreal rotation, QRgb couleur);
        void TracePoint_Automate(qreal x, qreal y, QRgb couleur);
        void NouvelleLangueEnv_Automate(int langue, bool exec_interpreteur);

        void QuestionBool_Automate(const QString &question, bool valeur_defaut, bool *v, bool *annuler_exec);
        void QuestionInt_Automate(const QString &question, int valeur_defaut, int *v, bool *annuler_exec);
        void QuestionFloat_Automate(const QString &question, double valeur_defaut, double *v, bool *annuler_exec);

        void NouveauxParametres(bool nouveaux_shaders=false);
        void NouvelleLicence();
        void AideParametres(unsigned int onglet);
        void NouveauRectSelection(Perspective3D::vues2D_t vue, bool ignore_gen_auto=false);
        void NouvelleOrigine(Perspective3D::vues2D_t vue);
        void SupprimeOrigine(Perspective3D::vues2D_t vue);
        void SupprimeVue(Perspective3D::vues2D_t vue);
        void OuvreFichierHistorique(QAction *action);
        void GereMenuContextuel2D(QPoint pos);
        void AfficheMenuContextuel2D(QPoint pos);

        void ExecFichier_Documentation(const QString &s);
        void OuvreConfig_Documentation(const QString &s);

        void FermetureAide(QCloseEvent *ev);
        void FermetureParametres();

        void InverseModeFilaire();

        void on_tabWidget_currentChanged(int index);
        void cmb_tolerance_currentIndexChanged(int index);
        void on_tabWidget_tabCloseRequested(int index);
        void on_actionFermer_le_plan_triggered();
        void on_action_MAJ_plan_triggered();
        void on_actionExtrusion_triggered();
        void on_actionRevolution_triggered();
        void on_actionVues_automatiques_triggered();
        void on_actionVue_Face_triggered();
        void on_actionVue_cote_triggered();
        void on_actionVue_haute_triggered();
        void on_actionSupprimer_les_vues_triggered();
        void on_actionOrigine_face_triggered();
        void on_actionOrigine_cote_triggered();
        void on_actionOrigine_haute_triggered();
        void on_actionSupprimer_les_origines_triggered();
        void on_actionGenerer_triggered();
        void on_actionModele_filaire_triggered(bool checked);
        void on_actionParametres_triggered();
        void on_actionAide_triggered();
        void on_actionAfficheConsole_triggered();
        void on_actionEnregistrer_le_mod_le_triggered();
        void on_actionImprimer_triggered();
        void on_actionEnregistrer_le_script_triggered();
        void on_actionArreter_le_script_triggered();
        void on_actionScripts_triggered();
        void on_actionEnregistrer_image_triggered();
        void on_actionDebloquer_le_logiciel_triggered();

#ifdef SUPPORT_VISION2D
        void EnregistrerScene2D_mousePress();
        void AnnulerScene2D_mousePress();
        void RetablirScene2D_mousePress();
    #ifdef DEBUG_API_P3D
        void EnregistrerMatriceVision2D_mousePress();
    #endif // DEBUG_API_P3D
#endif // SUPPORT_VISION2D

#ifdef SUPPORT_GIF
        void on_actionEnregistrer_animation_triggered();
#endif // SUPPORT_GIF

        void on_actionQuitter_triggered();
        void on_actionVue_de_face_3d_triggered();
        void on_actionVue_de_cote_3d_triggered();
        void on_actionVue_de_dessus_3d_triggered();
        void on_actionVue_oblique_3d_triggered();
        void on_action_Permutte_mode_plein_ecran_triggered();
        void on_actionPermutte_ecran_triggered();
        void on_actionAffichage_proprietes3D_triggered();
        void on_actionConversion_2D_triggered();
};

#endif // MAINWINDOW_H
