// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Mobius Forensic Toolkit
// Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022 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 "imagefile.h"
#include "imagefile_impl_dossier.h"
#include "imagefile_impl_solo.h"
#include "imagefile_impl_talon.h"
#include "imagefile_impl_null.h"
#include "ewf/imagefile_impl.h"
#include "msr/imagefile_impl.h"
#include "raw/imagefile_impl.h"
#include "split/imagefile_impl.h"
#include "vhd/imagefile_impl.h"
#include "vhdx/imagefile_impl.h"
#include <mobius/io/file.h>

namespace mobius
{
namespace imagefile
{
namespace
{
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Imagefile types available
// id, description, file extensions, writeable (true/false)
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static const std::vector <info> IMAGEFILE_TYPES =
{
  {"dossier", "Logicube Dossier image file", "LOG", false},
  {"ewf", "EWF image file", "E01|e01|ewf", true},
  {"msr", "Samsung Secret Zone image file", "MSR|msr", false},
  {"raw", "raw image file", "raw|dd|img|*", true},
  {"solo", "ICS Solo image file", "txt", false},
  {"split", "split image file", "001", true},
  {"talon", "Logicube Talon image file", "LOG", false},
  {"vhd", "VHD image file", "vhd", false},
  {"vhdx", "VHDX image file", "vhdx", false},
};

} // namespace

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Get list of available imagefile types
//! \return list of imagefile types
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
std::vector <info>
get_imagefile_types ()
{
  return IMAGEFILE_TYPES;
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Construct object
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
imagefile::imagefile ()
{
  impl_ = std::make_shared <imagefile_impl_null> ();
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Constructor from implementation pointer
//! \param impl implementation pointer
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
imagefile::imagefile (std::shared_ptr <imagefile_impl_base> impl)
  : impl_ (impl)
{
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Constructor from file object
//! \param f File object
//! \param type Imagefile type (default = "autodetect")
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
imagefile::imagefile (const mobius::io::file& f, const std::string& type)
{
  // detect imagefile type, if type == "autodetect"
  std::string i_type = type;

  if (type == "autodetect")
    {
      if (imagefile_impl_dossier::is_instance (f))
        i_type = "dossier";

      else if (ewf::imagefile_impl::is_instance (f))
        i_type = "ewf";

      else if (msr::imagefile_impl::is_instance (f))
        i_type = "msr";

      else if (imagefile_impl_talon::is_instance (f))
        i_type = "talon";

      else if (imagefile_impl_solo::is_instance (f))
        i_type = "solo";

      else if (vhd::imagefile_impl::is_instance (f))
        i_type = "vhd";

      else if (vhdx::imagefile_impl::is_instance (f))
        i_type = "vhdx";

      else if (split::imagefile_impl::is_instance (f))
        i_type = "split";

      else
        i_type = "raw";
    }

  // create impl according to i_type
  if (i_type == "dossier")
    impl_ = std::make_shared <imagefile_impl_dossier> (f);

  else if (i_type == "ewf")
    impl_ = std::make_shared <ewf::imagefile_impl> (f);

  else if (i_type == "msr")
    impl_ = std::make_shared <msr::imagefile_impl> (f);

  else if (i_type == "raw")
    impl_ = std::make_shared <raw::imagefile_impl> (f);

  else if (i_type == "solo")
    impl_ = std::make_shared <imagefile_impl_solo> (f);

  else if (i_type == "split")
    impl_ = std::make_shared <split::imagefile_impl> (f);

  else if (i_type == "talon")
    impl_ = std::make_shared <imagefile_impl_talon> (f);

  else if (i_type == "vhd")
    impl_ = std::make_shared <vhd::imagefile_impl> (f);

  else if (i_type == "vhdx")
    impl_ = std::make_shared <vhdx::imagefile_impl> (f);

  else
    impl_ = std::make_shared <imagefile_impl_null> ();
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Create new imagefile object
//! \param url Imagefile URL
//! \param type Imagefile type (default = "autodetect")
//! \return Imagefile object
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
imagefile
new_imagefile_by_url (const std::string& url, const std::string& type)
{
  auto f = mobius::io::new_file_by_url (url);
  return imagefile (f, type);
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Create new imagefile object
//! \param path Imagefile path
//! \param type Imagefile type (default = "autodetect")
//! \return Imagefile object
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
imagefile
new_imagefile_by_path (const std::string& path, const std::string& type)
{
  auto f = mobius::io::new_file_by_path (path);
  return imagefile (f, type);
}

} // namespace imagefile
} // namespace mobius
