// FileHead.h: interface for the FileHead class.
//
//////////////////////////////////////////////////////////////////////

#ifndef FILEHEAD_H
#define FILEHEAD_H

#include "filelog.h"
#include "listnode.h"
#include "strbuf.h"
#include "clientloguser.h"
#include "clientapi.h"
#include "cbase.h"
#include <stdlib.h>

/* A FileRevArrow is a single pointer from one rev to another.  It also
 * serves as a singly-linked-list node. */

enum ArrowType //how should this pointer be rendered?
{
	edit, branch, copy, ignore, impure, merge
};

enum Contrib //how much content contribution does this represent?
{
	none, some, all
};

enum RevType //what was the action that created this rev?
{
	UNKNOWN_TYPE, EDIT, BRANCH, ADD, INTEG, DEL
};

class FileHead;

struct FileRevArrow
{
	FileRev* ptr;
	ArrowType type;
	Contrib contrib;
	FileRevArrow* next;
};

struct FileTextArrow
{
	StrBuf file;
	StrBuf rev;
	ArrowType type;
	FileTextArrow* next;
	FileHead* fhead;
};

enum CacheLocation { cl_unset, cl_from, cl_into, cl_main };

/* A FileHead object represents a file and all its revision history.  Its name comes
 * from the fact that it's the head of a linked list of FileRev objects.  The FileHead
 * is a part of a FileLogCache. */

class FileHead  
{
public:
	FileHead(StrBuf, FileLogCache*);
	virtual ~FileHead();

	FileHead* next; //This is the next FileHead in a "from" or "into" chain.
					//See FileLogCache for more info about its structure.

	/* These FileHeads are a more "absolute" line of links across the FileLogCache -
	 * you can start at one end, follow one of these pointers, and make it all the way
	 * to the other end. */
	FileHead* next_from;
	FileHead* next_into;

	FileRev* head; //The FileRev corresponding to the head revision of this file.
	FileRev* tail; //The last created FileRev - in a complete FileHead this will be rev #1.

	FileLogCache* flc; //The FileLogCache that this FileHead is a part of.
	
	StrBuf name; //The Perforce path to this file, eg "//depot/foo/file".

	/* addRev adds a new revision to this FileHead, at the tail position.  As 
	 * arguments it takes the revision number, the change number, the file 
	 * type, ane whether it's text.  addRev is called once by ClientLogUser for each revision record 
	 * in a filelog.  It is assumed that the revisions will be added in order 
	 * from head to first. */
	void addRev(StrBuf newrev, StrBuf newchange, RevType, bool istext);

	/* scanInto is used to follow "into" integration records - it's a command for
	 * this FileHead to locate the revision indicated by the 'startrev' argument,
	 * and set its 'from' pointer to the 'caller' argument.  This is its primary function.
	 * Once this is done, it checks that revision and its successors to see if they were
	 * integrated into other files, and calls scanInto on those files where necessary.  In
	 * this way, all of the children of children are found.  The startrev argument is of
	 * the form "14", and the caller argument is a pointer to the revision that was the source
	 * of the integration that created revision 14. */
	void scanInto(StrBuf startrev, FileRev* caller, ArrowType atype);

	/* scanFrom is similar to scanInto, but it does roughly the opposite.  It returns the
	 * FileRev object corresponding to the 'endrev' argument - this pointer is used
	 * to establish a 'from' pointer from the caller file to this one.  scanFrom also
	 * checks all of the revisions before the endrev for "from" integration records, and
	 * calls scanFrom on the referenced files. */
	FileRev* scanFrom(StrBuf endrev);

	/* scanMain should only be called on the "main" FileHead.  It performs sort of an
	 * interleaved scanFrom and scanInto. */
	void scanMain();

	/* It's handy to know where in the FLC structure a given FileHead is. */
	CacheLocation loc;

	/* ClientLogUser object which will channel filelog inputs into this FileHead */
	ClientLogUser* ui;

	int size; //number of revs in this FileHead.
};

/* A FileRev object represents a single file revision.  */
class FileRev  
{
public:
	/* Constructor -  initializes the named variables. */
	FileRev(StrBuf rev, FileHead* file, StrBuf change, RevType type, bool istext);

	/* Add a new FileRevArrow to this FileRev. */
	void AddFromArrow(FileRev* rev, ArrowType atype);

	/* Add new FileTextArrows, to later be translated into FileRevArrows. */
	void AddFromText(StrBuf& infile, StrBuf& inrev, ArrowType atype);
	void AddIntoText(StrBuf& infile, StrBuf& inrev, ArrowType atype);

	virtual ~FileRev();

	FileRev* prev; //the previous FileRev in the linked list.
	FileRev* next; //the next FileRev in the linked list.
	FileHead* fh; //the FileHead this FileRev is a part of.

	StrBuf rev; //the rev number, eg "14".
	StrBuf change; //the change number, eg "123".
	RevType type; //the rev type

	bool fromcheck; //Has this rev been touched by scanFrom()?
	bool intocheck; //Has this rev been touched by scanInto()?

	FileRevArrow* fromarrows; //List of FileRev pointers to be rendered
	FileTextArrow* fromtexts; /* Textual descriptions to be turned into */
	FileTextArrow* intotexts; /* pointers                               */

	CBaseEntity* ent; //The CObjectRev created from this FileRev, if any.
	bool istext;
};



#endif // FILEHEAD_H
