// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// 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/imagefile/imagefile_impl_dossier.h>
#include <mobius/io/file.h>
#include <mobius/datetime/timedelta.h>
#include <mobius/string_functions.h>
#include <mobius/regex_impl.h>
#include <mobius/exception.inc>
#include <mobius/charset.h>
#include <stdexcept>

namespace mobius
{
namespace imagefile
{
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief get URL for first segment file
//! \param url imagefile URL
//! \return first segment file URL
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static const std::string
get_first_segment_url (const std::string& url)
{
  return url.substr (0, url.length () - 4) + ".001";
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief check if URL is an instance of imagefile dossier
//! \return true/false
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
bool
imagefile_impl_dossier::is_instance (const std::string& url)
{
  bool instance = false;

  mobius::io::file f (url);

  if (f && f.exists ())
    {
      auto reader = f.new_reader ();
      mobius::bytearray data = reader.read (128);
      const std::string text = conv_charset_to_utf8 (data, "ASCII");
      instance = text.find ("Forensic Dossier") != std::string::npos;
    }

  return instance;
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief construct object
//! \param url imagefile URL
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
imagefile_impl_dossier::imagefile_impl_dossier (const std::string& url)
  : imagefile_impl_base (url), split_imagefile_ (get_first_segment_url (url))
{
  mobius::io::file f (url);
  constexpr mobius::io::file::size_type LOG_MAX_SIZE = 65536;

  if (f.exists () && f.get_size () < LOG_MAX_SIZE)
    {
      mobius::regex REGEX_DOSSIER_SERIAL ("Serial No.:([0-9]+)");
      mobius::regex REGEX_DOSSIER_SOFTWARE ("Software: ([A-Z0-9.]+)");
      mobius::regex REGEX_TIME_ZONE ("Time Zone: ([0-9+-]+)");
      mobius::regex REGEX_DRIVE_MODEL ("Model : ([^|]+?)\\|");
      mobius::regex REGEX_DRIVE_SERIAL ("Serial: ([0-9A-Z-]+) *\\|");
      mobius::regex REGEX_TOTAL_SECTORS ("Total Sectors.*\r\n\\* *([0-9]+)");
      mobius::regex REGEX_COMPLETION_TIME ("Completion Time: ([0-9]{2})/([0-9]{2})/([0-9]{4}) *([0-9]{2}):([0-9]{2}):([0-9]{2})");

      // parse .log file
      auto reader = f.new_reader ();
      mobius::bytearray data = reader.read (f.get_size ());
      const std::string text = conv_charset_to_utf8 (data, "ASCII");

      int timezone = 0;

      if (REGEX_TIME_ZONE.match (text))
        timezone = stoi (REGEX_TIME_ZONE[1]);

      if (REGEX_DOSSIER_SERIAL.match (text))
        set_acquisition_platform ("Logicube Forensic Dossier (s/n: " + REGEX_DOSSIER_SERIAL[1] + ')');

      if (REGEX_DOSSIER_SOFTWARE.match (text))
        set_acquisition_tool ("Dossier software " + REGEX_DOSSIER_SOFTWARE[1]);

      if (REGEX_DRIVE_MODEL.match (text))
        set_drive_model (string_strip (REGEX_DRIVE_MODEL[1]));

      if (REGEX_DRIVE_SERIAL.match (text))
        set_drive_serial_number (REGEX_DRIVE_SERIAL[1]);

      if (REGEX_TOTAL_SECTORS.match (text))
        {
          set_sectors (stoll (REGEX_TOTAL_SECTORS[1]));
          set_size (get_sectors () * get_sector_size ());
        }

      if (REGEX_COMPLETION_TIME.match (text))
        {
          mobius::datetime::datetime d (stoi (REGEX_COMPLETION_TIME[3]),
                                        stoi (REGEX_COMPLETION_TIME[1]),
                                        stoi (REGEX_COMPLETION_TIME[2]),
                                        stoi (REGEX_COMPLETION_TIME[4]),
                                        stoi (REGEX_COMPLETION_TIME[5]),
                                        stoi (REGEX_COMPLETION_TIME[6]));
          if (timezone)
            {
              mobius::datetime::timedelta delta;
              delta.set_seconds (-timezone * 3600);
              d = d + delta;
            }

          set_acquisition_time (d);
        }

      set_segments (split_imagefile_.get_segments ());
      set_segment_size (split_imagefile_.get_segment_size ());
      set_acquisition_user (f.get_user_name ());
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief create new reader for imagefile
//! \return reader
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
const mobius::io::reader
imagefile_impl_dossier::new_reader () const
{
  return split_imagefile_.new_reader ();
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief create new writer for imagefile
//! \return writer
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
const mobius::io::writer
imagefile_impl_dossier::new_writer () const
{
  throw std::runtime_error (MOBIUS_EXCEPTION_MSG ("writer not implemented"));
}

} // namespace imagefile
} // namespace mobius
