/*
 * Copyright (c) 1991,1993-1994 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the Computer Systems
 *	Engineering Group at Lawrence Berkeley Laboratory.
 * 4. Neither the name of the University nor of the Laboratory may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * @(#) $Header: /usr/src/mash/repository/vint/nam-1/netmodel.h,v 1.18 1998/10/15 21:17:15 haoboy Exp $ (LBL)
 */

#ifndef nam_netmodel_h
#define nam_netmodel_h

#define NO_ANGLE 10

class Edge;
class Node;
class Lan;
class Route;
class Agent;
struct TraceEvent;
class Queue;
class Animation;
class View;
class NetView;
class PSView;
class Paint;
class Packet;
class Group;
class Tag;
struct BBox;
class EditView;

#include "trace.h"
#include "monitor.h"

/*
 * The underlying model for a NetView.  We factor this state out of the
 * NetView since we might have multiple displays of the same network
 * (i.e., zoomed windows), as opposed to multiple interpretations 
 * (i.e, strip charts).
 */
class NetModel : public TraceHandler {
    public:
	NetModel(const char *animator);
	virtual ~NetModel();

	void render(View*);
	void render(PSView*);
	void update(double, Animation*);

	// Only redraw the part within a rectangle. 
	// Follows Tk_CanvasEventuallyRedraw
	virtual void render(EditView*, BBox &bb);

	/* TraceHandler hooks */
	virtual void update(double);
	void reset(double);
	void handle(const TraceEvent&, double now, int direction);

	virtual void BoundingBox(BBox&);
	void addView(NetView*);
	//Animation* inside(double now, float px, float py) const;
	Animation* inside(float px, float py) const;
        int add_monitor(Animation *a);
	void delete_monitor(Monitor *m);
	void delete_monitor(Animation *a);
	void delete_monitor(int monnum);
	void check_monitors(Animation *a);
        int monitor(double now, int monitor, char *result, int len);
	Packet *newPacket(PacketAttr &pkt, Edge *e, double time);
	void color_subtrees();
	int save_layout(const char *filename);

	// Tagging methods
	int tagCmd(View *v, int argc, char **argv,
		   char *newTag, char *cmdName);
	Animation* findClosest(float dx, float dy, double halo);
	void tagObject(Tag *tag, Animation *);
	int tagArea(BBox &bb, Tag *tag, int bEnclosed);
	int deleteTagCmd(char *tagName, char *tagDel);

	int add_tag(Tag *tag);
	void delete_tag(const char *tn);
	Tag* lookupTag(const char *tn);

	inline double now() { return now_; }

	// If editing is enabled, these functions must be public
	virtual void moveNode(Node *n);
	virtual void recalc() {}

	void remove_view(View *v);

  	void add_drop(const TraceEvent &, double now, int direction);

    protected:
	void scale_estimate();
	int traverse(Node* n);
	void move(double& x, double& y, double angle, double d) const;
	void layout();
	void placeEdgeByAngle(Edge* e, Node* src) const;
	virtual void placeEdge(Edge* e, Node* src) const;
	virtual void placeRoute(Route* r, Node* src) const;
	virtual void placeAgent(Agent* a, Node* src) const;

	int addr2id(int addr) const;
	int addAddress(int id, int addr) const;
	Node* lookupNode(int nn) const;
	void removeNode(Node *n);
	Lan* lookupLan(int nn) const;
	Packet *lookupPacket(int src, int dst, int id) const;

	int command(int argc, const char*const* argv);

#define EDGE_HASH_SIZE 256
	inline int ehash(int src, int dst) const {
		return (src ^ (dst << 4)) & (EDGE_HASH_SIZE-1);
	}
	struct EdgeHashNode {
		EdgeHashNode* next;
		int src;
		int dst;
		Edge* edge;
		Queue* queue;
	};
	EdgeHashNode* lookupEdge(int, int) const;
	Tcl_HashTable *addrHash_;
	void enterEdge(Edge* e);
	void removeEdge(Edge* e);
	void saveState(double);

	Animation *drawables_;
	Animation *animations_;
	Queue *queues_;
	View* views_;
	Node* nodes_;
	Lan* lans_;
	double now_;
	double nymin_, nymax_, node_size_;	/*XXX*/
	int mon_count_;
	Monitor *monitors_;
	EdgeHashNode* hashtab_[EDGE_HASH_SIZE];

	int nclass_;		// no. of classes (colors)
	int* paint_;

	// Map group address to group id
	Tcl_HashTable *grpHash_;
	int nGroup_;
	int add_group(Group *grp);
	Group* lookupGroup(unsigned int addr);

	// Map tag name (string) to tag id
	Tcl_HashTable *tagHash_;
	int nTag_;

	// Map object class name to class id
	Tcl_HashTable *objnameHash_;
	int registerObjName(const char*, int);
	int lookupObjname(const char *);
	Animation* lookupTagOrID(const char *);
};

#endif
