// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Mobius Forensic Toolkit
// Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025 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/core/resource.h>
#include <mobius/vfs/block.h>
#include <mobius/vfs/filesystem.h>

namespace
{
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Decode filesystem block
//! \param parent_block Parent block
//! \param fs_type Filesystem type
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static mobius::vfs::block
_create_filesystem_block (const mobius::vfs::block& parent_block, const std::string& fs_type)
{
  auto block = mobius::vfs::new_slice_block (parent_block, "filesystem");
  mobius::vfs::filesystem fs (block.new_reader (), 0, fs_type);

  block.set_attribute ("impl_type", fs_type);
  block.set_attribute ("name", fs.get_name ());
  block.set_attribute ("size", fs.get_size ());

  for (const auto& [name, value] : fs.get_metadata ())
    block.set_attribute (name, value);

  block.set_attribute ("description", fs.get_name ());
  block.set_handled (true);

  return block;
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Try to decode block
//! \param block Block object
//! \param new_blocks Vector for newly created blocks
//! \param pending_blocks Pending blocks
//! \return <b>true</b> if block was decoded, <b>false</b> otherwise
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static bool
decoder (
  const mobius::vfs::block& block,
  std::vector <mobius::vfs::block>& new_blocks,
  std::vector <mobius::vfs::block>&
)
{
  bool rc = false;

  for (const auto& resource : mobius::core::get_resources ("vfs.filesystem"))
    {
      auto fs_resource = resource.get_value <mobius::vfs::filesystem_resource_type> ();

      if (fs_resource.is_instance (block.new_reader (), 0))
        {
          auto b = _create_filesystem_block (block, resource.get_id ());
          new_blocks.push_back (b);
          rc = true;
        }
    }

  return rc;
}

} // namespace

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Extension data
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
extern "C"
{
const char *EXTENSION_ID = "vfs.block.filesystems";
const char *EXTENSION_NAME = "Block: Filesystems";
const char *EXTENSION_VERSION = "1.1";
const char *EXTENSION_AUTHORS = "Eduardo Aguiar";
const char *EXTENSION_DESCRIPTION = "Filesystems VFS block support";
} // extern "C"

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Start extension
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
extern "C" void
start ()
{
  mobius::core::add_resource (
     "vfs.block.decoder.filesystems",
     "Filesystems VFS block decoder",
     static_cast <mobius::vfs::block_decoder_resource_type> (decoder)
  );
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Stop extension
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
extern "C" void
stop ()
{
  mobius::core::remove_resource ("vfs.block.decoder.filesystems");
}
