#ifndef __MOBIUS_IMAGEFILE_SEGMENT_ARRAY_BASE_H__
#define __MOBIUS_IMAGEFILE_SEGMENT_ARRAY_BASE_H__

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Mobius Forensic Toolkit
// Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017 Eduardo Aguiar
//
// This program 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 2, or (at your option) any later
// version.
//
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include <mobius/io/reader.h>
#include <mobius/io/writer.h>
#include <mobius/io/file.h>
#include <string>
#include <vector>
#include <cstdint>

namespace mobius
{
namespace imagefile
{
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief segment file class
//! \author Eduardo Aguiar
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class segment
{
public:
  // datatypes
  using idx_type = std::uint32_t;
  using size_type = mobius::io::reader::size_type;

  // constructors
  segment (idx_type, const std::string&);
  segment (const segment&) = default;
  segment (segment&&) = default;

  // assignment operators
  segment& operator= (const segment&) = default;
  segment& operator= (segment&&) = default;

  // prototypes
  const mobius::io::reader new_reader () const;
  const mobius::io::writer new_writer () const;
  size_type get_size () const;
  const std::string get_user_name () const;
  const mobius::datetime::datetime get_last_modification_time () const;

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  //! \brief get segment index
  //! \return index
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  idx_type
  get_idx () const
  {
    return idx_;
  }

private:
  mutable bool is_created_ = false;
  const idx_type idx_;
  mobius::io::file file_;
};

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief segment array class
//! \author Eduardo Aguiar
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class segment_array_base
{
public:
  // datatypes
  using idx_type = std::vector <segment>::size_type;
  using const_iterator = std::vector <segment>::const_iterator;
  using iterator = std::vector <segment>::iterator;

  // constructors and destructor
  explicit segment_array_base (const std::string&);
  segment_array_base (const segment_array_base&) = default;
  segment_array_base (segment_array_base&&) = default;
  virtual ~segment_array_base () = default;

  // assignment operators
  segment_array_base& operator= (const segment_array_base&) = default;
  segment_array_base& operator= (segment_array_base&&) = default;

  // prototypes
  const segment& operator[](idx_type) const;
  segment& operator[](idx_type);
  void resize (idx_type);
  void scan ();

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  //! \brief get segment array size
  //! \return number of segments
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  idx_type
  get_size () const
  {
    return segments_.size ();
  }

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  //! \brief get const_iterator to the beginning of the array
  //! \return const_iterator
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  const_iterator
  begin () const
  {
    return segments_.begin ();
  }

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  //! \brief get const_iterator past to the end of the array
  //! \return const_iterator
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  const_iterator
  end () const
  {
    return segments_.end ();
  }

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  //! \brief get iterator to the beginning of the array
  //! \return iterator
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  iterator
  begin ()
  {
    return segments_.begin ();
  }

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  //! \brief get iterator past to the end of the array
  //! \return iterator
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  iterator end ()
  {
    return segments_.end ();
  }

protected:
  virtual const std::string get_next_extension (const std::string&) const = 0;

private:
  std::vector <segment> segments_;
  std::string prefix_;
  std::string next_extension_;
};

} // namespace imagefile
} // namespace mobius

#endif
