// SPDX-FileComment: This file is part of TNL - Template Numerical Library (https://tnl-project.org/)
// SPDX-License-Identifier: MIT

#pragma once

#include <TNL/Algorithms/parallelFor.h>

#include "ChunkedEllpackView.h"

namespace TNL::Algorithms::Segments {

template< typename Device, typename Index, ElementsOrganization Organization >
__cuda_callable__
ChunkedEllpackView< Device, Index, Organization >::ChunkedEllpackView(
   Index size,
   Index storageSize,
   Index numberOfSlices,
   Index chunksInSlice,
   Index desiredChunkSize,
   typename Base::OffsetsView segmentToChunkMapping,
   typename Base::OffsetsView segmentToSliceMapping,
   typename Base::OffsetsView chunksToSegmentsMapping,
   typename Base::OffsetsView segmentPointers,
   typename Base::SliceInfoContainerView slices )
: Base(
     size,
     storageSize,
     numberOfSlices,
     chunksInSlice,
     desiredChunkSize,
     std::move( segmentToChunkMapping ),
     std::move( segmentToSliceMapping ),
     std::move( chunksToSegmentsMapping ),
     std::move( segmentPointers ),
     std::move( slices ) )
{}

template< typename Device, typename Index, ElementsOrganization Organization >
__cuda_callable__
void
ChunkedEllpackView< Device, Index, Organization >::bind( ChunkedEllpackView view )
{
   Base::bind(
      view.size,
      view.storageSize,
      view.numberOfSlices,
      view.chunksInSlice,
      view.desiredChunkSize,
      std::move( view.segmentToChunkMapping ),
      std::move( view.segmentToSliceMapping ),
      std::move( view.chunksToSegmentsMapping ),
      std::move( view.segmentPointers ),
      std::move( view.slices ) );
}

template< typename Device, typename Index, ElementsOrganization Organization >
__cuda_callable__
typename ChunkedEllpackView< Device, Index, Organization >::ViewType
ChunkedEllpackView< Device, Index, Organization >::getView()
{
   return { this->getElementCount(),
            this->getStorageSize(),
            this->getNumberOfSlices(),
            this->getChunksInSlice(),
            this->getDesiredChunkSize(),
            this->getSegmentToChunkMappingView(),
            this->getSegmentToSliceMappingView(),
            this->getChunksToSegmentsMappingView(),
            this->getSegmentPointersView(),
            this->getSlicesView() };
}

template< typename Device, typename Index, ElementsOrganization Organization >
__cuda_callable__
auto
ChunkedEllpackView< Device, Index, Organization >::getConstView() const -> ConstViewType
{
   return { this->getElementCount(),
            this->getStorageSize(),
            this->getNumberOfSlices(),
            this->getChunksInSlice(),
            this->getDesiredChunkSize(),
            this->getSegmentToChunkMappingView(),
            this->getSegmentToSliceMappingView(),
            this->getChunksToSegmentsMappingView(),
            this->getSegmentPointersView(),
            this->getSlicesView() };
}

template< typename Device, typename Index, ElementsOrganization Organization >
void
ChunkedEllpackView< Device, Index, Organization >::save( File& file ) const
{
   file.save( &this->size );
   file.save( &this->storageSize );
   file.save( &this->numberOfSlices );
   file.save( &this->chunksInSlice );
   file.save( &this->desiredChunkSize );
   file << this->segmentToChunkMapping << this->segmentToSliceMapping << this->chunksToSegmentsMapping << this->segmentPointers
        << this->slices;
}

template< typename Device, typename Index, ElementsOrganization Organization >
void
ChunkedEllpackView< Device, Index, Organization >::load( File& file )
{
   file.load( &this->size );
   file.load( &this->storageSize );
   file.load( &this->numberOfSlices );
   file.load( &this->chunksInSlice );
   file.load( &this->desiredChunkSize );
   file >> this->segmentToChunkMapping >> this->segmentToSliceMapping >> this->chunksToSegmentsMapping >> this->segmentPointers
      >> this->slices;
}

}  // namespace TNL::Algorithms::Segments
