
#ifndef __texturestack_h__
#define __texturestack_h__

#ifndef __tags_h__
#include "tags.h"
#endif

#ifndef PandaWave_XVIEW
#include <XView.h>
#endif

#ifndef __ttageditform_h__
#include "TTagEditForm.h"
#endif

#ifndef PandaWave_XPTRSET
#include <XPtrSet.h>
#endif

#ifndef SS_DRAGDROP
#include <XDragDrop.h>
#endif

class XGBitmap;


// types in file

struct txst_tagheader {
	unsigned short count;
	unsigned short padding;
	
	// count * txst_stackrefs follow
};


enum {
	_texturestack_do_not_downsample_bit = 0,
	NUMBER_OF_TEXTURESTACK_FLAGS,
	
	_texturestack_do_not_downsample_flag = FLAG(_texturestack_do_not_downsample_bit)
};


struct txst_stackref {
	unsigned offset;	// from start of tag
	unsigned length;
	unsigned short flags;
	unsigned short usage_chance;
};

struct txst_stackheader {
	unsigned short count;
	unsigned short padding;
	
	// count * txst_texheaders follow
};

enum {
	txst_use_basecolor,
	txst_use_detailmask,
	txst_use_details,
	txst_use_skinblend,
	txst_use_logomask,
	txst_use_fullbrightmask,
	txst_use_reflectmask
};

struct txst_texheader {
	unsigned offset;	// from start of stack
	unsigned length;	// of texture data excluding this header
	unsigned char channels;	// 1=alpha, 3=rgb, 4=rgba
	unsigned char format;	// right now only 0=raw 8-bit
	unsigned char use;
	unsigned char layer;	// for skinblends and detailmasks, 0-based
	unsigned short width, height;
	signed short decal_corner_x;
	signed short decal_corner_y;
	signed short decal_ux, decal_uy;
	signed short decal_vx, decal_vy;
};


// editable types in memory

struct stacked_texture {
	stacked_texture *next, *prev;
	
	const void *compressed_data;
	unsigned compressed_length;
	
	XGBitmap *thumbnail;
	
	unsigned char channels;
	unsigned char format;
	unsigned char use;
	unsigned char layer;
	unsigned short width, height;
	signed short decal_corner_x;
	signed short decal_corner_y;
	signed short decal_ux, decal_uy;
	signed short decal_vx, decal_vy;
};

struct texture_stack_head {
	stacked_texture *textures;
	unsigned short flags;
	unsigned short usage_chance;
};

struct stack_set {
	tag_entry *entry;
	
	int used_stacks;
	int avail_stacks;
	texture_stack_head *stacks;
	bool modified;
};


extern byte_swap_code swap_txst_tagheader[];
extern byte_swap_code swap_txst_stackref[];
extern byte_swap_code swap_txst_stackheader[];
extern byte_swap_code swap_txst_texheader[];

void edit_texturestack( tag_entry *e );
void defaultnew_texturestack( tag_entry *e );

stack_set *load_stackset( tag_entry *e );
void save_stackset( tag_entry *e, stack_set *ss );
void dispose_stackset( stack_set *ss );
void compact_stackset( stack_set *ss );

stack_set *new_empty_stackset( int maxstacks );

stacked_texture *get_texture( stack_set *ss, int stacknum, int stacklevel );

void insert_texturestack_in_set( stack_set *ss, int index );
int insert_into_texturestack( stack_set *ss, int index, int pos, stacked_texture *tex );
void remove_from_texturestack( stack_set *ss, int index, stacked_texture *tex, bool collapse_set );

stack_set *import_psd_colormap( XGFileSpecifier *fs );

void make_texture_thumbnail( stacked_texture *tex );
stacked_texture *duplicate_stacked_texture( const stacked_texture *tex );
void dispose_stacked_texture( stacked_texture *tex );
void recompress_texture( stacked_texture *tex, int quality );
void find_texture_in_stack( const stack_set *ss, const stacked_texture *tex, int *outStackNum, int *outStackLevel );



class TtxstEditForm: public TTagEditForm {
	public:
							TtxstEditForm( struct tag_entry *t );
		virtual				~TtxstEditForm();
		
		DECLAREDISPATCH
		long				DoGetMenuStatus(long,void *);
		long				DoMenuCommand(long,void *);
		long				DoKeyEvent( long arg, void * );
		
		
		virtual void		CommitToTag();
		virtual void		ReloadTag();
		virtual bool		NeedCommit();
		
		void				RebuildEditorContents();
		
		void				SetModified( bool );
		void				DeleteSelected();
		void				CopySelected();
		void				Paste();
	protected:
		stack_set *stacks;
		class TtxstEditView *edit;
		static stacked_texture *st_clip;
};

class TtxstEditView: public XGView, public XGDropper {
	friend class TtxstEditForm;
	public:
							TtxstEditView( XGView *parent, XGArgStream &stream );
		virtual				~TtxstEditView();
		
		void				DoDrawView( XRect invalid );
		bool 				DoMouseDown( XPoint where, short flags );
		
		// selection
		void				InvalElements( const XGPtrSet<stacked_texture> &elems );
		void				GetSelection( XGPtrSet<stacked_texture> *outSel )
								{ *outSel = fSelection; }
		void				SetSelection( const XGPtrSet<stacked_texture> &inSel );
		void				ClearSelection();
		bool				IsSelected( stacked_texture *tex )
								{ return fSelection.HasMember( tex ); }
		
		// drag and drop
		bool				Accept(long /* modifiers */, long /* itemRef */, long flavor );
		void				Track(XPoint where, long /* modifiers */);
		void				Enter(XPoint where, long mods, bool hilite);
		void				Leave();
		void				BeginDrop(XPoint where, long mods);
		bool				Drop(XPoint where, long mods, long itemRef, long flavor, void * dataptr, long datalen);
		void				EndDrop(XPoint where, long mods);
		void				FindDrop( XPoint where, int *num, int *level );
		int					AddFile( int stacknum, int level, XGFileSpecifier &fs );
		
		enum {
			kClassID = 'TXST'
		};
		stack_set *stacks;
private:		
		XGPtrSet<stacked_texture> fSelection;
		int fDropStackNum;
		int fDropStackLevel;
		bool fDrawDropPoint;
		void				DrawDropPoint( bool show );
	
};


#endif

