/// Basic3DOutputter.h
/**
*/

#ifndef BASIC_3D_OUTPUTTER_H_
#define BASIC_3D_OUTPUTTER_H_

#include <string>

#include "OutputterBase.h"
#include "SeriesHandler.h"

namespace jcs {

  class BasicVolumeFormat;
  struct Basic3DHeader;

  /// Handles header+raw volume types
  /**
    */
  class Basic3DOutputter : public OutputterBase {

  public :
    Basic3DOutputter(const Options& options);

    virtual ~Basic3DOutputter();

    virtual void UpdateOutputForSeries(SeriesHandler* handler);
    virtual int ConvertSeries(SeriesHandler* handler) = 0;
    virtual void RemoveSeries(const std::string& seriesUid);

    virtual BasicVolumeFormat* GetOutputVolume(const char* file) = 0;

    // following only used internally or by basic conversion
    wxFileName GetFileNameFromVolId(const VolId& VolId);

    int GetDimensionality() const { return dim_; }
    int GetDimensionality(const std::string& series_uid);
    void SetDimensionality(int dim) { dim_ = dim; }
    void SetDimensionality(const std::string& series_uid, int dim);

    int GetSkip() const { return skip_; }
    int GetSkip(const std::string& series_uid);
    void SetSkip(int skip) { skip_ = skip; }
    void SetSkip(const std::string& series_uid, int skip);

    bool GetRescale() const { return rescale; }
    bool GetRescale(const std::string& series_uid);
    void SetRescale(bool value) { rescale = value; }
    void SetRescale(const std::string& series_uid, bool value);

    virtual void SetOption(const std::string& name, int value);
    virtual void SetOption(const std::string& name, bool value);

    /// Filename extension for header file.
    wxString headerExtension;
    /// Filename extension for image/raw data file.
    wxString rawExtension;
    bool rescale;
    std::string bvecs_postfix;
    std::string bvals_postfix;
    std::string moco_postfix;
    std::string info_postfix;
    std::string txt_ext;

  protected:
    std::map<VolId, std::string> volKeyMap;
    static Options Get3DOptions();

  private:
    int dim_;
    int skip_;
    void RegisterOutputFile(std::string series_uid, std::string ext, std::string postfix, SeriesHandler* handler);

  };

  template <class T>
  class Basic3DConversion {

  public:
    Basic3DConversion(Basic3DOutputter* outputter, SeriesHandler* handler);
    ~Basic3DConversion() {}
    virtual void Convert();
    typedef std::map <VolId, Volume<T> > vMapType;

  protected:
    virtual void GetHeaderForSeries() = 0;
    virtual void CompleteHeaderForVolume(std::pair<VolId, Volume<T> > volPair) { }

    virtual void ProcessSlice(std::vector<T>& slice) { }
    virtual Basic3DHeader* GetHeader() = 0; 

    int GetSkip();
    int GetNumberOfVolumes();
    void ProcessSlicesAndAppend(BasicVolumeFormat* outputVolume, typename vMapType::iterator it);

    Basic3DOutputter* mOutputter;
    SeriesHandler* mHandler;
    void WriteGradientFiles();

  private:
    void WriteMoCoFiles();
    void WriteStringInfo();
    void IterativeWrite(wxFileName fileName, std::vector<std::string> src);
  };
}

#include "Basic3DConversion.txx"

#endif
