#ifndef _FishIDE_Settings_h_
#define _FishIDE_Settings_h_

#include <Core/Core.h>

using namespace Upp;

#include "AVersion.h"

class Board;

typedef enum
{
	TOOLKIT_OK = 0,
	TOOLKIT_PATH_MISSING,
	TOOLKIT_PATH_INVALID,
	SKETCHBOOK_PATH_MISSING,
	UPLOADER_MISSING,
	UPLOADER_CONFIG_MISSING,
	GCC_MISSING
} ToolkitStatus;

// get application configuration path
String const &GetConfigPath(void);

class SettingsClass
{
	friend SettingsClass &__GetSettings();
	
	private:
	
		// sketch folder
		String _sketchFolder;
		
		// examples URLs and their contents
		// (contents are refreshed when loading, if a connection is available)
		VectorMap<String, String> _examplesURLs;
		
		// packages URLs and their contents
		// (contents are refreshed when loading, if a connection is available)
		VectorMap<String, String> _packagesURLs;
		
		// library URLs and their contents
		// (contents are refreshed when loading, if a connection is available)
		VectorMap<String, String> _librariesURLs;
		
		// map of available boards
		ArrayMap<String, Board *> _availableBoards;
		
		// active board name
		String _activeBoard;
		
		// active sub-menu board values
		VectorMap<String, String>_activeBoardMenus;
		
		// core libraries locations
		// can be different from platform's ones
		String _platformLibsRoot;
		
		// system libraries locations
		// those are managed by library manager
		String _systemLibsRoot;

		// users libraries root
		String _userLibsRoot;
		
		// current board's architecture
		String _architecture;
		
		// setup lib and core folders
		void SetupFolders(void);

		// serial port device
		String _device;

		// compiler options
		int _compilerVerbosity;
		int _compilerWarnLevel;
		int _compilerOptimizations;
		String _compilerUserWarnings;
		bool _compilerFullRebuild;
		
		bool _compilerAutoLibDependencies;

		// uploader options
		int _uploaderVerbosity;
		
		// ide options
		bool _ideCreateProjectStubs;
		bool _ideCreateLibraryStubs;
		bool _ideRememberFiles;
		bool _ideRememberProjects;
		bool _ideSysLibsReadOnly;
		bool _ideShowSplash;
		
		// editor options
		int _editorTabsize;
		int _editorIndentAmount;
		bool _editorShowTabs;
		bool _editorIndentSpaces;
		bool _editorNoParenthesisIndent;
		bool _editorShowLineNumbers;
		bool _editorBookmarkPos;
		bool _editorFindpicksel;
		bool _editorFindpicktext;
		bool _editorPersistentFindReplace;
		bool _editorFindReplaceRestorePos;
		bool _editorAutoEnclose;
		
		// astyle stuffs
		bool _astyleBracketIndent;
		bool _astyleNamespaceIndent;
		bool _astyleBlockIndent;
		bool _astyleCaseIndent;
		bool _astyleClassIndent;
		bool _astyleLabelIndent;
		bool _astyleSwitchIndent;
		bool _astylePreprocessorIndent;
		int _astyleMinInStatementIndentLength;
		int _astyleMaxInStatementIndentLength;
		bool _astyleBreakClosingHeaderBracketsMode;
		bool _astyleBreakElseIfsMode;
		bool _astyleBreakOneLineBlocksMode;
		bool _astyleSingleStatementsMode;
		bool _astyleBreakBlocksMode;
		bool _astyleBreakClosingHeaderBlocksMode;
		int _astyleBracketFormatMode;
		int _astyleParensPaddingMode;
		bool _astyleParensUnPaddingMode;
		bool _astyleOperatorPaddingMode;
		bool _astyleEmptyLineFill;
		bool _astyleTabSpaceConversionMode;
		
		// constructor
		SettingsClass();
		
		// refresh examples jsons
		void RefreshExamplesJSONs(void);
		
		// refresh packages jsons
		void RefreshPackagesJSONs(void);
		
		// refresh libraries jsons
		void RefreshLibrariesJSONs(void);
		
		// scan available boards
		void scanBoards(void);

		// mark installed platforms and tools upon loading config
		void MarkInstalled(void);
		
		// stuff to speed up loading of packages and libraries
		// after initial load
		bool examplesLoaded;
		bool packagesLoaded;
		bool librariesLoaded;
		
	protected:

	public:
	
		// xml support
		void Xmlize(XmlIO &xml);
		
		// refresh installed platforms and tools
		void RefreshInstalled(void);
		
		// refresh examples -- needed upon loading or settings changed
		void RefreshExamples(bool force = false);

		// refresh packages -- needed upon loading or settings changed
		void RefreshPackages(bool force = false);
		
		// refresh libraries -- needed upon loading or settings changed
		void RefreshLibraries(bool force = false);

		// gets ide root -- aka ide configuration path
		String const &GetConfigPath(void) const { return ::GetConfigPath(); }
		String const &GetIdeRoot(void) const { return ::GetConfigPath(); }
		
		// get sketch folder location
		String const &GetSketchFolder(void) const { return _sketchFolder; }
		SettingsClass &SetSketchFolder(String const &s) { _sketchFolder = s; return *this; }
		
		// get examples urls in string format (\n terminates each url)
		String GetExamplesURLs(void) const;
		SettingsClass &SetExamplesURLs(String const &s);

		// get package urls in string format (\n terminates each url)
		String GetPackagesURLs(void) const;
		SettingsClass &SetPackagesURLs(String const &s);
		
		// get libraries urls in string format (\n terminates each url)
		String GetLibrariesURLs(void) const;
		SettingsClass &SetLibrariesURLs(String const &s);
		
		// get all available boards
		ArrayMap<String, Board*> const &GetAvailableBoards(void) const { return _availableBoards; }
		
		// get selected board
		Board *GetSelectedBoard(void);
		
		// set/get active board name
		String const &GetActiveBoard(void) const { return _activeBoard; }
		SettingsClass &SetActiveBoard(String const &name);
		
		// get core libraries locations
		// can be different from platform's ones
		String const &GetPlatformLibsRoot(void) const { return _platformLibsRoot; }
		
		// get system libraries location
		// those ones are managed by library manager
		String const &GetSystemLibsRoot(void) const { return _systemLibsRoot; }
		
		// users libraries root
		String const &GetUserLibsRoot(void) const { return _userLibsRoot; }
		
		// managed examples root
		String GetExamplesRoot(void) const { return AppendFileName(GetIdeRoot(), "examples"); }
		
		// current architecture
		String const &GetArchitecture(void) const { return _architecture; }
		
		// set/get serial port device
		SettingsClass &SetDevice(String const &dev) { _device = dev; return *this; }
		String const &GetDevice(void) const { return _device; }
		
		// compiler options
		SettingsClass &SetCompilerVerbosity(int v);
		int GetCompilerVerbosity(void) const				{ return _compilerVerbosity; }
	
		SettingsClass &SetCompilerWarnLevel(int v);
		int GetCompilerWarnLevel(void) const				{ return _compilerWarnLevel; }
		
		SettingsClass &SetCompilerOptimizations(int o);
		int GetCompilerOptimizations(void)					{ return _compilerOptimizations; }
	
		SettingsClass &SetCompilerUserWarnings(String const &s);
		String const &GetCompilerUserWarnings(void) const	{ return _compilerUserWarnings; }
	
		SettingsClass &SetCompilerFullRebuild(bool b);
		bool GetCompilerFullRebuild(void) const				{ return _compilerFullRebuild; }
		
		SettingsClass &SetCompilerAutoLibDependencies(bool b);
		bool GetCompilerAutoLibDependencies(void) const		{ return _compilerAutoLibDependencies; }
		
		// uploader options
		SettingsClass &SetUploaderVerbosity(int v);
		int GetUploaderVerbosity(void) const				{ return _uploaderVerbosity; }
		
		// ide options
		SettingsClass &SetIdeCreateProjectStubs(bool b);
		bool GetIdeCreateProjectStubs(void) const			{ return _ideCreateProjectStubs; }
	
		SettingsClass &SetIdeCreateLibraryStubs(bool b);
		bool GetIdeCreateLibraryStubs(void) const			{ return _ideCreateLibraryStubs; }
	
		SettingsClass &SetIdeRememberFiles(bool b);
		bool GetIdeRememberFiles(void) const 				{ return _ideRememberFiles; }
	
		SettingsClass &SetIdeRememberProjects(bool b);
		bool GetIdeRememberProjects(void) const 			{ return _ideRememberProjects; }
		
		SettingsClass &SetIdeSysLibsReadOnly(bool b);
		bool GetIdeSysLibsReadOnly(void) const 				{ return _ideSysLibsReadOnly; }
		
		SettingsClass &SetIdeShowSplash(bool b);
		bool GetIdeShowSplash(void) const 					{ return _ideShowSplash; }
		
		// try to detect sketchbook path. If not found, return a standard path
		// depending on OS
		String LocateSketchbook(void) const;
		
		// callback triggered by changes in settings
		// use to re-sync board when change in toolkit
		Callback WhenChange;

		// astyle stuffs
		bool GetAstyleBracketIndent(void) const							{ return _astyleBracketIndent; }
		SettingsClass &SetAstyleBracketIndent(bool b)					{ _astyleBracketIndent = b; return *this; }
		bool GetAstyleNamespaceIndent(void)	const						{ return _astyleNamespaceIndent; }
		SettingsClass &SetAstyleNamespaceIndent(bool b)					{ _astyleNamespaceIndent = b; return *this; }
		bool GetAstyleBlockIndent(void) const							{ return _astyleBlockIndent; }
		SettingsClass &SetAstyleBlockIndent(bool b)						{ _astyleBlockIndent = b; return *this; }
		bool GetAstyleCaseIndent(void) const							{ return _astyleCaseIndent; }
		SettingsClass &SetAstyleCaseIndent(bool b)						{ _astyleCaseIndent = b; return *this; }
		bool GetAstyleClassIndent(void)	const							{ return _astyleClassIndent; }
		SettingsClass &SetAstyleClassIndent(bool b)						{ _astyleClassIndent = b; return *this; }
		bool GetAstyleLabelIndent(void) const							{ return _astyleLabelIndent; }
		SettingsClass &SetAstyleLabelIndent(bool b)						{ _astyleLabelIndent = b; return *this; }
		bool GetAstyleSwitchIndent(void) const							{ return _astyleSwitchIndent; }
		SettingsClass &SetAstyleSwitchIndent(bool b)					{ _astyleSwitchIndent = b; return *this; }
		bool GetAstylePreprocessorIndent(void) const					{ return _astylePreprocessorIndent; }
		SettingsClass &SetAstylePreprocessorIndent(bool b)				{ _astylePreprocessorIndent = b; return *this; }
		int GetAstyleMinInStatementIndentLength(void) const				{ return _astyleMinInStatementIndentLength; }
		SettingsClass &SetAstyleMinInStatementIndentLength(int i)		{ _astyleMinInStatementIndentLength = i; return *this; }
		int GetAstyleMaxInStatementIndentLength(void) const				{ return _astyleMaxInStatementIndentLength; }
		SettingsClass &SetAstyleMaxInStatementIndentLength(int i)		{ _astyleMaxInStatementIndentLength = i; return *this; }
		bool GetAstyleBreakClosingHeaderBracketsMode(void) const		{ return _astyleBreakClosingHeaderBracketsMode; }
		SettingsClass &SetAstyleBreakClosingHeaderBracketsMode(bool b)	{ _astyleBreakClosingHeaderBracketsMode = b; return *this; }
		bool GetAstyleBreakElseIfsMode(void) const						{ return _astyleBreakElseIfsMode; }
		SettingsClass &SetAstyleBreakElseIfsMode(bool b)				{ _astyleBreakElseIfsMode = b; return *this; }
		bool GetAstyleBreakOneLineBlocksMode(void) const				{ return _astyleBreakOneLineBlocksMode; }
		SettingsClass &SetAstyleBreakOneLineBlocksMode(bool b)			{ _astyleBreakOneLineBlocksMode = b; return *this; }
		bool GetAstyleSingleStatementsMode(void) const					{ return _astyleSingleStatementsMode; }
		SettingsClass &SetAstyleSingleStatementsMode(bool b)			{ _astyleSingleStatementsMode = b; return *this; }
		bool GetAstyleBreakBlocksMode(void) const						{ return _astyleBreakBlocksMode; }
		SettingsClass &SetAstyleBreakBlocksMode(bool b)					{ _astyleBreakBlocksMode = b; return *this; }
		bool GetAstyleBreakClosingHeaderBlocksMode(void) const			{ return _astyleBreakClosingHeaderBlocksMode; }
		SettingsClass &SetAstyleBreakClosingHeaderBlocksMode(bool b)	{ _astyleBreakClosingHeaderBlocksMode = b; return *this; }
		int GetAstyleBracketFormatMode(void) const						{ return _astyleBracketFormatMode; }
		SettingsClass &SetAstyleBracketFormatMode(int i)				{ _astyleBracketFormatMode = i; return *this; }
		int GetAstyleParensPaddingMode(void) const						{ return _astyleParensPaddingMode; }
		SettingsClass &SetAstyleParensPaddingMode(int i)				{ _astyleParensPaddingMode = i; return *this; }
		bool GetAstyleParensUnPaddingMode(void) const					{ return _astyleParensUnPaddingMode; }
		SettingsClass &SetAstyleParensUnPaddingMode(bool b)				{ _astyleParensUnPaddingMode = b; return *this; }
		bool GetAstyleOperatorPaddingMode(void) const					{ return _astyleOperatorPaddingMode; }
		SettingsClass &SetAstyleOperatorPaddingMode(bool b)				{ _astyleOperatorPaddingMode = b; return *this; }
		bool GetAstyleEmptyLineFill(void) const							{ return _astyleEmptyLineFill; }
		SettingsClass &SetAstyleEmptyLineFill(bool b)					{ _astyleEmptyLineFill = b; return *this; }
		bool GetAstyleTabSpaceConversionMode(void) const				{ return _astyleTabSpaceConversionMode; }
		SettingsClass &SetAstyleTabSpaceConversionMode(bool b)			{ _astyleTabSpaceConversionMode = b; return *this; }

		// editor options
		int GetEditorTabsize(void) const								{ return _editorTabsize; }
		SettingsClass &SetEditorTabsize(int i)							{ _editorTabsize = i; return *this; }
		int GetEditorIndentAmount(void) const							{ return _editorIndentAmount; }
		SettingsClass &SetEditorIndentAmount(int i)						{ _editorIndentAmount = i; return *this; }
		bool GetEditorShowTabs(void) const								{ return _editorShowTabs; }
		SettingsClass &SetEditorShowTabs(bool b)							{ _editorShowTabs = b; return *this; }
		bool GetEditorIndentSpaces(void) const							{ return _editorIndentSpaces; }
		SettingsClass &SetEditorIndentSpaces(bool b)						{ _editorIndentSpaces = b; return *this; }
		bool GetEditorNoParenthesisIndent(void) const					{ return _editorNoParenthesisIndent; }
		SettingsClass &SetEditorNoParenthesisIndent(bool b)				{ _editorNoParenthesisIndent = b; return *this; }
		bool GetEditorShowLineNumbers(void) const						{ return _editorShowLineNumbers; }
		SettingsClass &SetEditorShowLineNumbers(bool b)					{ _editorShowLineNumbers = b; return *this; }
		bool GetEditorBookmarkPos(void) const							{ return _editorBookmarkPos; }
		SettingsClass &SetEditorBookmarkPos(bool b)						{ _editorBookmarkPos = b; return *this; }
		bool GetEditorFindpicksel(void) const							{ return _editorFindpicksel; }
		SettingsClass &SetEditorFindpicksel(bool b)						{ _editorFindpicksel = b; return *this; }
		bool GetEditorFindpicktext(void) const							{ return _editorFindpicktext; }
		SettingsClass &SetEditorFindpicktext(bool b)					{ _editorFindpicktext = b; return *this; }
		bool GetEditorPersistentFindReplace(void) const					{ return _editorPersistentFindReplace; }
		SettingsClass &SetEditorPersistentFindReplace(bool b)			{ _editorPersistentFindReplace = b; return *this; }
		bool GetEditorFindReplaceRestorePos(void) const					{ return _editorFindReplaceRestorePos; }
		SettingsClass &SetEditorFindReplaceRestorePos(bool b)			{ _editorFindReplaceRestorePos = b; return *this; }
		bool GetEditorAutoEnclose(void) const							{ return _editorAutoEnclose; }
		SettingsClass &SetEditorAutoEnclose(bool b)						{ _editorAutoEnclose = b; return *this; }
		
		String GetVersion(void) const;
};

extern SettingsClass &__GetSettings(void);

#define Settings __GetSettings()

#endif
