#include "ntfsmftentryxml.hh"

//#define EXTRA_OUTPUT

NTFSMFTEntryXML::NTFSMFTEntryXML () 
{
  xmloutputfile = new XMLOutput ();
  // TODO: make this an optional variable that's inputted
  xmloutputfile->openFile("testntfsmftentryxml.xml");
  xmloutputfile->print(xml_header);
  xmloutputfile->push ("NTFS", "");
}

NTFSMFTEntryXML::~NTFSMFTEntryXML ()
{
  xmloutputfile->pop ();
  delete xmloutputfile;
}

void NTFSMFTEntryXML::push (const std::string tag, const std::string attribute)
{
  xmloutputfile->push (tag, attribute);
}

void NTFSMFTEntryXML::pop () 
{
  xmloutputfile->pop ();
}

void NTFSMFTEntryXML::file_info (const std::string tag, const std::string variable)
{
  xmloutputfile->xmloutputstring (tag, variable, "");
}

void NTFSMFTEntryXML::file_info_attribute (const std::string tag, const std::string variable, const std::string attribute)
{
  xmloutputfile->xmloutputstring (tag, variable, attribute);
}

void NTFSMFTEntryXML::byterun ( seglist segs, int64_t fileLength, int64_t initializedSize, int compressedStatus )
{
  xmloutputfile->push ("byte_runs", "");

  for ( unsigned int i = 0; i < segs.size(); i++ ) {
    seg segment = segs.at(i);
    std::stringstream sstream;
    sstream << "file_offset='";
    sstream << segment.file_offset;

    if (compressedStatus) {
      if (segment.compressed == 0) {
	sstream << "' fs_offset='";
	sstream << segment.fs_offset;
	sstream << "' img_offset='";
	sstream << segment.img_offset;
      } 
      sstream << "' uncompressed_len='";

    } else {
      if (segment.fs_offset == 0 && segment.img_offset == 0) {
	sstream << "' fill='";
	sstream << 0;
      } else {
	sstream << "' fs_offset='";
	sstream << segment.fs_offset;
	sstream << "' img_offset='";
	sstream << segment.img_offset;
      }
	sstream << "' len='";
    }

    if ( (i == segs.size()-1) && (fileLength != 0)) {
      sstream << (fileLength - segment.file_offset);
    } else {
      sstream << segment.len;
    } 
    sstream << "'";

    xmloutputfile->xmloutputstring ("byte_run", "", sstream.str());
  }

  xmloutputfile->pop ();
}

void NTFSMFTEntryXML::output_into_XML ( NTFSMFTEntry entry, const int64_t offset ) {
       	push("fileobject", "");

	std::stringstream sstream;

	sstream << 32256;
	file_info("part_offset", sstream.str());
	sstream.str(""); sstream.clear();

	sstream << offset;
	file_info("fs_offset", sstream.str());
	sstream.str(""); sstream.clear();

	push("parent_object", "");
	sstream << entry.get_parentMFTentry();
	file_info("inode", sstream.str());
	sstream.str(""); sstream.clear ();
	pop();

#ifdef EXTRA_OUTPUT
	sstream << entry.get_fixupSignature();
	file_info("fixup_signature", sstream.str());
	sstream.str(""); sstream.clear ();

	sstream << entry.get_offsetFileNameAttr();
	file_info("filename_attr_offset", sstream.str());
	sstream.str(""); sstream.clear ();
#endif
	
	file_info("filename", entry.get_filename());

	file_info("partition", "-");

	sstream << entry.get_name_type();
	file_info("name_type", sstream.str());
	sstream.str(""); sstream.clear ();

	sstream << entry.get_length ();
	file_info("filesize", sstream.str());
	sstream.str(""); sstream.clear ();

	sstream << entry.get_alloc();
	file_info("alloc", "-");
	sstream.str(""); sstream.clear ();	

	sstream << entry.get_inUse ();
	file_info("used", sstream.str());
	sstream.str(""); sstream.clear ();	
	
	sstream << entry.get_compressed ();
	file_info("compressed", sstream.str());
	sstream.str(""); sstream.clear ();

	file_info("inode", "-");
	file_info("meta_type", "-");
	file_info ("mode", "-");

	sstream << entry.get_nlink();
	file_info("nlink", sstream.str());
	sstream.str(""); sstream.clear ();	

	sstream << entry.get_ownerID();
	file_info("uid", sstream.str());
	sstream.str(""); sstream.clear ();	

	file_info("gid", "-");

#ifdef EXTRA_OUTPUT		
	sstream << entry.get_offsetDATAattr ();
	file_info("DATA_attr_offset", sstream.str());
	sstream.str(""); sstream.clear();
#endif

	sstream << entry.get_ctime ();
	file_info("ctime", sstream.str());
	sstream.str(""); sstream.clear();

	sstream << entry.get_atime ();
	file_info("atime", sstream.str());
	sstream.str(""); sstream.clear();

	sstream << entry.get_crtime ();
	file_info("crtime", sstream.str());
	sstream.str(""); sstream.clear();

	sstream << entry.get_mtime ();
	file_info("mtime", sstream.str());
	sstream.str(""); sstream.clear();

	sstream << entry.get_sequenceValue();
	file_info("seq", sstream.str());
	sstream.str(""); sstream.clear();

#ifdef EXTRA_OUTPUT
	sstream << entry.get_runlistOffset();
	file_info("runlist_offset", sstream.str());
	sstream.str(""); sstream.clear();
#endif

	seglist clustersForXML = entry.get_seglist();
	byterun( clustersForXML, entry.get_length (), entry.get_initializedSize(), entry.get_compressed () );

	file_info_attribute("hashdigest", "-", "type='md5'");
	file_info_attribute("hashdigest", "-", "type='sha1'");

	pop();

}
