// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Mobius Forensic Toolkit
// Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024 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 "decoder_impl_arestra.h"
#include "common.h"
#include <mobius/decoder/data_decoder.h>
#include <mobius/encoder/hexstring.h>

namespace mobius::extension::app::ares
{
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Decode file
//! \see read_details_DB_Download - helper_download_disk.pas (line 722)
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
decoder_impl_arestra::decode (const mobius::io::reader& reader)
{
  if (!reader || reader.get_size () < 4096)
    return;

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Create main section
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  auto decoder = mobius::decoder::data_decoder (reader);
  decoder.seek (reader.get_size () - 4096);

  section_ = mobius::core::file_decoder::section (reader, "File");

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Decode header
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  auto header_section = section_.new_child ("header");

  auto signature = decoder.get_bytearray_by_size (13);
  std::uint32_t version = 0;

  if (signature == "___ARESTRA___")
    version = 1;

  else if (signature == "___ARESTRA__2")
    version = 2;

  else if (signature == "___ARESTRA__3")
    version = 3;

  else
    return;

  is_instance_ = true;
  std::uint64_t file_size = 0;
  std::uint64_t progress = 0;

  if (version == 1)
    {
      file_size = decoder.get_uint32_le ();
      progress = decoder.get_uint32_le ();
    }
  else
    {
      file_size = decoder.get_uint64_le ();
      progress = decoder.get_uint64_le ();
    }

  header_section.end ();

  metadata_.set_value ("general", "signature", signature.to_string ());
  metadata_.set_value ("general", "file_version", version);
  metadata_.set_value ("general", "file_size", file_size);
  metadata_.set_value ("general", "progress", progress);
  metadata_.set_value ("general", "is_completed", file_size == progress);

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Decode gaps
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  auto gaps_section = section_.new_child ("gaps");

  std::vector <mobius::pod::data> gaps;
  std::uint64_t start_pchunk = 0;
  std::uint64_t end_pchunk = 0xffffffffffffffff;

  while (end_pchunk)
    {
      if (version == 1)
        {
          end_pchunk = decoder.get_uint32_le ();
          start_pchunk = decoder.get_uint32_le ();
        }
      else
        {
          start_pchunk = decoder.get_uint64_le ();
          end_pchunk = decoder.get_uint64_le ();
        }

      if (end_pchunk)
        gaps.emplace_back (mobius::pod::data {start_pchunk, end_pchunk});
    }

  gaps_section.end ();

  metadata_.set_value ("general", "gaps", gaps);

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Decode params
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  auto params_section = section_.new_child ("params");

  auto mime = decoder.get_uint8 ();
  auto is_paused = (decoder.get_uint8 () == 1);
  auto param1 = decoder.get_uint32_le ();
  auto param2 = decoder.get_uint32_le ();
  auto param3 = decoder.get_uint32_le ();

  params_section.end ();

  metadata_.set_value ("general", "media_type", media_type_to_string (mime));
  metadata_.set_value ("general", "is_paused", is_paused);
  metadata_.set_value ("general", "param1", param1);
  metadata_.set_value ("general", "param2", param2);
  metadata_.set_value ("general", "param3", param3);

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Decode metadata, if any
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  auto metadata_section = section_.new_child ("metadata");
  auto data_size = decoder.get_uint16_le ();

  if (data_size > 0 && data_size != 3500)
    {
      auto data = decoder.get_bytearray_by_size (data_size);

      for (const auto& [k, v] : mobius::extension::app::ares::get_metadata (data, true))
        metadata_.set_value ("metadata", k, v);
    }

  metadata_section.end ();

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Padding section
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  auto padding_section = section_.new_child ("padding");
  decoder.seek (reader.get_size ());
  padding_section.end ();

  section_.end ();
}

} // namespace mobius::extension::app::ares
