// Copyright 1999
// College of Computer Science
// Northeastern University Boston MA 02115

// This software may be used for educational purposes as long as this copyright
// notice is retained at the top of all files

// Should this software be modified, the words "Modified from Original" must be
// included as a comment below this notice

// All publication rights are retained.  This software or its documentation may
// not be published in any media either in whole or in part.

///////////////////////////////////////////////////////////////////////////////

// RGB.h	RGBdata       definition
//			NativeRGBdata definition

///////////////////////////////////////////////////////////////////////////////

#ifndef RGB_H_
#define RGB_H_

#include "Platform.h"				// Native system macros and byte type

#include <string>

using namespace std;

///////////////////////////////////////////////////////////////////////////////

// NativeRGBdata = typedef for native color structure

///////////////////////////////////////////////////////////////////////
//                   BEGIN PLATFORM DEPENDENT CODE                   //

#if defined(CORE_PLATFORM_WIN32)

typedef COLORREF NativeRGBdata;

#endif // end Win32 specific


#if defined(CORE_PLATFORM_MACOS)

typedef RGBColor NativeRGBdata;

#endif // end MacOS specific

//                    END PLATFORM DEPENDENT CODE                    //
///////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////

// Simple color data class

class EXPORT RGBdata {

	// System independent color information: rvalue, gvalue, bvalue
	// System  dependent  color information: NativeRGB

///////////////////////////////////////////////////////////////////////
//                   BEGIN PLATFORM DEPENDENT CODE                   //

#if defined(CORE_PLATFORM_WIN32)

	union {
		NativeRGBdata NativeRGB;	// Win32 color structure

		struct {
			byte rvalue;
			byte gvalue;
			byte bvalue;
			byte padding;			// added to force 32 bit alignment
		};
	};

#endif // end Win32 specific

#if defined(CORE_PLATFORM_MACOS)

	union {
		NativeRGBdata NativeRGB;	// MacOS color structure

		struct {
			byte rvalue;
			byte padding1;			// added to force 16 bit alignment

			byte gvalue;
			byte padding2;			// added to force 16 bit alignment

			byte bvalue;
			byte padding3;			// added to force 16 bit alignment
		};
	};

#endif // end MacOS specific

//                    END PLATFORM DEPENDENT CODE                    //
///////////////////////////////////////////////////////////////////////


public:

	// set and get data with byte information
	
	RGBdata& Set(byte r, byte g, byte b) {

		rvalue = r;
		gvalue = g;
		bvalue = b;

		// Platform dependent code fills padding with zero

///////////////////////////////////////////////////////////////////////
//                   BEGIN PLATFORM DEPENDENT CODE                   //

#if defined(CORE_PLATFORM_WIN32)

		padding = 0;

#endif // end Win32 specific


#if defined(CORE_PLATFORM_MACOS)

		padding1 = 0;
		padding2 = 0;
		padding3 = 0;

#endif // end MacOS specific

//                    END PLATFORM DEPENDENT CODE                    //
///////////////////////////////////////////////////////////////////////

		return *this;

	}; // RGBdata& Set(byte r, byte g, byte b)
	

	// default Set

	RGBdata& Set() {
		return Set(0,0,0);
	};


	// Get functions

	void Get(byte& r, byte& g, byte& b) const {
		r = rvalue;
		g = gvalue;
		b = bvalue;
	};
	

	void Get(short& r, short& g, short& b) const {
		r = rvalue;
		g = gvalue;
		b = bvalue;
	};
	
	
	void Get(long& r, long& g, long& b) const {
		r = rvalue;
		g = gvalue;
		b = bvalue;
	};
	
	
	void Get(int& r, int& g, int& b) const {
		r = rvalue;
		g = gvalue;
		b = bvalue;
	};
	
	
	// set and get data with RGBdata information
	
	RGBdata& Set(const RGBdata& color) {
		NativeRGB = color.NativeRGB;

		return *this;
	};


	void Get(RGBdata& color) const {
		color.NativeRGB = NativeRGB;
	};


	// set and get data with NativeRGBdata information
	
	RGBdata& Set(const NativeRGBdata& color) {
		NativeRGB = color;

		return *this;
	};


	void Get(NativeRGBdata& color) const {
		color = NativeRGB;
	};


	// constructors

	// default initialization: black
	
	RGBdata() {
		Set();
	};
	

	// explicit initialization
	
	RGBdata(byte r, byte g, byte b) {
		Set(r,g,b);
	};
	
	
	// copy constructor from RGBdata

	RGBdata(const RGBdata& color) {
		Set(color);
	};


	// copy constructor from NativeRGBdata

	RGBdata(const NativeRGBdata& color) {
		Set(color);
	};


	// operator= for RGBdata

	RGBdata& operator= (const RGBdata& color) {
		return Set(color);
	};


	// operator= for NativeRGBdata

	RGBdata& operator= (const NativeRGBdata& color) {
		return Set(color);
	};


	// explicit conversion to NativeRGBdata

	NativeRGBdata Native() const {
		return NativeRGB;
	};


	// member shading routines similar to stand alone versions below
	
	RGBdata& RedShade		(byte level = 255)	{ return Set(level, 0, 0); };
	RGBdata& GreenShade		(byte level = 255)	{ return Set(0, level, 0); };
	RGBdata& BlueShade		(byte level = 255)	{ return Set(0, 0, level); };
	RGBdata& CyanShade		(byte level = 255)	{ return Set(0, level, level); };
	RGBdata& MagentaShade	(byte level = 255)	{ return Set(level, 0, level); };
	RGBdata& YellowShade	(byte level = 255)	{ return Set(level, level, 0); };
	RGBdata& GrayShade		(byte level = 0)	{ return Set(level, level, level); };

	// IOTools member functions

	// New data is always stored in object
	// When appropriate, object is also returned by reference

	RGBdata& Request(						// respond-or-default
		const string&		prompt,			// prompt to user
		const RGBdata&		answer			// default answer
	);


	RGBdata& Request(						// mandatory response
		const string&		prompt			// prompt to user
	);


	bool Reading(							// respond-or-decline
		const string&		prompt			// prompt to user
	);
	
	
	// member functions for conversion of string to PointData

	// at the start position string should contain 3 byte values: r g b
	// optionally r g b may be separated by commas as in: r, g, b
	
	RGBdata& FromString(
		const string&	source,			// string to read
		int				start,			// start position to read
		int&			next,			// next  position to read
		int&			error			// string IO error code
	);


	RGBdata& FromString(
		const char*		start,			// start position to read
		const char*&	next,			// next  position to read
		int&			error			// string IO error code
	);


	// member function for conversion of RGBdata to string

	// wide format: r, g, b using a field width of 3 each
	// otherwise:   r, g, b using minimal space 
	
	string ToString(bool wide = false) const;

}; // class RGBdata


// Stand alone routines to generate pure shades:
//		Red, Green, Blue, Cyan, Magenta, Yellow, Gray
// 		Note that GrayShade defaults to level zero to produce black

inline RGBdata RedShade		(byte level = 255)	{ return RGBdata(level, 0, 0); }
inline RGBdata GreenShade	(byte level = 255)	{ return RGBdata(0, level, 0); }
inline RGBdata BlueShade	(byte level = 255)	{ return RGBdata(0, 0, level); }
inline RGBdata CyanShade	(byte level = 255)	{ return RGBdata(0, level, level); }
inline RGBdata MagentaShade	(byte level = 255)	{ return RGBdata(level, 0, level); }
inline RGBdata YellowShade	(byte level = 255)	{ return RGBdata(level, level, 0); }
inline RGBdata GrayShade	(byte level = 0)	{ return RGBdata(level, level, level); }


// This set of functions parallels the functions for points and rects


inline void SetColor(RGBdata& Color, byte r, byte g, byte b) {
	Color.Set(r, g, b);
}


inline void GetColor(const RGBdata& Color, byte& r, byte& g, byte& b) {
	Color.Get(r, g, b);
}


inline void GetColor(const RGBdata& Color, short& r, short& g, short& b) {
	Color.Get(r, g, b);
}


inline void GetColor(const RGBdata& Color, long& r, long& g, long& b) {
	Color.Get(r, g, b);
}


inline void GetColor(const RGBdata& Color, int& r, int& g, int& b) {
	Color.Get(r, g, b);
}


inline RGBdata MakeColor(byte r, byte g, byte b) {
	return RGBdata(r, g, b);
}


// This set of functions is patterned after procedural IOTools


inline RGBdata RequestRGB(				// respond-or-default
	const string&		prompt,			// prompt to user
	const RGBdata&		answer			// default answer
) {
	RGBdata response;

	return response.Request(prompt, answer);
}
	
	
inline RGBdata RequestRGB(				// mandatory response
	const string&		prompt			// prompt to user
) {
	RGBdata response;

	return response.Request(prompt);
}
	
	
inline bool ReadingRGB(					// respond-or-decline
	const string&		prompt,			// prompt to user
	RGBdata&			answer			// user answer if provided
) {
	return answer.Reading(prompt);
}
	
	
inline RGBdata StringToRGB(
	const string&	source,			// string to read
	int				start,			// start position to read
	int&			next,			// next  position to read
	int&			error			// string IO error code
) {
	RGBdata response;

	return response.FromString(source, start, next, error);
}
	
	
inline RGBdata StringToRGB(
	const char*		start,			// start position to read
	const char*&	next,			// next  position to read
	int&			error			// string IO error code
) {
	RGBdata response;

	return response.FromString(start, next, error);
}
	
	
inline ostream& operator<< (ostream& os, const RGBdata& data) {
	os << data.ToString(true);
	return os;
}

#endif // RGB_H_
