/*****************************************************************************
Open Source MIT License

Copyright (c) 2017 Matthew Ahmed

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*****************************************************************************/

// Settings.h: interface for the CSettings class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SETTINGS_H__22CE3EF4_55C0_11D3_BD00_444553540000__INCLUDED_)
#define AFX_SETTINGS_H__22CE3EF4_55C0_11D3_BD00_444553540000__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

//- SHAKER DEFS
// For label and date stamp pairs of radio buttons
#define RB_BEFORE 0
#define RB_AFTER  1

// Repeat handling radio buttons, shuffle tab
#define RB_REPEAT_DIST    0
#define RB_REPEAT_SEP     1
#define RB_REPEAT_IGNORE  2

// Genres & Playlists listbox order
#define RB_GENRES_FIRST    0
#define RB_PLISTS_FIRST    1

// Version 3.0 Remember max age for "new" as
#define RB_NUM_DAYS    0
#define RB_FIXED_DATE  1

//// v3.22 now applied to ini->nPlaylistFmt
//#define RB_FMT_LAST   0 // v3.22 new
//#define RB_FMT_WPL    1 // v3.22 changed from 0
//#define RB_FMT_M3U    2 // v3.22 changed from 1
//#define RB_FMT_M3U8   3 // v3.22 changed from 2

// Version 3.3: 0 still last used, 1 wpl; M3U-ANSI change 2 to 3; M3U-UTF8 3 to 2
#define RB_FMT_LAST   0 // v3.22 new
#define RB_FMT_WPL    1 // v3.22 changed from 0
#define RB_FMT_M3U8   2 // v3.3 changed from 3
#define RB_FMT_M3U    3 // v3.3 changed from 2

// Default repetitions for star ratings
#define UREPS1_DEFAULT   1
#define UREPS2_DEFAULT   2
#define UREPS3_DEFAULT   3
#define UREPS4_DEFAULT   5
#define UREPS5_DEFAULT   9
#define UREPS_SAME_DEFAULT 4
#define UMAX_REPS_DEFAULT  15
//#define UREPS_REMEMBER_NO       0
//#define UREPS_REMEMBER_SESSION  1 
//#define UREPS_REMEMBER_ALWAYS   2
#define UREPS_REMEMBER_ALWAYS   0
#define UREPS_REMEMBER_SESSION  1 
#define UREPS_REMEMBER_NO       2
#define UREPS_REMEMBER_DEFAULT  UREPS_REMEMBER_SESSION

#define NDAYSNEW_DEFAULT  45

#define USEPONLY_DEFAULT  30
#define USEPDIST_DEFAULT  50

#define NTRUNCSIZE_DEFAULT  300

// Album art filename radio buttons, copy tab
// Same constants used for source and target variable
#define RB_JPG_F    0
#define RB_JPG_A    1  // "AlbumArt.jpg" (no space)
#define RB_JPG_AA   2  // "Album Art.jpg"
#define RB_JPG_O    3

// Copy option radio buttons
#define RB_SRC_LAST 0
#define RB_SRC_LIB  1
// #define RB_SRC_RIP  2

#define RB_TGT_MUS  0
#define RB_TGT_OTH  1


#define NUM_OF_SECTS     5   // This must be exactly how many sections in class; update if add section
#define MAX_KEYS_IN_SECT 50  // OK if this is way more than used, just wastes a little memory

typedef struct IniKeySet
{
	LPTSTR sKeyName;
	LPTSTR * ppS;		// pointer to actual var if string pointer
	INT * pN;				// pointer to actual var if int
} IniKey;

typedef struct IniSection
{
	LPTSTR sSectName;
	UINT uNextInd;
	IniKey * pKeyArr[MAX_KEYS_IN_SECT];
} IniSect;

class CSettings  
{
public:
	////- IF MORE THAN ONE SECTION, ADD IT HERE AND RE#define NUM_OF_SECTS
	////- AND POINT ARRAY MEMBER AT NEW SECTION IN CONSTRUCTOR
	IniSect m_sectMain; // public so can write only part of ini file
	IniSect m_sectPref; // public so can write only part of ini file
	IniSect m_sectCopy; // public so can write only part of ini file
	IniSect m_sectOptCopy; // public so can write only part of ini file
	IniSect m_sectOptLog; 

	////- DECLARE INI VARIABLES HERE, AND WRITE Add STATEMENTS IN Init
/* e.g:
	BOOL bCheck;
	LPTSTR sEdit;
	INT nEdit;
	UINT uEdit;
*/

//- SHAKER VARS

// m_sectPref
  // Default Save name
  BOOL bSrcName;
  BOOL bLabel;
  UINT uLabelPlace;
  LPTSTR sLabel;
  BOOL bDate;
  UINT uDatePlace;

  BOOL bTgtDirLast;
  LPTSTR sTgtDirLast;

//  BOOL bSrcDirLast;

// In v2.2 not really convert, but same var name to pick up v1 prefs
//  BOOL ubConvertWpl; // UINT for radio buttons, used as boolean
//  INT nConvertWpl; // In version 3.0 0 is still leave .wpl, 1 still .m3u; add 2 .m3u8
  INT nPlaylistFmt; // v3.22 replace nConvertWpl to force reset on upgrade
  INT nPlaylistFmtLast;   // v3.22 new
  BOOL bSongRelativePath; // v3.22 new
  BOOL bWmpNotify;
  INT nDefStars;

  BOOL bLog;
  BOOL bLogFlush;
  BOOL bElapsed;

  // m_sectMain:
//  LPTSTR sSrcDirLast;

//  UINT uOutName;
  INT nRepeatOpt;

  UINT uSepOption;
  UINT uSepDistSize;
  UINT uSepCount;

  INT nTruncSize;
  BOOL bTruncate;
  // Added in 2.1:
  BOOL bTruncNoReps;
  INT nUseMaxTruncSize;

  // Added in 3.0
  INT nListboxOrder;

  // No dialog button, only in ini file
  BOOL bIncludeAutoPlists;

  // m_sectPref Shuffle Tab vars for Jukebox
  // 3.0 Change repetitions vars to INT.
  //     Need negative nRepsSame for exclusion selection, others are in same array
  INT nReps1;
  INT nReps2;
  INT nReps3;
  INT nReps4;
  INT nReps5;
  INT nRepsSame;
  INT bLimitReps;
  INT nMaxReps;

  // Long term defaults to set in the Preferences dialog
  INT nReps1Default;
  INT nReps2Default;
  INT nReps3Default;
  INT nReps4Default;
  INT nReps5Default;
  INT nRepsSameDefault;

  UINT uRememberReps;
  INT nDaysNew;
  BOOL bDaysNewAsDate;
  //BOOL bConfirmDeleteLv;


  // m_sectCopy
  UINT uSrcJpg;
  UINT uTgtJpg;
  LPTSTR sTgtJpgOther;
  LPTSTR sSrcJpgOther;
  LPTSTR sArtLastSrc;

  // m_sectOptCopy
  UINT uArtSrcDir;
//  LPTSTR sArtSrcDirOth;
  UINT uArtTgtDir;
  LPTSTR sArtTgtDirOth;
  BOOL bArtLog;
  BOOL bArtLogDetail;
  BOOL bArtLogFlush;
  BOOL bArtSaveHide;
  // These in Match dlg, keep in m_sectOptCopy
  BOOL bArtHideNoImg;
  BOOL bArtHideNoSrc;
  BOOL bArtHideNoTgt;
  BOOL bArtHideRed;

	
	////- NO CHANGES NEEDED PAST HERE UNLESS SPECIAL APP-SPECIFIC

	BOOL SetAndSaveKey(LPTSTR & sVar, LPCTSTR sNewVal);
	BOOL SetAndSaveKey(INT & nVar, INT nNewVal);
	inline BOOL SetAndSaveKey(UINT & uVar, UINT uNewVal)
	{
		return SetAndSaveKey((INT &) uVar, (INT) uNewVal);
	}

	CSettings();
	virtual ~CSettings();

	BOOL Init(LPCTSTR sIniDirSlash, LPCTSTR sIniFileNameWithExt = NULL);
	BOOL SetStr(LPTSTR & sVar, LPCTSTR sValue);

  BOOL ReadIniSection(IniSect & sect);
	BOOL WriteIniSection(IniSect & sect);
	BOOL CSettings::WriteIniAll();

	BOOL SetError(LPCTSTR sErr1, LPCTSTR sErr2 = NULL);
	BOOL AddToError(LPCTSTR sErr);
	void GetError(LPTSTR sTarget = NULL, BOOL bClear = TRUE);
	BOOL ShowError(LPCTSTR sCapt, LPCTSTR sPre = NULL, LPCTSTR sPost = NULL);
	void ClearError();

protected:
	LPTSTR m_sErrDlgNotSet;
	HWND m_hDlg;
	IniSect * m_pSects[NUM_OF_SECTS];

	BOOL GetOwnIniPath(LPCTSTR sIniDirSlash, LPCTSTR sIniFileNameWithExt = NULL);
	TCHAR m_sIniPath[_MAX_PATH];
	TCHAR m_sIniDirSlash[_MAX_PATH];

	IniKey * AllocateNextKey(IniSect & sect, LPCTSTR sKeyName);

	BOOL Add(IniSect & sect, LPCTSTR sKeyName, LPTSTR & sVar, LPCTSTR sDef);
	BOOL Add(IniSect & sect, LPCTSTR sKeyName, INT & nVar, const INT nDef);
	// INT & nVar version will handle BOOL's; need cast for UINT's:
	inline BOOL Add(IniSect & sect, LPTSTR sKeyName, UINT & uVar, const UINT uDef)
	{
		return Add(sect, sKeyName, (INT &) uVar, (const INT) uDef);
	}

	void DeleteSection(IniSect & sect);

	BOOL ReadIniKey(IniKey * pKey, LPCTSTR sSectName);
//	BOOL ReadIniSection(IniSect & sect);
	BOOL WriteIniKey(IniKey * pKey, LPCTSTR sSectName);

	TCHAR m_sError[1024];
	LPCTSTR m_sErrKeyNotFound;

// BEGIN EXTRAS FOR PREFERENCES DIALOG

#if !defined(SETTINGS_LITE_)

public:

	void SetDlg(HWND hDlg);
	BOOL CopySection(IniSect & Target, IniSect & Source);
	BOOL CopyFrom(CSettings & Source);
	BOOL CopyAndSaveFrom(CSettings & Source);
	BOOL InitDlgCopy(HWND hDlg, CSettings & Source);

	BOOL DlgCheckToKey(BOOL & bVar, INT nID, BOOL bFlip = FALSE);
	BOOL DlgCheckFromKey(BOOL bVar, INT nID, BOOL bFlip = FALSE);

	BOOL DlgEditFromKey(LPTSTR sVar, INT nID);
	BOOL DlgEditFromKey(INT nVar, INT nID);
	BOOL DlgEditFromKey(UINT uVar, INT nID);

	BOOL DlgEditToKey(LPTSTR & sVar, INT nID,
											BOOL bEmptyOK = FALSE, INT nMax = 1023);
	BOOL DlgEditToKey(INT & nVar, INT nID,
											BOOL bEmptyOK = FALSE, INT nMax = 31);
	BOOL DlgEditToKey(UINT & uVar, INT nID,
														BOOL bEmptyOK = FALSE, INT nMax = 31);

	// If pass nVar by value, compiler rejects fn overload when called
	BOOL DlgRBsFromKey(INT & nVar, INT nIdFirst, INT nIdLast,
										 INT nIdxFirst = 0, INT nValIncrement = 1);
	inline BOOL DlgRBsFromKey(UINT & uVar, INT nIdFirst, INT nIdLast,
														UINT uIdxFirst = 0, INT nValIncrement = 1)
	{
		return DlgRBsFromKey((INT &) uVar, nIdFirst, nIdLast,
												 (INT) uIdxFirst, nValIncrement);
	}

	BOOL DlgRBsToKey(INT & nVar, INT nIdFirst, INT nIdLast,
												 INT nIdxFirst = 0, INT nValIncrement = 1);
	inline BOOL DlgRBsToKey(UINT & uVar, INT nIdFirst, INT nIdLast,
															UINT uIdxFirst = 0, INT nValIncrement = 1)
	{
		return DlgRBsToKey((INT &) uVar, nIdFirst, nIdLast,
																(INT) uIdxFirst, nValIncrement);
	}


	BOOL DlgListToKey(LPTSTR & sVar, INT nID, BOOL bCombo);
	BOOL DlgListToKey(INT & nVar, INT nMin, INT nID, BOOL bCombo);
	inline BOOL DlgListToKey(UINT & uVar, UINT uMin, INT nID, BOOL bCombo)
	{
		return DlgListToKey((INT &) uVar, (INT) uMin, nID, bCombo);
	}

	BOOL DlgListFromKey(LPTSTR sVar, INT nID, BOOL bCombo);
	BOOL DlgListFromKey(INT nVar, INT nMin, INT nID, BOOL bCombo);
	inline BOOL DlgListFromKey(UINT uVar, UINT uMin, INT nID, BOOL bCombo)
	{
		return DlgListFromKey((INT) uVar, (INT) uMin, nID, bCombo);
	}

protected:

	BOOL fnEditToStr(LPTSTR sRead, HWND hEdit, BOOL bEmptyOK, INT nMax);

#endif  // !defined SETTINGS_LITE_

};

#endif // !defined(AFX_SETTINGS_H__22CE3EF4_55C0_11D3_BD00_444553540000__INCLUDED_)

