//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
//
//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//

//  VISU OBJECT : interactive object for VISU entities implementation
//  File   : VISU_Result_i.hh
//  Author : Alexey PETROV
//  Module : VISU
//
#ifndef __VISU_RESULT_I_H__
#define __VISU_RESULT_I_H__

#include "VISU_PrsObject_i.hh"
#include "VISU_BoostSignals.h"
#include "SALOME_GenericObj_i.hh"

#include "SALOME_Event.h"
#include "VTKViewer.h"

#include <boost/shared_ptr.hpp>
#include <gp_Dir.hxx>
#include <vector>
#include <map>

class VISU_Convertor;

namespace VISU
{
  //----------------------------------------------------------------------------
  class TResultObserver;


  //----------------------------------------------------------------------------
  class VISU_I_EXPORT Result_i : public virtual POA_VISU::Result,
				 public virtual RemovableObject_i,
				 public virtual SALOME::GenericObj_i
  {
    Result_i(const Result_i &);

  public:
    enum ESourceId {
      eRestoredComponent = -2, 
      eRestoredFile = -1,  
      eSavedFile = 0, 
      eFile = 1, 
      eComponent = 2
    };

    enum ECreationId {
      eImportFile, 
      eCopyAndImportFile, 
      eImportMed, 
      eImportMedField
    };

    static
    Result_i*
    New(SALOMEDS::Study_ptr theStudy,
	const ESourceId& theSourceId,
	const ECreationId& theCreationId,
	CORBA::Boolean theIsBuildImmediately,
	CORBA::Boolean theIsBuildFields,
	CORBA::Boolean theIsBuildMinMax,
	CORBA::Boolean theIsBuildGroups);
    
    virtual
    void
    RemoveFromStudy();

    virtual
    VISU::VISUType 
    GetType() 
    {
      return VISU::TRESULT;
    }

    virtual
    CORBA::Boolean
    BuildAll();

    virtual
    CORBA::Boolean 
    Build(CORBA::Boolean theIsBuildAll,
	  CORBA::Boolean theIsAtOnce);

    virtual
    CORBA::Boolean
    ExportMED(const char* theFileName);

    virtual
    CORBA::Boolean
    IsDone();

    virtual
    CORBA::Boolean
    IsEntitiesDone();

    virtual
    void
    SetBuildFields(CORBA::Boolean theIsBuildFields, 
		   CORBA::Boolean theIsCalculateMinMax);

    virtual
    CORBA::Boolean
    IsFieldsDone();

    virtual
    void 
    SetBuildGroups(CORBA::Boolean theIsBuildGroups);

    virtual
    CORBA::Boolean
    IsGroupsDone();

    virtual
    CORBA::Boolean
    IsMinMaxDone();

    virtual
    CORBA::Boolean 
    IsPartsDone();

    virtual
    VISU::Result::EntityNames* 
    GetMeshNames();

    virtual
    VISU::Result::Entities* 
    GetEntities(const char* theMeshName);

    virtual
    VISU::Result::EntityNames* 
    GetFamilies(const char* theMeshName, 
		Entity theEntity);

    virtual
    VISU::Result::EntityNames* 
    GetGroups(const char* theMeshName);

    virtual
    VISU::Result::EntityNames*
    GetFields(const char* theMeshName, 
	      Entity theEntity);

    virtual
    VISU::Result::TimeStampNumbers* 
    GetTimeStampNumbers(const char* theMeshName, 
			Entity theEntity, 
			const char* theFieldName);

    virtual
    CORBA::Long 
    GetNumberOfComponents(const char* theMeshName, 
			  Entity theEntity, 
			  const char* theFieldName);

    virtual
    VISU::Result::EntityNames* 
    GetPartNames(const char* theMeshName);

    virtual
    VISU::Result::Resolutions* 
    GetResolutions(const char* theMeshName, 
		   const char* thePartName);

    virtual
    VISU::Result::Resolution
    GetResolution(const char* theMeshName, 
		  const char* thePartName);

    virtual
    void 
    SetResolution(const char* theMeshName, 
		  const char* thePartName, 
		  VISU::Result::Resolution theResolution);

    virtual 
    void
    UpdateObservers();

    virtual 
    void
    ConnectObserver(TResultObserver* theObserver,
		    boost::signalslib::connection& theConnection);

    virtual
    SALOME_MED::MedFileInfo*
    GetMEDFileInfo();
    
    typedef boost::signal0<void> TUpdateObserverSignal;

    typedef VISU_Convertor TInput;
    typedef boost::shared_ptr<TInput> PInput;

  private:
    ESourceId mySourceId;
    ECreationId myCreationId;

    PInput myInput;
    std::string myFileName;
    QFileInfo myFileInfo;
    std::string myInitFileName;

  protected:
    Result_i(SALOMEDS::Study_ptr theStudy,
	     const ESourceId& theSourceId,
	     const ECreationId& theCreationId,
	     CORBA::Boolean theIsBuildImmediately,
	     CORBA::Boolean theIsBuildFields,
	     CORBA::Boolean theIsBuildMinMax,
	     CORBA::Boolean theIsBuildGroups);

    Result_i();

    virtual
    ~Result_i();

    virtual
    Storable* 
    Build(SALOMEDS::SObject_ptr theSObject,
	  CORBA::Boolean theIsAtOnce = true) ;

    virtual
    void
    BuildDataTree(const std::string& theResultEntry);

    virtual
    Storable* 
    BuildAll(SALOMEDS::SObject_ptr theSObject) ;

    ESourceId
    GetSourceId() const;
	
    _PTR(Study) myStudy;
    CORBA::Boolean myIsBuildImmediately;

    CORBA::Boolean myIsEntitiesDone;

    CORBA::Boolean myIsFieldsDone;
    CORBA::Boolean myIsBuildFields;

    CORBA::Boolean myIsGroupsDone;
    CORBA::Boolean myIsBuildGroups;

    CORBA::Boolean myIsPartsDone;
    CORBA::Boolean myIsBuildParts;

    CORBA::Boolean myIsMinMaxDone;
    CORBA::Boolean myIsBuildMinMax;
    TUpdateObserverSignal myUpdateObserverSignal;

    CORBA::Boolean myIsAllDone;

  public:
    virtual
    size_t
    IsPossible();

    virtual
    Storable* 
    Create(const char* theFileName);

    virtual
    Storable* 
    Create(SALOMEDS::SObject_ptr theMedSObject);

    virtual
    Storable* 
    Create(SALOME_MED::FIELD_ptr theField);

    virtual
    Storable* 
    Restore(SALOMEDS::SObject_ptr theSObject,
	    const Storable::TRestoringMap& theMap,
	    const std::string& thePrefix,
	    CORBA::Boolean theIsMultiFile);

    static 
    Storable* 
    StorableEngine(SALOMEDS::SObject_ptr theSObject,
		   const Storable::TRestoringMap& theMap,
		   const std::string& thePrefix,
		   CORBA::Boolean theIsMultiFile);

    virtual 
    void
    ToStream(std::ostringstream& theStr);

    //---------------------------------------------------------------
    typedef std::string TFileName;
    typedef std::vector<TFileName> TFileNames;

    virtual 
    bool
    Save(SALOMEDS::SComponent_ptr theComponent,
	 const std::string& theURL,
	 bool theIsMultiFile,
	 bool theIsASCII,
	 TFileNames& theFileNames,
	 TFileNames& theFiles);

    //---------------------------------------------------------------
    virtual 
    CORBA::Boolean 
    CanCopy(SALOMEDS::SObject_ptr theObject);

    virtual 
    bool 
    CopyFrom(SALOMEDS::SObject_ptr theObject, 
	     CORBA::Long& theObjectID,
	     const std::string& theTmpDir,
	     TFileNames& theFileNames);

    //---------------------------------------------------------------
    virtual
    const char* 
    GetComment() const;

    static const std::string myComment;

    virtual
    PInput 
    GetInput(const std::string& theMeshName = "",
	     VISU::Entity theEntity = VISU::NONE,
	     const std::string& theFieldName = "", 
	     CORBA::Long theTimeStampNumber = -1);

    virtual
    std::string
    GetInitFileName() const;

    virtual
    void 
    SetInitFileName(const std::string& theFileName);

    virtual
    std::string
    GetFileName() const;

    QFileInfo
    GetFileInfo() const;

    ECreationId
    GetCreationId() const;
	
  private:
    SALOMEDS::SObject_var mySObject;
    SALOMEDS::Study_var myStudyDocument;
    SALOMEDS::SComponent_var mySComponent;

  public:
    std::string
    GetEntry();

    SALOMEDS::SObject_var
    GetSObject() const;

    SALOMEDS::Study_var
    GetStudyDocument() const;

    _PTR(Study) 
    GetStudy() const;

    SALOMEDS::SComponent_var
    GetSComponent() const;

    std::string
    GetEntry(const Storable::TRestoringMap& theRestoringMap);

    // Info on structured mesh contained in TInput
  public:
    typedef enum { AXIS_X = 0, AXIS_Y, AXIS_Z } TAxis;
    typedef std::vector< vtkFloatingPointType > TAxisInfo;
    const TAxisInfo* GetAxisInfo(const std::string& theMeshName,
				 TAxis              theAxis,
				 gp_Dir&            thePlaneNormal);
    // Return i,j or k values and cutting plane normal for theAxis.
    // In the case of any problems, return NULL pointer
  private:
    struct TGridInfo {
      TAxisInfo myComponets[ 3 ];
      gp_Dir    myAxis     [ 3 ];
    };
    std::map< std::string, TGridInfo > myMeshName2GridInfoMap;
  };

  //! To find Result object as published on father of the given SObject
  VISU_I_EXPORT
  Result_var 
  FindResult(SALOMEDS::SObject_ptr theSObject);

  //! To get VISU::Result object published on the given SALOMEDS::SObject
  Result_i* 
  GetResult(SALOMEDS::Study_ptr theStudy,
	    const std::string& theResultEntry);
}

#endif
