//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
//
//  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
//

//  File   : VISU_ElnoMeshValue.hxx
//  Author : Alexey PETROV
//  Module : VISU
//
#ifndef VISU_ElnoMeshValue_HeaderFile
#define VISU_ElnoMeshValue_HeaderFile

#include "VISU_VTKTypeList.hxx"
#include <vtkDataSetAttributes.h>


/*! 
  \file VISU_ElnoMeshValue.hxx
  \brief The file contains declarations for the acess to the specific ELNO MED data
*/

namespace VISU
{
  //---------------------------------------------------------------
  template< int elno_type >
  struct TGetElnoNodeData
  {
    typedef typename TL::TEnum2VTKArrayType< elno_type >::TResult TVTKDataArray;
    typedef typename TL::TEnum2VTKBasicType< elno_type >::TResult TDataType;
    TVTKDataArray *myElnoDataArray;
    vtkIntArray *myElnoDataMapper;
    int myElemInfo[3];


    //----------------------------------------------------------------------------
    TGetElnoNodeData( vtkDataArray *theElnoDataArray,
                      vtkDataArray *theElnoDataMapper )
      : myElnoDataArray( TVTKDataArray::SafeDownCast( theElnoDataArray ) )
      , myElnoDataMapper( vtkIntArray::SafeDownCast( theElnoDataMapper ) )
    {}


    //----------------------------------------------------------------------------
    TDataType*
    operator () ( vtkIdType theCellId, vtkIdType theLocalPntId )
    {
      myElnoDataMapper->GetTupleValue( theCellId, myElemInfo );

      vtkIdType aPos = myElemInfo[ 0 ] + theLocalPntId * myElemInfo[ 1 ];

      return myElnoDataArray->GetPointer( aPos );
    }


    //----------------------------------------------------------------------------
    int
    getNbComp()
    {
      myElnoDataMapper->GetTupleValue( 0, myElemInfo );

      return myElemInfo[ 1 ];
    }
  };


  //----------------------------------------------------------------------------------------------
  template< int elno_type >
  struct TSetElnoNodeData
  {
    typedef typename TL::TEnum2VTKArrayType< elno_type >::TResult TVTKDataArray;
    typedef typename TL::TEnum2VTKBasicType< elno_type >::TResult TDataType;

    //----------------------------------------------------------------------------------------------
    TSetElnoNodeData( vtkIdType theEffectNbComp,
                      vtkIdType theRealNbComp,
                      vtkIdType theNbTuples,
                      const char* theDataArrayName,
                      const char* theMapperArrayName )
      : myElnoDataArray( TVTKDataArray::New() )
      , myElnoDataMapper( vtkIntArray::New() )
    {
      myElnoDataArray->SetNumberOfComponents( theEffectNbComp );
      myElnoDataArray->SetNumberOfTuples( theNbTuples );
      myElnoDataArray->SetName( theDataArrayName );

      myElnoDataMapper->SetNumberOfComponents( 3 );
      myElnoDataMapper->Allocate( theNbTuples * 3 );
      myElnoDataMapper->SetName( theMapperArrayName );

      myElemInfo[ 0 ] = 0;
      myElemInfo[ 1 ] = theRealNbComp;
      myElemInfo[ 2 ] = 0;
    }


    //----------------------------------------------------------------------------------------------
    ~TSetElnoNodeData()
    {
      myElnoDataArray->Delete();
      myElnoDataMapper->Delete();
    }


    //----------------------------------------------------------------------------------------------
    int
    AddNextPointData( TDataType* theDataPtr )
    {
      vtkIdType aPos = myElemInfo[ 0 ] + myElemInfo[ 2 ] * myElemInfo[ 1 ];

      TDataType* aDataPtr = myElnoDataArray->GetPointer( aPos );

      for ( vtkIdType aCompId = 0; aCompId < myElemInfo[ 1 ]; aCompId++ )
        *aDataPtr++ = *theDataPtr++;

      return myElemInfo[ 2 ]++;
    }


    //----------------------------------------------------------------------------------------------
    void
    InsertNextCellData()
    {
      myElnoDataMapper->InsertNextTupleValue( myElemInfo );
      myElemInfo[ 0 ] += myElemInfo[ 2 ] * myElemInfo[ 1 ];
      myElemInfo[ 2 ] = 0;
    }


    //----------------------------------------------------------------------------------------------
    void
    AddData( vtkDataSetAttributes* theDataSetAttributes )
    {
      theDataSetAttributes->AddArray( myElnoDataArray );
      theDataSetAttributes->AddArray( myElnoDataMapper );
    }

  protected:
    TVTKDataArray *myElnoDataArray;
    vtkIntArray *myElnoDataMapper;
    int myElemInfo[ 3 ];
  };


  //---------------------------------------------------------------
}

#endif
