/*
this file is part of Notepad++
Copyright (C)2003 Don HO <donho@altern.org>

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef USER_DEFINE_H
#define USER_DEFINE_H

#include <string>
#include <shlwapi.h>

#include "UserDefineResource.h"
#include "ControlsTab.h"
#include "ColourPicker.h"
#include "UserDefineLangReference.h"
//#include "Parameters.h"

class ScintillaEditView;
class UserLangContainer;
class Style;

#define WL_LEN_MAX 1024

#define BOLD_MASK     1
#define ITALIC_MASK   2

const int nbWordList = 4;
const int nbBlockColor = 5;
const int nbBoolean = 5;

const bool DOCK = true;
const bool UNDOCK = false;

const int maxNbGroup = 10;

const int KWL_FOLDER_OPEN_INDEX = 1;
const int KWL_FOLDER_CLOSE_INDEX = 2;
const int KWL_OPERATOR_INDEX = 3;
const int KWL_COMMENT_INDEX = 4;
const int KWL_KW1_INDEX = 5;
const int KWL_KW2_INDEX = 6;
const int KWL_KW3_INDEX = 7;
const int KWL_KW4_INDEX = 8;

const int STYLE_DEFAULT_INDEX = 0;
const int STYLE_BLOCK_OPEN_INDEX = 1;
const int STYLE_BLOCK_CLOSE_INDEX = 2;
const int STYLE_WORD1_INDEX = 3;
const int STYLE_WORD2_INDEX = 4;
const int STYLE_WORD3_INDEX = 5;
const int STYLE_WORD4_INDEX = 6;
const int STYLE_COMMENT_INDEX = 7;
const int STYLE_COMMENTLINE_INDEX = 8;
const int STYLE_NUMBER_INDEX = 9;
const int STYLE_OPERATOR_INDEX = 10;



class SharedParametersDialog : public StaticDialog
{
public:
	SharedParametersDialog() {};
	SharedParametersDialog(int nbGroup) : _nbGroup(nbGroup) {};
	virtual void updateDlg() = 0;


protected :
	//Shared data
	static UserLangContainer *_pUserLang;
	static ScintillaEditView *_pScintilla;
/*
	virtual void redraw() const {
		RECT rc;
		getClientRect(rc);
		//display(false);
		//display(true);
		BOOL b = ::InvalidateRect(_hSelf, &rc, FALSE);
		b = ::UpdateWindow(_hSelf);
		b= 0;
	};	
*/	



	
	//data for per object
	int _nbGroup;
	ColourPicker *_pFgColour[maxNbGroup];
    ColourPicker *_pBgColour[maxNbGroup];
	int _fgStatic[maxNbGroup];
	int _bgStatic[maxNbGroup];
	int _fontSizeCombo[maxNbGroup];
	int _fontNameCombo[maxNbGroup];

    BOOL CALLBACK run_dlgProc(UINT Message, WPARAM wParam, LPARAM lParam);
    void initControls();
	void styleUpdate(const Style & style, ColourPicker *pFgColourPicker, ColourPicker *pBgColourPicker, 
					 int fontComboId, int fontSizeComboId, int boldCheckId, int italicCheckId);

	virtual void setKeywords2List(int ctrlID) = 0;
	virtual int getGroupIndexFromCombo(int ctrlID, bool & isFontSize) const = 0;
	virtual int getStylerIndexFromCP(HWND hWnd, bool & isFG, ColourPicker **ppCP) const = 0;
	virtual int getGroupeIndexFromCheck(int ctrlID, bool & isBold) const = 0;
	

};

class FolderStyleDialog : public SharedParametersDialog
{
public:
	FolderStyleDialog();
	void updateDlg();
protected :
	void setKeywords2List(int ctrlID);
	
	int getGroupIndexFromCombo(int ctrlID, bool & isFontSize) const {
        switch (ctrlID)
        {
			case IDC_DEFAULT_FONT_COMBO :
                isFontSize = false;
                return STYLE_DEFAULT_INDEX;

            case IDC_DEFAULT_FONTSIZE_COMBO :
                isFontSize = true;
                return STYLE_DEFAULT_INDEX;

            case IDC_FOLDEROPEN_FONT_COMBO :
                isFontSize = false;
                return STYLE_BLOCK_OPEN_INDEX;

            case IDC_FOLDEROPEN_FONTSIZE_COMBO :
                isFontSize = true;
                return STYLE_BLOCK_OPEN_INDEX;

            case IDC_FOLDERCLOSE_FONT_COMBO :
                isFontSize = false;
                return STYLE_BLOCK_CLOSE_INDEX;

            case IDC_FOLDERCLOSE_FONTSIZE_COMBO :
                isFontSize = true;
                return STYLE_BLOCK_CLOSE_INDEX;

            default :
                return -1;
        }
	};
	int getStylerIndexFromCP(HWND hWnd, bool & isFG, ColourPicker **ppCP) const;
	int getGroupeIndexFromCheck(int ctrlID, bool & isBold) const {
        switch (ctrlID)
        {
            case IDC_DEFAULT_BOLD_CHECK :
                isBold = true;
                return STYLE_DEFAULT_INDEX;

            case IDC_DEFAULT_ITALIC_CHECK :
                isBold = false;
                return STYLE_DEFAULT_INDEX;

            case IDC_FOLDEROPEN_BOLD_CHECK :
                isBold = true;
                return STYLE_BLOCK_OPEN_INDEX;

            case IDC_FOLDEROPEN_ITALIC_CHECK :
                isBold = false;
                return STYLE_BLOCK_OPEN_INDEX;

            case IDC_FOLDERCLOSE_BOLD_CHECK :
                isBold = true;
                return STYLE_BLOCK_CLOSE_INDEX;

            case IDC_FOLDERCLOSE_ITALIC_CHECK :
                isBold = false;
                return STYLE_BLOCK_CLOSE_INDEX;

            default :
                return -1;
        }
	};
};

class KeyWordsStyleDialog : public SharedParametersDialog
{
public:
	KeyWordsStyleDialog() ;
	void updateDlg();

protected :
	void setKeywords2List(int id);

    // SEE @REF #01
    int getGroupIndexFromCombo(int ctrlID, bool & isFontSize)  const {
        switch (ctrlID)
		{
			case IDC_KEYWORD1_FONT_COMBO :
                isFontSize = false;
                return STYLE_WORD1_INDEX;

			case IDC_KEYWORD1_FONTSIZE_COMBO : 
                isFontSize = true;
                return STYLE_WORD1_INDEX;

			case IDC_KEYWORD2_FONT_COMBO : 
                isFontSize = false;
                return STYLE_WORD2_INDEX;

			case IDC_KEYWORD2_FONTSIZE_COMBO : 
                isFontSize = true;
                return STYLE_WORD2_INDEX;

            case IDC_KEYWORD3_FONT_COMBO : 
                isFontSize = false;
                return STYLE_WORD3_INDEX;

			case IDC_KEYWORD3_FONTSIZE_COMBO : 
                isFontSize = true;
                return STYLE_WORD3_INDEX;

			case IDC_KEYWORD4_FONT_COMBO : 
                isFontSize = false;
                return STYLE_WORD4_INDEX;

			case IDC_KEYWORD4_FONTSIZE_COMBO : 
                isFontSize = true;
                return STYLE_WORD4_INDEX;

			default : 
                return -1;
		}
    };
    int getStylerIndexFromCP(HWND hWnd, bool & isFG, ColourPicker **ppCP) const;
    int getGroupeIndexFromCheck(int ctrlID, bool & isBold) const {
		switch (ctrlID)
        {
            case IDC_KEYWORD1_BOLD_CHECK :
                isBold = true;
                return STYLE_WORD1_INDEX;

            case IDC_KEYWORD1_ITALIC_CHECK :
                isBold = false;
                return STYLE_WORD1_INDEX;

            case IDC_KEYWORD2_BOLD_CHECK :
                isBold = true;
                return STYLE_WORD2_INDEX;

            case IDC_KEYWORD2_ITALIC_CHECK :
                isBold = false;
                return STYLE_WORD2_INDEX;

            case IDC_KEYWORD3_BOLD_CHECK :
                isBold = true;
                return STYLE_WORD3_INDEX;

            case IDC_KEYWORD3_ITALIC_CHECK :
                isBold = false;
                return STYLE_WORD3_INDEX;

            case IDC_KEYWORD4_BOLD_CHECK :
                isBold = true;
                return STYLE_WORD4_INDEX;

            case IDC_KEYWORD4_ITALIC_CHECK :
                isBold = false;
                return STYLE_WORD4_INDEX;

            default :
                return -1;
        }
    };
};

class CommentStyleDialog : public SharedParametersDialog
{
public :
    CommentStyleDialog();
    void updateDlg();
protected :
    void setKeywords2List(int id);
    int getGroupIndexFromCombo(int ctrlID, bool & isFontSize) const {
        switch (ctrlID)
		{
			case IDC_COMMENT_FONT_COMBO :
                isFontSize = false;
                return STYLE_COMMENT_INDEX;
			
			case IDC_COMMENT_FONTSIZE_COMBO : 
                isFontSize = true;
                return STYLE_COMMENT_INDEX;            
			
			case IDC_COMMENTLINE_FONT_COMBO : 
                isFontSize = false;
                return STYLE_COMMENTLINE_INDEX;
			
			case IDC_COMMENTLINE_FONTSIZE_COMBO : 
                isFontSize = true;
                return STYLE_COMMENTLINE_INDEX;
			
			case IDC_NUMBER_FONT_COMBO : 
                isFontSize = false;
                return STYLE_NUMBER_INDEX;
			
			case IDC_NUMBER_FONTSIZE_COMBO : 
                isFontSize = true;
                return STYLE_NUMBER_INDEX;

			
			default : 
                return -1;
		}
    };

    int getStylerIndexFromCP(HWND hWnd, bool & isFG, ColourPicker **ppCP) const;
    int getGroupeIndexFromCheck(int ctrlID, bool & isBold) const {
		switch (ctrlID)
        {
            case IDC_COMMENT_BOLD_CHECK :
                isBold = true;
                return STYLE_COMMENT_INDEX;
           
			case IDC_COMMENT_ITALIC_CHECK :
                isBold = false;
                return STYLE_COMMENT_INDEX;
            
			case IDC_COMMENTLINE_BOLD_CHECK :
                isBold = true;
                return STYLE_COMMENTLINE_INDEX;
           
			case IDC_COMMENTLINE_ITALIC_CHECK :
                isBold = false;
                return STYLE_COMMENTLINE_INDEX;
            
			case IDC_NUMBER_BOLD_CHECK :
                isBold = true;
                return STYLE_NUMBER_INDEX;
            
			case IDC_NUMBER_ITALIC_CHECK :
                isBold = false;
                return STYLE_NUMBER_INDEX;

            default :
                return -1;
        }
	};

private :
    void convertTo(char *dest, const char *toConvert, char prefix) const {
        int index = strlen(dest);
        dest[index++] = ' ';
        dest[index++] = prefix;
        for (int i = 0 ; i < strlen(toConvert) ; i++)
        {
            if (toConvert[i] == ' ')
            {
                if (toConvert[i+1] != ' ')
                {
                    dest[index++] = ' ';
                    dest[index++] = prefix;
                }
            }
            else
            {
                dest[index++] = toConvert[i];
            }
        }
        dest[index] = '\0'; 
    };
	void retrieve(char *dest, const char *toRetrieve, char prefix) const {
		int j = 0;
		bool begin2Copy = false;

		for (int i = 0 ; i < strlen(toRetrieve) ; i++)
		{
			if (((i == 0) || toRetrieve[i-1] == ' ') && (toRetrieve[i] == prefix))
			{
				begin2Copy = true;
				continue;
			}
			else if (((toRetrieve[i] == ' ') && begin2Copy == true))
			{
				dest[j++] = toRetrieve[i];
				begin2Copy = false;
			}
			if (begin2Copy)
				dest[j++] = toRetrieve[i];
		}
		dest[j++] = '\0';
	};
};

class SymbolsStyleDialog : public SharedParametersDialog 
{
public :
	static const bool ADD;
	static const bool REMOVE;
	void updateDlg();
protected :
	BOOL CALLBACK run_dlgProc(UINT Message, WPARAM wParam, LPARAM lParam);
    void setKeywords2List(int ctrlID) {};
    int getGroupIndexFromCombo(int ctrlID, bool & isFontSize) const {
		isFontSize = (ctrlID == IDC_SYMBOL_FONTSIZE_COMBO);
		return STYLE_OPERATOR_INDEX;
	};
    int getStylerIndexFromCP(HWND hWnd, bool & isFG, ColourPicker **ppCP) const;
    int getGroupeIndexFromCheck(int ctrlID, bool & isBold) const {
		isBold = (ctrlID == IDC_SYMBOL_BOLD_CHECK);
		return STYLE_OPERATOR_INDEX;
	};

private :
	void symbolAction(bool action);
	void listboxsRemoveAll();
	void listboxsInit();
	void listboxsReInit() {
		listboxsRemoveAll();
		listboxsInit();
	};
};

class UserDefineDialog : public SharedParametersDialog 
{
friend class ScintillaEditView;
public :
	UserDefineDialog();//: SharedParametersDialog(), _status(UNDOCK){};
	~UserDefineDialog();//{};

	void init(HINSTANCE hInst, HWND hPere, ScintillaEditView *pSev) {
		if (!_pScintilla)
		{
			Window::init(hInst, hPere);
			_pScintilla = pSev;
		}
	};

	void setScintilla(ScintillaEditView *pScinView) {
		_pScintilla = pScinView;
	};

 	virtual void UserDefineDialog::create(int dialogID) {
		StaticDialog::create(dialogID);
	}

	int getWidth() const {
		return _dlgPos.right;
	};

	int getHeight() const {
		return _dlgPos.bottom;
	};
	void doDialog(bool willBeShown = true) {
		if (!isCreated())
			create(IDD_GLOBAL_USERDEFINE_DLG);
		display(willBeShown);
	};

	virtual void reSizeTo(RECT & rc) // should NEVER be const !!!
	{ 
		Window::reSizeTo(rc);
		display(false);
		display();
	};

	void changeStyle();
    bool isDocked() const {return _status == DOCK;};
	int getNbKeywordList() {return nbKeywodList;};
	bool isDirty() const {return _isDirty;};
	HWND getFolderHandle() const {
		return _folderStyleDlg.getHSelf();
	};

	HWND getKeywordsHandle() const {
		return _keyWordsStyleDlg.getHSelf();
	};

	HWND getCommentHandle() const {
		return _commentStyleDlg.getHSelf();
	};

	HWND getSymbolHandle() const {
		return _symbolsStyleDlg.getHSelf();
	};

	void setTabName(int index, const char *name2set) {
		_ctrlTab.renameTab(index, name2set);
	};
protected :
	virtual BOOL CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam);

private :
	ControlsTab _ctrlTab;
	WindowVector _wVector;
	UserLangContainer *_pCurrentUserLang;

	FolderStyleDialog		_folderStyleDlg;
	KeyWordsStyleDialog		_keyWordsStyleDlg;
	CommentStyleDialog		_commentStyleDlg;
	SymbolsStyleDialog		_symbolsStyleDlg;    

	bool _status;
    RECT _dlgPos;
	//ScintillaEditView *_pScintilla;
   
	bool _isDirty;
	void getActualPosSize() {
        ::GetWindowRect(_hSelf, &_dlgPos);
        _dlgPos.right -= _dlgPos.left;
        _dlgPos.bottom -= _dlgPos.top;
    };
    void restorePosSize(){reSizeTo(_dlgPos);};
	void enableLangAndControlsBy(int index);

protected :
	void setKeywords2List(int ctrlID){};
    int getGroupIndexFromCombo(int ctrlID, bool & isFontSize) const {return -1;};
    int getStylerIndexFromCP(HWND hWnd, bool & isFG, ColourPicker **ppCP) const {return -1;};
    int getGroupeIndexFromCheck(int ctrlID, bool & isBold) const {return -1;};
	void updateDlg() {
		_folderStyleDlg.updateDlg();
		_keyWordsStyleDlg.updateDlg();
		_commentStyleDlg.updateDlg();
		_symbolsStyleDlg.updateDlg();
	};
};

class StringDlg : public StaticDialog
{
public :
        StringDlg() : StaticDialog() {};
        void init(HINSTANCE hInst, HWND parent, char *title, char *staticName, char *text2Set) {
            Window::init(hInst, parent);
			strcpy(_title, title);
			strcpy(_static, staticName);
			strcpy(_textValue, text2Set);
        };

        int doDialog() {
			return ::DialogBoxParam(_hInst, MAKEINTRESOURCE(IDD_STRING_DLG), _hParent,  (DLGPROC)dlgProc, (LPARAM)this);
        };

		virtual void destroy() {};

protected :
BOOL CALLBACK run_dlgProc(UINT Message, WPARAM wParam, LPARAM lParam)
{

	switch (Message)
	{
		case WM_INITDIALOG :
		{
			::SetWindowText(_hSelf, _title);
			::SetDlgItemText(_hSelf, IDC_STRING_STATIC, _static);
			::SetDlgItemText(_hSelf, IDC_STRING_EDIT, _textValue);

			return TRUE;
		}

		case WM_COMMAND : 
		{
			switch (wParam)
			{
				case IDOK :
				{
					::GetDlgItemText(_hSelf, IDC_STRING_EDIT, _textValue, 256);
					::EndDialog(_hSelf, int(_textValue));
					return TRUE;
				}

				case IDCANCEL :
					::EndDialog(_hSelf, int(NULL));
					return TRUE;

				default:
					return FALSE;
			}
		}
		default :
			return FALSE;
	}

	return FALSE;
}

private :
		char _title[64];
        char _textValue[256];
		char _static[32];
		//POINT _p;

};


#endif //USER_DEFINE_H
