unit uAppSettings;

interface

uses
  uJSON;

 const
   COMPANY_NAME = 'MyCompany';

type
  TAppSettings = class
  protected
    fFilename : string;
    fSaveOnFree: boolean;
    fSettings : TJSONObject;
    function createOrGetSection(aSection : string) : TJSONObject;
  public
    constructor Create(aFilename : string);
    destructor Destroy; override;
    procedure Save;
    function getInteger(aSection, aKey : string; aDefault : integer) : integer;
    function getString(aSection, aKey : string; aDefault : string) : string;
    function getFloat(aSection, aKey : string; aDefault : double ) : double;
    function getBool(aSection, aKey : string; aDefault : boolean) : boolean;
    procedure setValue(aSection, aKey : string; aValue : integer); overload;
    procedure setValue(aSection, aKey : string; aValue : string); overload;
    procedure setValue(aSection, aKey : string; aValue : double); overload;
    procedure setValue(aSection, aKey : string; aValue : boolean); overload;
    property SaveOnFree : boolean read fSaveOnFree write fSaveOnFree;
    procedure OpenPathInExplorer;
  end;

var
  AppSettings,
  UserSettings : TAppSettings;

implementation

uses
  ShellAPI, ShlObj, SysUtils, Windows, IOUtils;

constructor TAppSettings.Create(aFilename: string);
var
  s : string;
begin
  fFilename := aFilename;
  fSaveOnFree := true;
  if TFile.Exists(aFilename) then
  begin
    s := TFile.ReadAllText(aFilename);
    fSettings := TJSONObject.create(s);
  end
  else
    fSettings := TJSONObject.create;
end;

destructor TAppSettings.Destroy;
begin
  if fSaveOnFree then Save;
  fSettings.Free;
  inherited;
end;

function TAppSettings.createOrGetSection(aSection: string): TJSONObject;
begin
  result := fSettings.optJSONObject(aSection);
  if result = nil then
  begin
    result := TJSONObject.create;
    fSettings.put(aSection,result);
  end;
end;

procedure TAppSettings.Save;
begin
  TFile.WriteAllText(fFilename,fSettings.toString(3));
end;

function TAppSettings.getBool(aSection, aKey: string;
  aDefault: boolean): boolean;
var
  section : TJSONObject;
begin
  result := aDefault;
  section := fSettings.optJSONObject(aSection);
  if section <> nil then result := section.optBoolean(aKey);
end;

function TAppSettings.getFloat(aSection, aKey: string;
  aDefault: double): double;
var
  section : TJSONObject;
begin
  result := aDefault;
  section := fSettings.optJSONObject(aSection);
  if section <> nil then result := section.optDouble(aKey);
end;

function TAppSettings.getInteger(aSection, aKey: string;
  aDefault: integer): integer;
var
  section : TJSONObject;
begin
  result := aDefault;
  section := fSettings.optJSONObject(aSection);
  if section <> nil then result := section.optInt(aKey);
end;

function TAppSettings.getString(aSection, aKey, aDefault: string): string;
var
  section : TJSONObject;
begin
  result := aDefault;
  section := fSettings.optJSONObject(aSection);
  if section <> nil then result := section.optString(aKey);
end;

procedure TAppSettings.setValue(aSection, aKey: string; aValue: integer);
var
  section : TJSONObject;
begin
  section := createOrGetSection(aSection);
  section.put(aKey, aValue);
end;

procedure TAppSettings.setValue(aSection, aKey, aValue: string);
var
  section : TJSONObject;
begin
  section := createOrGetSection(aSection);
  section.put(aKey, aValue);
end;

procedure TAppSettings.setValue(aSection, aKey: string; aValue: boolean);
var
  section : TJSONObject;
begin
  section := createOrGetSection(aSection);
  section.put(aKey, aValue);
end;

procedure TAppSettings.setValue(aSection, aKey: string; aValue: double);
var
  section : TJSONObject;
begin
  section := createOrGetSection(aSection);
  section.put(aKey, aValue);
end;

procedure TAppSettings.OpenPathInExplorer;
begin
  ShellExecute(0,PChar('open'),PChar(ExtractFilePath(fFilename)),nil,nil,SW_SHOWNORMAL);
end;

function GetSpecialFolder(Folder: Integer): String;
var
  Path: array[0..MAX_PATH] of char;
begin
  If SHGetSpecialFolderPath(0, @Path, Folder, false)
    then Result:=Path
    else Result:='';
end;

function GetApplicationName : string;
begin
  result := ExtractFilename(ParamStr(0));
  delete(result,length(result)-3,4);
end;

initialization
begin
  ForceDirectories(GetSpecialFolder(CSIDL_COMMON_APPDATA)+'\'+COMPANY_NAME+'\'+GetApplicationName);
  ForceDirectories(GetSpecialFolder(CSIDL_APPDATA)+'\'+COMPANY_NAME+'\'+GetApplicationName);
  AppSettings := TAppSettings.Create(GetSpecialFolder(CSIDL_COMMON_APPDATA)+'\'+COMPANY_NAME+'\'+GetApplicationName+'\settings.json');
  UserSettings := TAppSettings.Create(GetSpecialFolder(CSIDL_APPDATA)+'\'+COMPANY_NAME+'\'+GetApplicationName+'\settings.json');
end;

finalization
begin
  AppSettings.Free;
  UserSettings.Free;
end;

end.
