/******************************************************************************
 *
 *  This file is part of the Data Logging Service (DLS).
 *
 *  DLS is free software: you can redistribute it and/or modify it under the
 *  terms of the GNU General Public License as published by the Free Software
 *  Foundation, either version 3 of the License, or (at your option) any later
 *  version.
 *
 *  DLS is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 *  details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with DLS. If not, see <http://www.gnu.org/licenses/>.
 *
 *****************************************************************************/

#ifndef LibDLSExportH
#define LibDLSExportH

/*****************************************************************************/

#include <fstream>
#include <memory>

#include "Exception.h"
#include "Channel.h"
#include "Job.h"
#include "Dir.h"
#include "globals.h"

/*****************************************************************************/

namespace LibDLS
{
    class File;

    /*************************************************************************/

    class DLS_PUBLIC ExportException:
        public Exception
    {
    public:
        ExportException(const std::string &pmsg): Exception(pmsg) {};
    };

    /*************************************************************************/

    typedef struct
    {
        long type;
        long mrows;
        long ncols;
        long imagf;
        long namelen;
    }
    Mat4Header;

    /*************************************************************************/

    class DLS_PUBLIC Export
    {
    public:
        Export();
        virtual ~Export();

        void setReferenceTime(const Time &);
        void setTrim(const Time &, const Time &);

        virtual void open(const std::string &,
                const std::string &,
                const Time &start, const Time &end);
        virtual void close();
        virtual void begin(
            const Directory &,
            const Channel &,
            const std::string &,
            const std::string & = std::string()
            ) = 0;
        virtual void data(const Data *) = 0;
        virtual void end() = 0;
        virtual void addMessage(const Job::Message &);

    protected:
        class Impl;
        std::unique_ptr<Impl> const _impl;

        explicit Export(Impl * impl);
    };

    /*************************************************************************/

    class DLS_PUBLIC ExportAscii:
        public Export
    {
    public:
        ExportAscii();
        ~ExportAscii();

        void begin(
            const Directory &,
            const Channel &,
            const std::string &,
            const std::string & = std::string()
            );
        void data(const Data *);
        void end();

    private:
        std::ofstream _file;
    };

    /*************************************************************************/

    class DLS_PUBLIC ExportMat4:
        public Export
    {
    public:
        ExportMat4();
        ~ExportMat4();

        void begin(
            const Directory &,
            const Channel &,
            const std::string &,
            const std::string & = std::string()
            );
        void data(const Data *);
        void end();

    private:
        Mat4Header _header;
        File *_file;
    };

    /*************************************************************************/

    /* HDF-5 support may be disabled in the library. In this case you will get
     * a linker error complaining about an undefined reference.
     */
    class ExportHDF5:
        public Export
    {
    public:
        ExportHDF5();
        ~ExportHDF5();

        void open(const std::string &,
                const std::string &,
                const Time &start, const Time &end);
        void close();
        void begin(
            const Directory &,
            const Channel &,
            const std::string &,
            const std::string & = std::string()
            );
        void data(const Data *);
        void end();
        void addMessage(const Job::Message &);

    private:
        class ImplHDF5;
    };
}

/*****************************************************************************/

#endif
