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

  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.

=========================================================================*/
// .NAME vtkKWOpenWizard - a class to load data into VV

#ifndef __vtkKWOpenWizard_h
#define __vtkKWOpenWizard_h

#include "vtkKWWizard.h"

class vtkAlgorithm;
class vtkImageReader2;
class vtkStringArray;
class vtkImageData;
class vtkUnstructuredGrid;

class vtkKWOpenFileProperties;
class vtkKWCheckButton;
class vtkKWColorImageConversionFilter;
class vtkKWEntry;
class vtkKWEntryWithLabel;
class vtkKWImageWidget;
class vtkKWLabel;
class vtkKWLabelWithLabel;
class vtkKWLoadSaveDialog;
class vtkKWMenuButton;
class vtkKWMenuButtonWithLabel;
class vtkKWOpenFileHelper;
class vtkKWOrientationFilter;
class vtkKWPushButton;
class vtkKWRadioButtonSet;
class vtkKWWindow;
class vtkKWSpinBoxWithLabel;

class vtkDICOMCollectorOptions;
class vtkKWOpenWizardInternals;

class VTK_EXPORT vtkKWOpenWizard : public vtkKWWizard
{
public:
  static vtkKWOpenWizard* New();
  vtkTypeRevisionMacro(vtkKWOpenWizard,vtkKWWizard);
  void PrintSelf(ostream& os, vtkIndent indent);

  // Description:
  // Invoke the dialog and display it in a modal manner.  This method returns
  // a zero if the dialog was killed or canceled, nonzero otherwise.  If
  // verbosity is INVOKE_QUIET, then the Wizard will try not to query 
  // anything from the user. After the invoke call you can call Load which
  // will actually load and orient the data.
  //BTX
  enum
  {
    INVOKE_QUIET = 0,
    INVOKE_VERBOSE = 1
  };
  //ETX
  virtual int Invoke();
  virtual int InvokeQuiet();
  virtual int Invoke(const char *fileName, int verbosity);
  virtual int Invoke(vtkStringArray *fileNames, int verbosity);

  // Description:
  // Load the data from a specific output port (or the first one, 0);
  virtual void Load(int output_port);
  virtual void Load() { this->Load(0); };

  // Description:
  // Release the data from a specific output port (or the first one, 0);
  virtual void Release(int output_port);
  virtual void Release() { this->Release(0); };

  // Description:
  // Return the ImageData output from the source reader or filter, or
  // just the source reader/filter, for a given port (or the first one, 0)
  virtual vtkImageData *GetOutput(int output_port);
  virtual vtkImageData *GetOutput() { return this->GetOutput(0); };

  // Description:
  // Return the ImageData output from the source reader or filter, or
  // just the source reader/filter, for a given port (or the first one, 0)
  virtual vtkUnstructuredGrid *GetUnstructuredGridOutput(int output_port);
  virtual vtkUnstructuredGrid *GetUnstructuredGridOutput() { return this->GetUnstructuredGridOutput(0); };

  // Description:
  // Return the ImageData output corresponding to the i-th image from a series
  virtual vtkImageData *GetSeriesOutput(int, int output_port);

  // Description:
  // Once Invoke() or Load() have been invoked, ReadyToLoad should be
  // set to one of the following values
  //BTX
  enum
  {
    DATA_IS_UNAVAILABLE   = 0,
    DATA_IS_READY_TO_LOAD = 1,
    DATA_IS_LOADED        = 2
  };
  //ETX
  vtkGetMacro(ReadyToLoad, int);

  // Description: 
  // Get the OpenFileHelper internal instance.
  vtkGetObjectMacro(OpenFileHelper, vtkKWOpenFileHelper);  

  // Description: 
  // When the OpenFileHelper's IsFileValid returns a value of FILE_IS_VALID, 
  // it sets the internal values of this vtkKWOpenFileProperties object to
  // hold the properties of that file.
  virtual vtkKWOpenFileProperties* GetOpenFileProperties();

  // Description:
  // Set/Get how if the current open file properties should be kept untouched
  // to open the file later on. Set to Off by default; the default behavior
  // is that Invoke() will check several readers to find which one can
  // read our file; by doing so, it will already modify the internal open
  // file properties with value relevant to the reader (i.e. what the 
  // reader found about the data, it's scalar type, etc). Then, unless
  // IgnoreVVIOnRead is true, an attempt is made to read the .VVI file
  // corresponding to the file being opened. When found, the properties inside
  // that VVI file will override all or some of the open file properties.
  // Finally, if the wizard was not called in quiet mode, the GUI will 
  // pop up, allowing the user to fine-tune or override the open file 
  // properties. Once the user is done with the wizard, the final properties
  // are written to the .VVI file, so that the next time we open, they
  // can be retrieved automatically.
  // Set this variable to On if you want to manually set the current
  // OpenFileProperties object and make sure those are the variables used
  // to either open the file or as starting point values for the GUI.
  // See also, IgnoreVVIOnRead, IgnoreVVIOnWrite. 
  vtkBooleanMacro(OpenWithCurrentOpenFileProperties, int);
  vtkSetMacro(OpenWithCurrentOpenFileProperties, int);
  vtkGetMacro(OpenWithCurrentOpenFileProperties, int);

  // Description:
  // Return the reader to be used for reading in the data
  virtual vtkAlgorithm* GetLastReader();
  virtual void SetLastReader(vtkAlgorithm *);

  // Description:
  // Set/Get the file name(s)
  virtual void SetFileName(const char *);
  virtual const char *GetFileName();
  vtkGetObjectMacro(FileNames, vtkStringArray);  

  // Description:
  // Get the LoadSaveDialog used for prompting filenames
  // Note that the LoadSaveDialog is not instantied until Create()
  // is called.
  vtkGetObjectMacro(LoadDialog,vtkKWLoadSaveDialog);  

  // Description:
  // Query the data filename.
  virtual int QueryForFileName(const char *title = 0);

  // Description:
  // Close this Wizard
  virtual void Cancel();

  // Description:
  // Read/Write VVI for a given data file
  // ReadVVIForFile returns 0 on error (!= 0 if OK)
  // ReadVVIForFile will modify the internal OpenFileProperties with the
  // values found in the VVI file.
  virtual int ReadVVIForFile(const char *fname);
  virtual void WriteVVIForFile(const char *fname);

  // Description:
  // Set/Get if VVI files should be ignored when reading a file, or when
  // it's time to write VVI on disk
  vtkBooleanMacro(IgnoreVVIOnRead, int);
  vtkSetMacro(IgnoreVVIOnRead, int);
  vtkGetMacro(IgnoreVVIOnRead, int);
  vtkBooleanMacro(IgnoreVVIOnWrite, int);
  vtkSetMacro(IgnoreVVIOnWrite, int);
  vtkGetMacro(IgnoreVVIOnWrite, int);

  // Description:
  // Add a user-defined valid file extension
  // If that extension is recognized, the internal OpenFileHelper's 
  // IsFileValid method will automatically return
  // FILE_IS_VALID_NOT_DATA. Extension includes the period (e.g. ".txt").
  // The exension can be a space-separated list of extensions.
  // This method just forwards its parameters to the open helper.
  virtual void AddValidFileExtension(
    const char *description, const char *extension);

  // Description:
  // These methods are the main methods called to display the different pages
  // of the wizard
  virtual int PromptRaw();
  virtual int ValidateRaw();
  virtual int PromptRawInfo();
  virtual int ValidateRawInfo();
  virtual int PromptMultiplicity();
  virtual int ValidateMultiplicity();
  virtual int PromptSeries();
  virtual int ValidateSeries();
  virtual int PromptScope();
  virtual int ValidateScope();
  virtual int PromptSpatialAttributes();
  virtual int ValidateSpatialAttributes();
  virtual int PromptComponents();
  virtual int ValidateComponents();
  virtual int PromptUnits();
  virtual int ValidateUnits();
  virtual int PromptOrientation();
  virtual int ValidateOrientation();
  
  // Description:
  // Callbacks for GUI components
  virtual void SeriesPatternCallback(const char*);
  virtual void SeriesExtentCallback(int);
  virtual void OrientationCallback();
  virtual void ScalarTypeCallback();
  virtual void ByteOrderCallback();
  virtual void ScalarComponentsCallback();
  virtual void RawDimensionCallback(int);
  virtual void SetupRawPreviewCallback();

protected:
  vtkKWOpenWizard();
  ~vtkKWOpenWizard();

  // Description:
  // Series file names
  vtkStringArray *FileNames;

  // Description:
  // Create the widget
  virtual void CreateWidget();

  // Description:
  // Invoke
  virtual int Invoke(int verbosity);

  // Description:
  // Set the previous reader
  virtual void SetPreviousReader(vtkAlgorithm *);

  // Description:
  // Adjust the orientation filter given the current UI choices
  virtual void AdjustOrientationFilter();
  
  // Description:
  // Create the UI panels
  virtual void CreateMultiplicityFrame();
  virtual void CreateRawInfoFrame();
  virtual void CreateSeriesFrame();
  virtual void CreateScopeFrame();
  virtual void CreateSpatialAttributesFrame();
  virtual void CreateComponentsFrame();
  virtual void CreateUnitsFrame();
  virtual void CreateOrientationFrame();

  // Description:
  // Return the string pattern, minimum value and maximum value used to define
  // a input series. The values returned by these methods are only valid after
  // the invokation of the methods PromptSeries() and ValidateSeries().
  virtual const char *GetSeriesPattern();
  virtual int   GetSeriesMinimum();
  virtual int   GetSeriesMaximum();
  virtual void  SetSeriesPattern( const char * );
  virtual void  SetSeriesMinimum(int);
  virtual void  SetSeriesMaximum(int);

  // Description:
  // Check if the current parameters are OK
  virtual int AreRawFileValuesLargerThanFileSize();
  virtual int AreRawFileValuesReasonable();
  virtual int AreOrientationValuesReasonable();
  virtual int AreSeriesValuesReasonable();
  
  int OpenWithCurrentOpenFileProperties;
  int IgnoreVVIOnRead;
  int IgnoreVVIOnWrite;

  // Description:
  virtual void SetupRawPreview();
  virtual void ScheduleSetupRawPreview();

  // Description:
  // Check if a VVI file is valid. 
  // Return VVI_IS_INVALID on error (VVI_IS_VALID if OK)
  //BTX
  enum
  {
    VVI_IS_INVALID = 0,
    VVI_IS_VALID = 1,
    VVI_HAS_REQUIRED_TOKEN,
    VVI_IS_COMPLIANT
  };
  //ETX
  virtual int IsVVIValid(const char *vvi_fname);

  // Description:
  // Check if a given VVI file "includes" a data file as part as a
  // series.
  // For example, the VVI may specify a FilePattern and a WholeExent token 
  // and both will be used to check if the data file is part of this series.
  // Return VVI_IS_INVALID on error (VVI invalid or corrupted), VVI_IS_VALID is
  // the VVI is just valid, VVI_HAS_REQUIRED_TOKEN if the VVI is valid and 
  // has the required token, VVI_IS_COMPLIANT if the VVI is valid, has the 
  // required token, and is compliant (i.e. "includes" that data file).
  // At the end of the day, the value you are looking for is VVI_IS_COMPLIANT.
  virtual int DoesVVIIncludeFile(const char *vvi_fname, const char *fname);
  
  vtkKWLoadSaveDialog      *LoadDialog;

  vtkKWOpenFileHelper      *OpenFileHelper;

  vtkAlgorithm             *PreviousReader;
  vtkKWOpenFileProperties  *PreviousOpenFileProperties;

  int Invoked;
  int ReadyToLoad;
  
  vtkKWOrientationFilter   *OrientationFilter;
  vtkKWColorImageConversionFilter *ColorImageConversionFilter;


  vtkKWFrame               *SeriesFrame;
  vtkKWEntryWithLabel      *PatternEntry;
  vtkKWSpinBoxWithLabel    *KMinEntry;
  vtkKWSpinBoxWithLabel    *KMaxEntry;
  
  vtkKWFrame               *SpatialAttributesFrame;
  vtkKWLabel               *OriginLabel;
  vtkKWEntry               *OriginEntry[3];
  vtkKWLabel               *SpacingLabel;
  vtkKWEntry               *SpacingEntry[3];

  vtkKWFrame               *UnitsFrame;
  vtkKWEntryWithLabel      *DistanceUnitsEntry;
  vtkKWEntryWithLabel      *ScalarUnitsEntry[VTK_MAX_VRCOMP];
  
  vtkKWFrame               *ComponentsFrame;
  vtkKWCheckButton         *IndependentComponentsButton;

  vtkKWFrame               *ScopeFrame;
  vtkKWRadioButtonSet      *ScopeChoice;
  
  vtkKWFrame               *OrientationFrame;
  vtkKWMenuButtonWithLabel *SliceAxisMenu;
  vtkKWMenuButtonWithLabel *RowAxisMenu;
  vtkKWMenuButtonWithLabel *ColumnAxisMenu;

  vtkKWFrame               *MultiplicityFrame;
  vtkKWRadioButtonSet      *MultiplicityChoice;

  vtkKWFrame               *RawInfoFrame;
  vtkKWSpinBoxWithLabel    *IDimEntry;
  vtkKWSpinBoxWithLabel    *JDimEntry;
  vtkKWSpinBoxWithLabel    *KDimEntry;
  vtkKWMenuButtonWithLabel *ScalarTypeMenu;
  vtkKWMenuButtonWithLabel *ByteOrderMenu;
  vtkKWMenuButtonWithLabel *ScalarComponentsMenu;
  vtkKWImageWidget         *Preview;
  vtkImageReader2          *PreviewReader;

  // PIMPL Encapsulation for STL containers
  //BTX
  vtkKWOpenWizardInternals *Internals;
  //ETX

private:
  vtkKWOpenWizard(const vtkKWOpenWizard&); // Not implemented
  void operator=(const vtkKWOpenWizard&); // Not Implemented
};

#endif
