/*  PCSX2 - PS2 Emulator for PCs
 *  Copyright (C) 2002-2010  PCSX2 Dev Team
 *
 *  PCSX2 is free software: you can redistribute it and/or modify it under the terms
 *  of the GNU Lesser General Public License as published by the Free Software Found-
 *  ation, either version 3 of the License, or (at your option) any later version.
 *
 *  PCSX2 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 PCSX2.
 *  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "wx/filefn.h"
#include <memory>

// --------------------------------------------------------------------------------------
//  pxStreamBase
// --------------------------------------------------------------------------------------
class pxStreamBase
{
    DeclareNoncopyableObject(pxStreamBase);

protected:
    // Filename of the stream, provided by the creator/caller.  This is typically used *only*
    // for generating comprehensive error messages when an error occurs (the stream name is
    // passed to the exception handlers).
    wxString m_filename;

public:
    pxStreamBase(const wxString &filename);
    virtual ~pxStreamBase() = default;

    // Implementing classes should return the base wxStream object (usually either a wxInputStream
    // or wxOputStream derivative).
    virtual wxStreamBase *GetWxStreamBase() const = 0;
    virtual void Close() = 0;
    virtual wxFileOffset Tell() const = 0;
    virtual wxFileOffset Seek(wxFileOffset ofs, wxSeekMode mode = wxFromStart) = 0;

    virtual wxFileOffset Length() const;
    bool IsOk() const;
    wxString GetStreamName() const { return m_filename; }
};


// --------------------------------------------------------------------------------------
//  pxOutputStream
// --------------------------------------------------------------------------------------
class pxOutputStream : public pxStreamBase
{
    DeclareNoncopyableObject(pxOutputStream);

protected:
    std::unique_ptr<wxOutputStream> m_stream_out;

public:
    pxOutputStream(const wxString &filename, std::unique_ptr<wxOutputStream> &output);
    pxOutputStream(const wxString &filename, wxOutputStream *output);

    virtual ~pxOutputStream() = default;
    virtual void Write(const void *data, size_t size);

    void SetStream(const wxString &filename, std::unique_ptr<wxOutputStream> &stream);
    void SetStream(const wxString &filename, wxOutputStream *stream);

    void Close() { m_stream_out = nullptr; }

    virtual wxStreamBase *GetWxStreamBase() const;

    template <typename T>
    void Write(const T &data)
    {
        Write(&data, sizeof(data));
    }

    wxFileOffset Tell() const;
    wxFileOffset Seek(wxFileOffset ofs, wxSeekMode mode = wxFromStart);
};

// --------------------------------------------------------------------------------------
//  pxInputStream
// --------------------------------------------------------------------------------------
class pxInputStream : public pxStreamBase
{
    DeclareNoncopyableObject(pxInputStream);

protected:
    std::unique_ptr<wxInputStream> m_stream_in;

public:
    pxInputStream(const wxString &filename, std::unique_ptr<wxInputStream> &input);
    pxInputStream(const wxString &filename, wxInputStream *input);

    virtual ~pxInputStream() = default;
    virtual void Read(void *dest, size_t size);

    void SetStream(const wxString &filename, std::unique_ptr<wxInputStream> &stream);
    void SetStream(const wxString &filename, wxInputStream *stream);

    void Close() { m_stream_in = nullptr; }

    virtual wxStreamBase *GetWxStreamBase() const;

    template <typename T>
    void Read(T &dest)
    {
        Read(&dest, sizeof(dest));
    }

    wxFileOffset Tell() const;
    wxFileOffset Seek(wxFileOffset ofs, wxSeekMode mode = wxFromStart);
};
