unit fSelectDuplicates;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Buttons, StdCtrls,
  ExtCtrls, KASComboBox, KASButtonPanel, uFileView;

type

  { TfrmSelectDuplicates }

  TfrmSelectDuplicates = class(TForm)
    btnApply: TBitBtn;
    btnCancel: TBitBtn;
    btnOK: TBitBtn;
    btnIncludeMask: TSpeedButton;
    btnExcludeMask: TSpeedButton;
    cmbFirstMethod: TComboBoxAutoWidth;
    cmbIncludeMask: TComboBox;
    cmbExcludeMask: TComboBox;
    chkLeaveUnselected: TCheckBox;
    cmbSecondMethod: TComboBoxAutoWidth;
    lblIncludeMask: TLabel;
    lblExcludeMask: TLabel;
    lblFirstMethod: TLabel;
    lblSecondMethod: TLabel;
    pnlMethods: TPanel;
    pnlButtons: TKASButtonPanel;
    procedure btnApplyClick(Sender: TObject);
    procedure btnIncludeMaskClick(Sender: TObject);
    procedure chkLeaveUnselectedChange(Sender: TObject);
    procedure cmbFirstMethodChange(Sender: TObject);
  private
    FFileView: TFileView;
  end;

procedure ShowSelectDuplicates(TheOwner: TCustomForm; AFileView: TFileView);

implementation

{$R *.lfm}

uses
  uFile, uFileSorting, uFileFunctions, uDisplayFile, uFileProperty, uTypes,
  uGlobs, fMaskInputDlg, uLng, uSearchTemplate, DCStrUtils;

procedure ShowSelectDuplicates(TheOwner: TCustomForm; AFileView: TFileView);
begin
  with TfrmSelectDuplicates.Create(TheOwner) do
  begin
    FFileView:= AFileView;
    cmbFirstMethod.ItemIndex:= 0;
    cmbSecondMethod.ItemIndex:= 2;
    cmbIncludeMask.Items.Assign(glsMaskHistory);
    cmbExcludeMask.Items.Assign(glsMaskHistory);

    // Localize methods
    ParseLineToList(rsSelectDuplicateMethod, cmbFirstMethod.Items);
    ParseLineToList(rsSelectDuplicateMethod, cmbSecondMethod.Items);
    cmbSecondMethod.Items.Delete(cmbSecondMethod.Items.Count - 1);
    cmbSecondMethod.Items.Delete(cmbSecondMethod.Items.Count - 1);

    if ShowModal = mrOK then
    begin
      btnApplyClick(btnApply);
    end;
    Free;
  end;
end;

{ TfrmSelectDuplicates }

procedure TfrmSelectDuplicates.cmbFirstMethodChange(Sender: TObject);
begin
  cmbSecondMethod.Enabled:= cmbFirstMethod.ItemIndex < 4;
end;

procedure TfrmSelectDuplicates.btnApplyClick(Sender: TObject);
var
  ARange: TRange;
  AFinish: Integer;
  Index, J: Integer;
  ASelected: Integer;
  AFiles: TDisplayFiles;
  AGroup, AValue: Variant;
  NewSorting: TFileSortings = nil;
begin
  FFileView.MarkGroup(cmbIncludeMask.Text, True);
  if Length(cmbExcludeMask.Text) > 0 then begin
    FFileView.MarkGroup(cmbExcludeMask.Text, False);
  end;

  if not chkLeaveUnselected.Checked then Exit;

  AFiles:= FFileView.DisplayFiles;

  // First sort by group
  SetLength(NewSorting, 1);
  SetLength(NewSorting[0].SortFunctions, 1);
  NewSorting[0].SortFunctions[0] := fsfVariant;
  NewSorting[0].SortDirection := sdAscending;

  case cmbFirstMethod.ItemIndex of
    0, 1: // Newest/Oldest
      begin
        SetLength(NewSorting, 2);
        SetLength(NewSorting[1].SortFunctions, 1);
        NewSorting[1].SortFunctions[0] := fsfModificationTime;
        if (cmbFirstMethod.ItemIndex = 1) then
          // First item will be Oldest
          NewSorting[1].SortDirection := sdAscending
        else begin
          // First item will be Newest
          NewSorting[1].SortDirection := sdDescending;
        end;
      end;
    2, 3: // Largest/Smallest
      begin
        SetLength(NewSorting, 2);
        SetLength(NewSorting[1].SortFunctions, 1);
        NewSorting[1].SortFunctions[0] := fsfSize;
        if (cmbFirstMethod.ItemIndex = 3) then
          // First item will be Smallest
          NewSorting[1].SortDirection := sdAscending
        else begin
          // First item will be Largest
          NewSorting[1].SortDirection := sdDescending;
        end;
      end;
  end;

  if cmbSecondMethod.Enabled then
  begin
    case cmbSecondMethod.ItemIndex of
      0, 1:
        begin
          SetLength(NewSorting, 3);
          SetLength(NewSorting[2].SortFunctions, 1);
          NewSorting[2].SortFunctions[0] := fsfModificationTime;
          if (cmbSecondMethod.ItemIndex = 1) then
            NewSorting[2].SortDirection := sdAscending
          else begin
            NewSorting[2].SortDirection := sdDescending;
          end;
        end;
      2, 3:
        begin
          SetLength(NewSorting, 3);
          SetLength(NewSorting[2].SortFunctions, 1);
          NewSorting[2].SortFunctions[0] := fsfSize;
          if (cmbSecondMethod.ItemIndex = 3) then
            NewSorting[2].SortDirection := sdAscending
          else begin
            NewSorting[2].SortDirection := sdDescending;
          end;
        end;
    end;
  end;

  FFileView.Sorting:= NewSorting;

  // Skip '..' item
  if AFiles[0].FSFile.IsNameValid then
    ARange.First:= 0
  else begin
    ARange.First:= 1;
  end;

  AFinish:= AFiles.Count - 1;
  AGroup:= TFileVariantProperty(AFiles[ARange.First].FSFile.Properties[fpVariant]).Value;
  for Index:= ARange.First + 1 to AFinish do
  begin
    AValue:= TFileVariantProperty(AFiles[Index].FSFile.Properties[fpVariant]).Value;
    if (AValue <> AGroup) or (Index = AFinish) then
    begin
      if (AValue <> AGroup) then
      begin
        ASelected:= 0;
        ARange.Last:= Index - 1;
      end
      else begin
        ASelected:= -1;
        ARange.Last:= Index;
      end;
      for J:= ARange.First to ARange.Last do
      begin
        if AFiles[J].Selected then Inc(ASelected);
      end;
      // Selected all files in the group
      if ASelected = (Index - ARange.First) then
      begin
        if cmbFirstMethod.ItemIndex = 5 then
          AFiles[ARange.Last].Selected:= False
        else begin
          AFiles[ARange.First].Selected:= False;
        end;
      end;
      AGroup:= AValue;
      ARange.First:= Index;
    end;
  end;
end;

procedure TfrmSelectDuplicates.btnIncludeMaskClick(Sender: TObject);
var
  sMask: String;
  bTemplate: Boolean;
  AComboBox: TComboBox;
begin
  if Sender = btnIncludeMask then
    AComboBox:= cmbIncludeMask
  else begin
    AComboBox:= cmbExcludeMask;
  end;
  sMask:= AComboBox.Text;
  if ShowMaskInputDlg(rsMarkPlus, rsMaskInput, glsMaskHistory, sMask) then
  begin
    bTemplate:= IsMaskSearchTemplate(sMask);
    AComboBox.Enabled:= not bTemplate;
    AComboBox.Text:= sMask;
  end;
end;

procedure TfrmSelectDuplicates.chkLeaveUnselectedChange(Sender: TObject);
begin
  cmbFirstMethod.Enabled:= chkLeaveUnselected.Checked;
  cmbSecondMethod.Enabled:= chkLeaveUnselected.Checked;
end;

end.

