/*
 * steghide 0.5.1 - a steganography program
 * Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
 *
 * 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
 * of the License, 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

#ifndef SH_GRAPH_H
#define SH_GRAPH_H

#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <vector>
#include <unordered_map>

#include "EdgeIterator.h"
#include "SampleValueAdjacencyList.h"
#include "common.h"

class BitString ;
class SampleOccurence ;
class Selector ;
class Vertex ;
class VertexContent ;
struct VertexContentsEqual ;

/**
 * \class Graph
 * \brief a graph constructed from a cover file and a message to be embedded
 *
 * This class provides a purely graph-theoretic interface to any other class.
 * Some classes however need access to the internal (steganographic) representation,
 * for example: Vertex, EdgeIterator,... . These are declared as friends of Graph here and
 * thus have direct access to the private data structures.
 **/
class Graph {
	public:
	/**
	 * construct a graph
	 * \param cvr the underlying cover file
	 * \param emb the bitstring to be embedded (with correct arity already set)
	 **/
	Graph (CvrStgFile* cvr, const BitString& emb, Selector& sel) ;

	/**
	 * destructor
	 **/
	~Graph (void) ;

	/**
	 * get the number of vertices in this graph
	 **/
	unsigned long getNumVertices (void) const
		{ return Vertices.size() ; } ;

	/**
	 * get a vertex
	 * \param l the vertex label (index) of the vertex to be returned (must be < getNumVertices())
	 * \return the vertex with label l
	 **/
	Vertex* getVertex (VertexLabel l) const
		{ return Vertices[l] ; } ;

	void unmarkDeletedAllVertices (void) ;

	/**
	 * calculate and return the average vertex degree
	 **/
	float getAvgVertexDegree (void) const ;

	void printVerboseInfo (void) ;

	/**
	 * check the integrity of all data structures,
	 * only used for debugging and testing
	 **/
	bool check (bool verbose = false) const ;
	/**
	 * check the integrity of the Vertices data structure,
	 * only used for debugging and testing
	 **/
	bool check_Vertices (bool verbose = false) const ;
	/**
	 * check the integrity of the SampleValues data structure,
	 * only used for debugging and testing
	 **/
	bool check_SampleValues (bool verbose = false) const ;
	/**
	 * check the integrity of the SampleOccurences data structure,
	 * it is assumed that DeletedSampleOccurences is empty,
	 * only used for debugging and testing
	 **/
	bool check_SampleOccurences (bool verbose = false) const ;
	/**
	 * check the integrity of the SVALists data structure,
	 * only used for debugging and testing
	 **/
	bool check_SVALists (bool verbose = false) const ;

#ifdef DEBUG
	/**
	 * prints graph in a format suitable as input to the C implementation
	 * of Gabow's non-weighted matching algorithm by E. Rothberg to stdout
	 * (available at: ftp://ftp.zib.de/pub/Packages/mathprog/matching/index.html
	 **/
	void print (void) const ;

	void print_gml (std::ostream& out) const ;
	void printVertex_gml (std::ostream& out, Vertex* v, unsigned int recdepth, std::vector<bool>& nodeprinted, std::vector<bool>& edgesprinted, bool start = true) const ;
	void printPrologue_gml (std::ostream& out) const ;
	void printEpilogue_gml (std::ostream& out) const ;

	void print_Vertices (unsigned short spc = 0) const ;
#endif

	private:
	//
	// friend-declarations
	//
	friend class WKSConstructionHeuristic ;
	friend class EdgeIterator ;
	friend class SampleValueAdjacencyList ;
	friend class Vertex ;

	/// contains the vertices in this graph - Vertices[l] is the vertex with label l
	std::vector<Vertex*> Vertices ;

	/// contains the list of (unique) sample values - SampleValues[l] is the sample value with label l
	std::vector<SampleValue*> SampleValues ;

	/// contains the sample value adjacency lists (SVALists[v] contains only sample values with embedded value v)
	std::vector<SampleValueAdjacencyList*> SVALists ;

	/// SampleOccurences[l] contains all occurences of the sample value with label l
	std::vector<std::list<SampleOccurence> > SampleOccurences ;

	/**
	 * NumSampleOccurences[l][t] contains the number vertices that contain the sample value with label l and associated target t
	 **/
	std::vector<UWORD32*> NumSampleOccurences ;

	/// contains those sample occurences that have been marked as deleted from SampleOccurences
	std::vector<std::list<SampleOccurence> > DeletedSampleOccurences ;
	std::vector<UWORD32*> NumDeletedSampleOccurences ;

	std::list<SampleOccurence>::iterator markDeletedSampleOccurence (std::list<SampleOccurence>::iterator it) ;
	std::list<SampleOccurence>::iterator unmarkDeletedSampleOccurence (std::list<SampleOccurence>::iterator it) ;

	//
	// end of friend-declarations
	// Note: private members of Graph that are declared beyond this point should
	//       not be used by friends.
	//

	/**
	 * construct sample-related data structures
	 *
	 * needs: sposs(unsorted)
	 * provides: svalues(unsorted,unique), SampleValues
	 **/
	void constructSamples (const std::vector<SamplePos*> &sposs, std::vector<SampleValue**>& svalues) ;

	/**
	 * construct vertex-related data structures
	 *
	 * needs: sposs(unsorted), svalues(unsorted,unique), tvalues
	 * provides: sposs(sorted), Vertices (except SampleOccurenceIts)
	 **/
	void constructVertices (std::vector<SamplePos*>& sposs, std::vector<SampleValue**>& svalues, const std::vector<EmbValue>& tvalues) ;

	/**
	 * construct edge-related data structures
	 *
	 * needs: SampleValues, Vertices (except SampleOccurenceIts)
	 * provides: SVALists, SampleOccurences, Vertices (SampleOccurenceIts)
	 **/
	void constructEdges (void) ;

	CvrStgFile *File ;
	EmbValue EmbValueModulus ;
	unsigned short SamplesPerVertex ;

	bool check_SampleOccurences_size (bool verbose = false) const ;
	bool check_SampleOccurences_correctness (bool verbose = false) const ;
	bool check_SampleOccurences_completeness (bool verbose = false) const ;

	bool check_SVALists_size (bool verbose = false) const ;
	bool check_SVALists_soundness (bool verbose = false) const ;
	bool check_SVALists_sorted (bool verbose = false) const ;
	bool check_SVALists_uniqueness (bool verbose = false) const ;
	bool check_SVALists_completeness (bool verbose = false) const ;
} ;

#endif // ndef SH_GRAPH_H
