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

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/VolViewCopyright.htm 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 <iostream>

#include "vtksys/CommandLineArguments.hxx"
#include "vtksys/SystemTools.hxx"

#include "vtkXMLDataElement.h"
#include "vtkXMLUtilities.h"

#include "vtkVVFileInstancePool.h"
#include "vtkVVFileInstance.h"
#include "vtkVVSnapshotPool.h"
#include "vtkVVSnapshot.h"

#include "vtkVVDataItemPool.h"
#include "vtkVVDataItemVolume.h"
#include "vtkVVLODDataItemVolumeHelper.h"

#include "XML/vtkXMLVVFileInstancePoolReader.h"
#include "XML/vtkXMLVVDataItemPoolReader.h"
#include "XML/vtkXMLVVSnapshotPoolReader.h"

int main(int argc, char *argv[])
{
  // Parse the command line args

  typedef vtksys::CommandLineArguments cmd_args_type;
  cmd_args_type cmd_args;
  cmd_args.Initialize(argc, argv);

  // We need a session file

  char *session_file = NULL;
  cmd_args.AddArgument(
    "--session", cmd_args_type::SPACE_ARGUMENT, &session_file, " "); 
  
  cmd_args.Parse();

  // Seriously: we need that session file

  if (!session_file)
    {
    std::cout << "[FAILED] Missing arg: --session file" << std::endl;
    return EXIT_FAILURE;
    }

  if (!vtksys::SystemTools::FileExists(session_file))
    {
    std::cout << "[FAILED] Can not find: " << session_file << std::endl;
    return EXIT_FAILURE;
    }

  // First read the XML session file

  vtkXMLDataElement *xml = vtkXMLUtilities::ReadElementFromFile(session_file);
  if (!xml)
    {
    std::cout << "[FAILED] Can not parse: " << session_file << std::endl;
    return EXIT_FAILURE;
    }

  // Let's dig inside to find the file instance pool
  // using FindNestedElementWithName and parse the contents with an XML reader
  // This will give us the list of files loaded at the time the session
  // was saved.

  int res = EXIT_SUCCESS;

  vtkVVFileInstancePool *fip = NULL;
  vtkXMLObjectReader *fip_xmlr = NULL;
  vtkXMLDataElement *fip_xml = NULL;

  int fi_idx, f_idx;

  fip = vtkVVFileInstancePool::New();
  fip_xmlr = fip->GetNewXMLReader();
  fip_xml = xml->LookupElementWithName(fip_xmlr->GetRootElementName());

  if (!fip_xml)
    {
    std::cout << "[FAILED] Can not find XML element: " 
              << fip_xmlr->GetRootElementName() << std::endl;
    res = EXIT_FAILURE;
    }
  else
    {
    if (!fip_xmlr->Parse(fip_xml))
      {
      std::cout << "[FAILED] Can not parse XML element: " 
                << fip_xmlr->GetRootElementName() << std::endl;
      res = EXIT_FAILURE;
      }
    else
      {
      for (fi_idx = 0; fi_idx < fip->GetNumberOfFileInstances(); fi_idx++)
        {
        vtkVVFileInstance *fi = fip->GetNthFileInstance(fi_idx);
        if (fi)
          {
          std::cout << "File instance #" << fi_idx << std::endl;
          for (f_idx = 0; f_idx < fi->GetNumberOfFileNames(); f_idx++)
            {
            const char *fn = fi->GetNthFileName(f_idx);
            if (fn)
              {
              std::cout << "  - Filename #" << f_idx << ": " << fn << std::endl;
              }
            }
          }
        }
      }
    }

  // Let's dig inside to find the snapshot pool and parse the contents
  // with an XML reader as well.
  // This will give us the list of files that *could* be loaded if the user
  // selected a specific snapshot from the session file.

  vtkVVSnapshotPool *sp = vtkVVSnapshotPool::New();
  vtkXMLObjectReader *sp_xmlr = sp->GetNewXMLReader();
  vtkXMLDataElement *sp_xml = xml->LookupElementWithName(
    sp_xmlr->GetRootElementName());
  if (sp_xml)
    {
    if (!sp_xmlr->Parse(sp_xml))
      {
      std::cout << "[FAILED] Can not parse Snapshot Pool XML element: " 
                << sp_xmlr->GetRootElementName() << std::endl;
      res = EXIT_FAILURE;
      }
    else
      {
      int s_idx;
      for (s_idx = 0; s_idx < sp->GetNumberOfSnapshots(); s_idx++)
        {
        vtkVVSnapshot *s = sp->GetNthSnapshot(s_idx);
        if (s)
          {
          std::cout << "-------------------------------------------------------------" << endl;
          std::cout << "Snapshot #" << s_idx << " (" << 
            s->GetDescription() << ")" << std::endl;

          // Now parse the file instance pool inside each snapshot the same way

          fip_xml = s->GetSerializedForm()->LookupElementWithName(
            fip_xmlr->GetRootElementName());
          if (fip_xml)
            {
            if (!fip_xmlr->Parse(fip_xml))
              {
              std::cout << "[FAILED] Can not parse XML element: " 
                        << fip_xmlr->GetRootElementName() << std::endl;
              res = EXIT_FAILURE;
              }
            else
              {
              for (fi_idx = 0;fi_idx < fip->GetNumberOfFileInstances();fi_idx++)
                {
                vtkVVFileInstance *fi = fip->GetNthFileInstance(fi_idx);
                if (fi)
                  {
                  std::cout << "File instance #" << fi_idx << std::endl;
                  for (f_idx = 0; f_idx < fi->GetNumberOfFileNames(); f_idx++)
                    {
                    const char *fn = fi->GetNthFileName(f_idx);
                    if (fn)
                      {
                      std::cout << "  - Filename #" 
                                << f_idx << ": " << fn << std::endl;
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  
  fip->Delete();
  fip_xmlr->Delete();

  // Let's dig inside to find the data item pool
  // using FindNestedElementWithName and parse the contents with an XML reader
  // This will give us the list of data item loaded at the time the session
  // was saved.

  vtkVVDataItemPool *dip = NULL;
  vtkXMLObjectReader *dip_xmlr = NULL;
  vtkXMLDataElement *dip_xml = NULL;

  int di_idx;

  dip = vtkVVDataItemPool::New();
  dip_xmlr = dip->GetNewXMLReader();
  dip_xml = xml->LookupElementWithName(dip_xmlr->GetRootElementName());

  if (!dip_xml)
    {
    std::cout << "[FAILED] Can not find XML element: " 
              << dip_xmlr->GetRootElementName() << std::endl;
    res = EXIT_FAILURE;
    }
  else
    {
    if (!dip_xmlr->Parse(dip_xml))
      {
      std::cout << "[FAILED] Can not parse XML element: " 
                << dip_xmlr->GetRootElementName() << std::endl;
      res = EXIT_FAILURE;
      }
    else
      {
      for (di_idx = 0; di_idx < dip->GetNumberOfDataItems(); di_idx++)
        {
        vtkVVDataItem *di = dip->GetNthDataItem(di_idx);
        if (di)
          {
          std::cout << "Data item #" << di_idx << std::endl;
          vtkVVDataItemVolume *div = vtkVVDataItemVolume::SafeDownCast(di);
          if (div && div->GetLODHelper())
            {
            std::cout << "  LOD Compression Ratio: " << div->GetLODHelper()->GetCompressionRatio() << std::endl;
            }
          }
        }
      }
    }

  // Let's dig inside to find the snapshot pool and parse the contents
  // with an XML reader as well.
  // This will give us the list of data items that *could* be loaded if the
  // user selected a specific snapshot from the session file.

  int s_idx;
  for (s_idx = 0; s_idx < sp->GetNumberOfSnapshots(); s_idx++)
    {
    vtkVVSnapshot *s = sp->GetNthSnapshot(s_idx);
    if (s)
      {
      std::cout << "-------------------------------------------------------------" << endl;
      std::cout << "Snapshot #" << s_idx << " (" << 
        s->GetDescription() << ")" << std::endl;
      
      // Now parse the data item pool inside each data item the same way

      dip_xml = s->GetSerializedForm()->LookupElementWithName(
        dip_xmlr->GetRootElementName());
      if (dip_xml)
        {
        if (!dip_xmlr->Parse(dip_xml))
          {
          std::cout << "[FAILED] Can not parse XML element: " 
                    << dip_xmlr->GetRootElementName() << std::endl;
          res = EXIT_FAILURE;
          }
        else
          {
          for (di_idx = 0;di_idx < dip->GetNumberOfDataItems();di_idx++)
            {
            vtkVVDataItem *di = dip->GetNthDataItem(di_idx);
            if (di)
              {
              std::cout << "Data item #" << di_idx << std::endl;
              vtkVVDataItemVolume *div = vtkVVDataItemVolume::SafeDownCast(di);
              if (div && div->GetLODHelper())
                {
                std::cout << "  LOD Compression Ratio: " << div->GetLODHelper()->GetCompressionRatio() << std::endl;
                }
              }
            }
          }
        }
      }
    }
  
  dip->Delete();
  dip_xmlr->Delete();

  sp->Delete();
  sp_xmlr->Delete();

  // Bye

  xml->Delete();

  if (res == EXIT_SUCCESS)
    {
    std::cout << "[PASSED]" << std::endl;
    }

  return res;
}
