/* Copyright (C) 2007 The giomm Development Team
 *
 * This library 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 Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <glibmm/object.h>

#include <giomm/inputstream.h>
#include <giomm/outputstream.h>
#include <giomm/asyncresult.h>
#include <giomm/cancellable.h>

_DEFS(giomm,gio)
_PINCLUDE(glibmm/private/object_p.h)

namespace Gio
{

/** IOStream - Base class for implementing read/write streams.
 * IOStream represents an object that has both read and write streams.
 * Generally the two streams acts as separate input and output streams, but
 * they share some common resources and state. For instance, for seekable
 * streams they may use the same position in both streams.
 *
 * Examples of IOStream objects are SocketConnection which represents a two-way
 * network connection, and FileIOStream which represent a file handle opened in
 * read-write mode.
 *
 * To do the actual reading and writing you need to get the substreams with
 * get_input_stream() and get_output_stream().
 *
 * The IOStream object owns the input and the output streams, not the other way
 * around, so keeping the substreams alive will not keep the IOStream object
 * alive. If the IOStream object is freed it will be closed, thus closing the
 * substream, so even if the substreams stay alive they will always just return
 * a Gio::IO_ERROR_CLOSED for all operations.
 *
 * To close a stream use close() which will close the common stream object and
 * also the individual substreams. You can also close the substreams
 * themselves. In most cases this only marks the substream as closed, so
 * further I/O on it fails. However, some streams may support "half-closed"
 * states where one direction of the stream is actually shut down.
 *
 * @ingroup Streams
 *
 * @newin{2,22}
 */
class GIOMM_API IOStream : public Glib::Object
{
  _CLASS_GOBJECT(IOStream, GIOStream, G_IO_STREAM, Glib::Object, GObject, , , GIOMM_API)

public:

  _WRAP_ENUM(SpliceFlags, GIOStreamSpliceFlags, NO_GTYPE, decl_prefix GIOMM_API)

  /**  Asyncronously splice the output stream to the input stream of @a
   * stream2, and splice the output stream of @a stream2 to the input stream of
   * this stream.
   *
   * When the operation is finished @a slot will be called. You can then call
   * splice_finish() to get the result of the operation.
   *
   * @param stream2 The second IOStream.
   * @param slot A SlotAsyncReady slot.
   * @param cancellable A Cancellable object.
   * @param flags A set of SpliceFlags.
   * @param io_priority The io priority of the request.
   *
   * @newin{2,34}
   */
  void splice_async(const Glib::RefPtr<IOStream>& stream2,
    const SlotAsyncReady& slot, const Glib::RefPtr<Cancellable>& cancellable,
    SpliceFlags flags = SpliceFlags::NONE,
    int io_priority = Glib::PRIORITY_DEFAULT);
  _IGNORE(g_io_stream_splice_async)

  /// A non-cancellable version of splice_async().
  void splice_async(const Glib::RefPtr<IOStream>& stream2,
    const SlotAsyncReady& slot,
    SpliceFlags flags = SpliceFlags::NONE,
    int io_priority = Glib::PRIORITY_DEFAULT);

  _WRAP_METHOD(static bool splice_finish(const Glib::RefPtr<AsyncResult>& result), g_io_stream_splice_finish, errthrow)

  _WRAP_METHOD(Glib::RefPtr<InputStream> get_input_stream(), g_io_stream_get_input_stream, refreturn)
  _WRAP_METHOD(Glib::RefPtr<OutputStream> get_output_stream(), g_io_stream_get_output_stream, refreturn)
  _WRAP_METHOD(bool close(const Glib::RefPtr<Cancellable>& cancellable{?}), g_io_stream_close, errthrow)

  void close_async(const SlotAsyncReady&slot, const Glib::RefPtr<Cancellable>& cancellable, int io_priority=Glib::PRIORITY_DEFAULT);
  void close_async(const SlotAsyncReady& slot, int io_priority = Glib::PRIORITY_DEFAULT);
  _IGNORE(g_io_stream_close_async)
  _WRAP_METHOD(bool close_finish(const Glib::RefPtr<AsyncResult>& result), g_io_stream_close_finish, errthrow)
  _WRAP_METHOD(bool is_closed() const, g_io_stream_is_closed)
  _WRAP_METHOD(bool has_pending() const, g_io_stream_has_pending)
  _WRAP_METHOD(bool set_pending(), g_io_stream_set_pending, errthrow)
  _WRAP_METHOD(void clear_pending(), g_io_stream_clear_pending)
};

} // namespace Gio
