//
// Example script for 2BrightSparks SyncBackPro that filters out
// files and folders. This is different from using filters in 
// SyncBack itself as these are applied to the scan results and 
// file and folder selectios and filters have been applied.
//
// This can be useful if you want to only include certain
// sub-folders, for example. Because these custom filters are 
// applied to the final list of filenames (after any file and 
// folder selections and filters) it does not act like normal
// filters which are applied top-down.
//
// For example, you have the following folders:
//
// \abc\
// \abc\xyz\
// \abc\123\
// \def\
// \def\456\xyz\
//
// In this exmaple, you only want to include files and sub-folders
// within folders named 'xyz'. With normal SyncBack filters you
// would need to have the filter *\ and *\xyz\*. That would include
// all folders (but not their files or sub-folders) because of the
// need to have *\ (because filters are applied top-down).
//
// With the example you would just have the filter *\xyz\* and it
// would not include any other folders.
//
// This example only allows for 5 filters, but it is simple
// enough to modify this script to add more if needed.
//
// SBLang=Pascal
//
// https://www.2BrightSparks.com/
//
// IMPORTANT: Requires SyncBackPro V11.2.26.0 or newer
//

// These globals are set in the call to RunBeforeScanning
var gFilterInc;
var gNoFilters;
var gFilter1;
var gFilter2;
var gFilter3;
var gFilter4;
var gFilter5;

function Description(var ScriptType);
begin
  Result:='Custom filtering';
  ScriptType:=SCRIPTTYPE_RUN + SCRIPTTYPE_CONFIG;
End;

//==================================================================
// Configuration part of the script
//==================================================================

// Not for group profiles, and only display setup page if the profile
// is using the script.
function ConfigWantSetupNode(IsGroup);
begin
  Result:=not IsGroup and SBProfile.UsesScript;
end;

// Reset to factory defaults
procedure ConfigFactoryDefaults;
begin
  SBVariables.DeleteProperty('FiltersInc');
  SBVariables.DeleteProperty('Filters1');
  SBVariables.DeleteProperty('Filters2');
  SBVariables.DeleteProperty('Filters3');
  SBVariables.DeleteProperty('Filters4');
  SBVariables.DeleteProperty('Filters5');
end;

// Always allow the setup page to close
function ConfigCanClose;
begin
  Result:=TRUE;
end;

// Can revert to factory settings
function ConfigCanRevert;
begin
  Result:=TRUE;
end;

// Setup node caption
function ConfigNodeCaption;
begin
  Result:='Custom Filtering';
end;

// Create setup window display
procedure ConfigSetupDisplay;
begin
  SBProfile.AddLabel('Enter your filters below, e.g. \test\*.txt', 1);
  SBProfile.AddLabel('Wildcards (* and ?) and sets are supported (e.g. [a-z], [!123])', 1);
  SBProfile.AddLabel('It is not case sensitive', 1);

  SBProfile.AddCheckbox('If enabled, only files and folders matching a filter are included else they are excluded', 2);

  SBProfile.AddEdit('Filter 1', 256, FALSE, FALSE, 3);
  SBProfile.AddEdit('Filter 2', 256, FALSE, FALSE, 4);
  SBProfile.AddEdit('Filter 3', 256, FALSE, FALSE, 5);
  SBProfile.AddEdit('Filter 4', 256, FALSE, FALSE, 6);
  SBProfile.AddEdit('Filter 5', 256, FALSE, FALSE, 7);
end;

// Load settings. Return error message on failure.
function ConfigLoadSettings;
begin
  Result:='';

  if (SBVariables.GetProperty('FiltersInc', '', FALSE) = 'N') then
    SBProfile.SetCheckbox(FALSE, 2)
  else
    SBProfile.SetCheckbox(TRUE, 2);

  SBProfile.SetEdit(SBVariables.GetProperty('Filters1', '', FALSE), 3);
  SBProfile.SetEdit(SBVariables.GetProperty('Filters2', '', FALSE), 4);
  SBProfile.SetEdit(SBVariables.GetProperty('Filters3', '', FALSE), 5);
  SBProfile.SetEdit(SBVariables.GetProperty('Filters4', '', FALSE), 6);
  SBProfile.SetEdit(SBVariables.GetProperty('Filters5', '', FALSE), 7);
end;

// Save settings. Return error message on failure.
function ConfigSaveSettings(Silent);
begin
  Result:='';

  if SBProfile.GetCheckbox(2) then
    SBVariables.SetProperty('FiltersInc', 'Y')
  else
    SBVariables.SetProperty('FiltersInc', 'N');

  SBVariables.SetProperty('Filters1', SBProfile.GetEdit(3));
  SBVariables.SetProperty('Filters2', SBProfile.GetEdit(4));
  SBVariables.SetProperty('Filters3', SBProfile.GetEdit(5));
  SBVariables.SetProperty('Filters4', SBProfile.GetEdit(6));
  SBVariables.SetProperty('Filters5', SBProfile.GetEdit(7));
end;

// The settings have changed
procedure ConfigUpdateConditionals;
begin
end;

//==================================================================
// Running part of the script
//==================================================================

// This function is called just before scanning of the files and folders is about to start.
procedure RunBeforeScanning;
begin
  if (SBVariables.GetProperty('FiltersInc', '', FALSE) = 'N') then
    gFilterInc:=FALSE
  else
    gFilterInc:=TRUE;

  gFilter1:=Trim(SBVariables.GetProperty('Filters1', '', FALSE));
  gFilter2:=Trim(SBVariables.GetProperty('Filters2', '', FALSE));
  gFilter3:=Trim(SBVariables.GetProperty('Filters3', '', FALSE));
  gFilter4:=Trim(SBVariables.GetProperty('Filters4', '', FALSE));
  gFilter5:=Trim(SBVariables.GetProperty('Filters5', '', FALSE));
  
  gNoFilters:=(gFilter1 = '') and (gFilter2 = '') and (gFilter3 = '') and (gFilter4 = '') and (gFilter5 = '');
end;

procedure RunBeforeFolderCompare(Filename; var Skip);
begin
  // If it is already being skipped, then do not change that
  // If there are no filters, then do nothing
  if Skip or gNoFilters then Exit;
  
  if (gFilter1 <> '') then begin
    if MatchesMask(Filename, gFilter1) then begin
      if not gFilterInc then Skip:=TRUE;
      Exit;
    end;
  end;

  if (gFilter2 <> '') then begin
    if MatchesMask(Filename, gFilter2) then begin
      if not gFilterInc then Skip:=TRUE;
      Exit;
    end;
  end;

  if (gFilter3 <> '') then begin
    if MatchesMask(Filename, gFilter3) then begin
      if not gFilterInc then Skip:=TRUE;
      Exit;
    end;
  end;

  if (gFilter4 <> '') then begin
    if MatchesMask(Filename, gFilter4) then begin
      if not gFilterInc then Skip:=TRUE;
      Exit;
    end;
  end;

  if (gFilter5 <> '') then begin
    if MatchesMask(Filename, gFilter5) then begin
      if not gFilterInc then Skip:=TRUE;
      Exit;
    end;
  end;

  // If we get here then it has not matched a filter, so skip it
  if gFilterInc then Skip:=TRUE;
end;

procedure RunBeforeFileCompare(Filename; var Skip);
begin
  RunBeforeFolderCompare(Filename, Skip);
end;
