/*=========================================================================

  Program:   ParaView
  Module:    vtkStreamingTerrainMapper.cxx

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkStreamingTerrainMapper.h"

#include "vtkObjectFactory.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkPolyData.h"
#include "vtkBoundingBox.h"
#include "vtkDataObjectTreeIterator.h"
#include "vtkCompositeDataDisplayAttributes.h"
#include "vtkCamera.h"
#include "vtkRenderer.h"

namespace
{

struct Item
{
  vtkBoundingBox Box;
  unsigned int Index;
  unsigned int Level;
  vtkIdType CellCount;
};

double compute_coverage(const vtkBoundingBox& box, vtkRenderer* ren)
{
  vtkBoundingBox dbox;
  for (int cc=0; cc < 6; ++cc)
  {
    double corner[3];
    bbox.GetCorner(cc, corner);
    ren->WorldToView(corner[0], corner[1], corner[2]);
    ren->ViewToNormalizedViewport(corner[0], corner[1], corner[2]);
    dbox.AddPoint(corner);
  }

}

void prioritize(std::vector<Item>& boxes, vtkRenderer* ren)
{
  for (auto &item : boxes)
  {
    if (!item.Box.IsValid())
    {
      continue;
    }

    double coverage = compute_coverage(item.Box, ren);
  }
}

}

#include <vector>
#include <utility>

vtkStandardNewMacro(vtkStreamingTerrainMapper);
//----------------------------------------------------------------------------
vtkStreamingTerrainMapper::vtkStreamingTerrainMapper()
{
  vtkCompositeDataDisplayAttributes* compositeAttributes = vtkCompositeDataDisplayAttributes::New();
  this->SetCompositeDataDisplayAttributes(compositeAttributes);
  compositeAttributes->Delete();
}

//----------------------------------------------------------------------------
vtkStreamingTerrainMapper::~vtkStreamingTerrainMapper()
{
}

//----------------------------------------------------------------------------
void vtkStreamingTerrainMapper::Render(vtkRenderer* ren, vtkActor* actor)
{
  if (auto* input = vtkMultiBlockDataSet::SafeDownCast(this->GetInputDataObject(0, 0)))
  {
    unsigned int num_levels = input->GetNumberOfBlocks();

    auto level0 = vtkMultiBlockDataSet::SafeDownCast(input->GetBlock(0));
    unsigned int num_blocks = level0->GetNumberOfBlocks();

    std::vector<Item> boxes;
    for (unsigned int cc=0; cc < num_blocks; ++cc)
    {
      Item item;
      item.Index = cc;
      item.Level = 0;
      item.CellCount = 0;
      if (auto pd = vtkPolyData::SafeDownCast(level0->GetBlock(cc)))
      {
        double bds[6];
        pd->GetBounds(bds);
        item.CellCount = pd->GetNumberOfCells();
        item.Box.SetBounds(bds);
      }
      boxes.push_back(item);
    }

    prioritize(boxes, ren);

    // update visibilities for blocks
    for (unsigned int l=0; l < num_levels; ++l)
    {
      auto level = vtkMultiBlockDataSet::SafeDownCast(input->GetBlock(0));
      for (const auto& item : boxes)
      {
        if (auto block = vtkPolyData::SafeDownCast(level->GetBlock(item.Index)))
        {
          this->CompositeAttributes->SetBlockVisibility(block, (item.Level == l));
        }
      }
    }
  }
  this->Superclass::Render(ren, actor);
}


//----------------------------------------------------------------------------
void vtkStreamingTerrainMapper::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}
