#ifndef _FishIDE_Theme_h_
#define _FishIDE_Theme_h_

#include <Core/Core.h>
#include <Draw/Draw.h>

using namespace Upp;

class Theme
{
	public:
	
		struct HL : Moveable<HL>
		{
			Color _color;
			bool _bold;
			bool _italic;
			bool _underline;
			
			void Xmlize(XmlIO xml);
			HL(Color c, bool b, bool i, bool u) : _color(c), _bold(b), _italic(i), _underline(u) {}
			HL() { _color = Null; _bold = _italic = _underline = false; }
		};
		
		struct FontInfo
		{
			String	_name;
			int		_height;
			bool	_bold;
			bool	_italic;
			bool	_nonAntiAliased;
			
			void Xmlize(XmlIO xml);
			FontInfo() { _name = ""; _height = 0; _bold = _italic = _nonAntiAliased = false; }
			FontInfo(String const &name, int height, bool bold, bool italic, bool nonAntiAliased) :
				_name(name), _height(height), _bold(bold), _italic(italic), _nonAntiAliased(nonAntiAliased)
			{}
		};
		
	private:
	
		// gui colors
		VectorMap<String, Color> _colors;
		
		// syntax hihglight colors and properties
		VectorMap<String, HL> _hl;
		
		// fonts settings
		int _scopeHL;
		int _bracesHL;
		int _conditionalsInfo;
		bool _conditionalTracing;
		bool _thousandsSeparator;
		bool _currentLine;
	
		FontInfo	_ideFont;
		FontInfo	_editorFont;
		FontInfo	_consoleFont;
		FontInfo	_serialPortFont;
		
		void AddHlStyle(int idx, Color col, bool bold = false, bool italic = false, bool underline = false);
		
	protected:
	
	public:
	
		typedef Theme CLASSNAME;
	
		// constructor
		Theme();
		
		// copy constructor
		Theme(Theme const &t);
		
		// pick constructor
		Theme(Theme &&t);
		
		// assignment
		Theme &operator=(Theme const &t);
		Theme &operator=(Theme &&t);
		
		// destructor
		~Theme();
		
		// set default values
		void Defaults();
		
		// apply theme
		void Apply(void) const;
		
		// xmlize
		void Xmlize(XmlIO xml);
		
		// get/set colors
		VectorMap<String, Color> const &GetColors(void) const;
		void SetColors(VectorMap<String, Color> const &colors);
		
		// get/set syntax highlight
		VectorMap<String, HL> const &GetSyntax(void) const;
		void SetSyntax(VectorMap<String, HL> const &hl);
		
		int GetScopeHL(void) const				{ return _scopeHL; 				}
		void SetScopeHL(int s)					{ _scopeHL = s;					}
		int GetBracesHL(void) const				{ return _bracesHL;				}
		void SetBracesHL(int b)					{ _bracesHL = b;				}
		int GetConditionalsInfo(void) const		{ return _conditionalsInfo;		}
		void SetConditionalsInfo(int i)			{ _conditionalsInfo = i;		}
		bool GetConditionalTracing(void) const	{ return _conditionalTracing;	}
		void SetConditionalTracing(bool c)		{ _conditionalTracing = c;		}
		bool GetThousandsSeparator(void) const	{ return _thousandsSeparator;	}
		void SetThousandsSeparator(bool t)		{ _thousandsSeparator = t;		}
		bool GetCurrentLine(void) const			{ return _currentLine;			}
		void SetCurrentLine(bool c)				{ _currentLine = c;				}
	
		FontInfo const &GetIdeFontInfo(void) const			{ return _ideFont;			}
		FontInfo &GetIdeFontInfo(void) 						{ return _ideFont;			}
		void SetIdeFontInfo(FontInfo const &f)				{ _ideFont = f;				}
		FontInfo const &GetEditorFontInfo(void) const		{ return _editorFont;		}
		FontInfo &GetEditorFontInfo(void) 					{ return _editorFont;		}
		void SetEditorFontInfo(FontInfo const &f)			{ _editorFont = f;			}
		FontInfo const &GetConsoleFontInfo(void) const		{ return _consoleFont;		}
		FontInfo &GetConsoleFontInfo(void) 					{ return _consoleFont;		}
		void SetConsoleFontInfo(FontInfo const &f)			{ _consoleFont = f;			}
		FontInfo const &GetSerialPortFontInfo(void) const	{ return _serialPortFont;	}
		FontInfo &GetSerialPortFontInfo(void) 				{ return _serialPortFont;	}
		void SetSerialPortFontInfo(FontInfo const &f)		{ _serialPortFont = f;		}
		
		Font GetIdeFont(void) const;
		Font GetEditorFont(void) const;
		Font GetConsoleFont(void) const;
		Font GetSerialPortFontFont(void) const;

		// bottom pane text colors
		Color GetMessagesTextColor(void) const;
		Color GetErrorMessagesTextColor(void) const;
		Color GetMessagesBackgroundColor(void) const;
		Color GetSerialPortInputTextColor(void) const;
		Color GetSerialPortInputBackgroundColor(void) const;
		Color GetSerialPortOutputTextColor(void) const;
		Color GetSerialPortOutputBackgroundColor(void) const;

		// callback to propagate theme apply
		Event<Theme const *> WhenApply;
};

class ThemesClass
{
	friend ThemesClass &__GetThemes(void);
	
	private:
	
		// the themes
		ArrayMap<String, Theme> _themes;
	
		// current theme
		int _current;
	
		// constructor
		ThemesClass();
		
		// applay propagation handler
		void applyCb(Theme const *t) const { WhenApply(t); }
		
	protected:
	
	public:
	
		typedef ThemesClass CLASSNAME;
	
		// destructor
		~ThemesClass();
		
		// get all available theme names
		Vector<String> GetNames(void) const;
		
		// get themes count
		int GetCount(void) const { return _themes.GetCount(); }
		
		// check for presence by name
		bool Has(String const &name) const { return _themes.Find(name) >= 0; }
		
		// get a theme
		Theme const *Get(String const &name) const;
		Theme *Get(String const &name);
		Theme const *Get(int idx) const;
		Theme *Get(int idx);
		
		// add a new theme
		Theme &Add(String const &name, Theme const &base);
		
		// append themes from a map
		void Append(ArrayMap<String, Theme> const &themes);
		
		// remove a theme
		bool Remove(String const &name);
		bool Remove(int idx);
		
		// get current theme
		Theme const &GetCurrent(void) const;
		int GetCurrentIndex(void) const { return _current; }
		
		// set current theme
		void SetCurrentTheme(String const &name);
		void SetCurrentIndex(int idx);
		
		// apply current theme
		void ApplyCurrent(void) const;
		
		// rename theme
		bool Rename(String const &oldName, String const &newName);
		
		// xml support
		void Xmlize(XmlIO xml);
		
		// propagate theme apply
		Event<Theme const *>WhenApply;
};

extern ThemesClass &__GetThemes(void);

#define Themes __GetThemes()

#endif
