//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2015 Richard S. Smith and collaborators.
//
// If you use MorphoGraphX in your work, please cite:
//   http://dx.doi.org/10.7554/eLife.05864
//
// MorphoGraphX is free software, and is licensed under under the terms of the 
// GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
// 
#ifndef PRIVATEPROCESS_HPP
#define PRIVATEPROCESS_HPP

#include <Process.hpp>

#include <QMutex>
#include <QWaitCondition>

namespace mgx 
{
  /*
   * This class is used to hide the internal structure of MorphoGraphX from the processes.
   *
   * There will be one instance of this class shared by all the processes. 
   */
  class PrivateProcess {
  public:
    PrivateProcess(QObject* p) : current_stack(-1), current_mesh(-1), globalBrightness(0.0), globalContrast(1.0),
      globalShininess(32.0), globalSpecular(0.2), selected_label(0), mesh_selection(false), line_border_selection(false),
      clip1(0, p), clip2(1, p), clip3(2, p), cuttingSurface(), error(), warning(), parent(p), 
      success(false), changedFolder(false) {}
  
    // Accessible MorphoGraphX data from processes.
    std::vector<Stack*> _stacks;
    std::vector<Mesh*> _meshes;
    int current_stack, current_mesh;
    float globalBrightness, globalContrast, globalShininess, globalSpecular;
    int selected_label;
    bool mesh_selection, line_border_selection;
    Clip clip1, clip2, clip3;
    CuttingSurface cuttingSurface;
    QString error, warning, filename;
    QString currentPythonCall;
    QString actingFile;
    QObject* parent;
    MGXCamera *camera;
  
    bool success, changedFolder;
    QMutex lock;
    QWaitCondition updated;
  };
  
  //
  // This class is used to create the first process from nothing. All other processes with 
  // be created from this one, and will share its pointer to PrivateProcess.
  //
  class SetupProcess : public Process 
  {
  public:
    SetupProcess(QObject* parent = 0) : Process()
    {
      p = new PrivateProcess(parent);
    }
  
    void clear_private()
    {
      // Should only be called on close
      if(p) {
        for(size_t i = 0; i < p->_stacks.size(); ++i) {
          Stack* s = p->_stacks[i];
          if(s)
            delete s;
          p->_stacks[i] = 0;
        }
        for(size_t i = 0; i < p->_meshes.size(); ++i) {
          Mesh* m = p->_meshes[i];
          if(m)
            delete m;
          p->_meshes[i] = 0;
        }
      }
    }
  
    ~SetupProcess()
    {
      // Should only be called on close
      clear_private();
      if(p)
        delete p;
      p = 0;
    }
  
    // You cannot run this process
    bool run() { return true; }
    void setFile(const QString& s) { p->filename = s; }
  
    void resetModified()
    {
      if(p) {
        p->error = QString();
        p->warning = QString();
        for(size_t i = 0; i < p->_stacks.size(); ++i) {
          Stack* s = p->_stacks[i];
          if(s) {
            s->resetModified();
            if(s->main())
              s->main()->resetModified();
            if(s->work())
              s->work()->resetModified();
          }
        }
        for(size_t i = 0; i < p->_meshes.size(); ++i) {
          Mesh* m = p->_meshes[i];
          if(m)
            m->resetModified();
        }
        p->cuttingSurface.resetModified();
      }
    }
  };
}

#endif
