const
  cStackBurstDelta = 2.0;   // seconds

var
  AStacks: Integer;

  procedure StoreBurstAsStack(ABurst: TStrings);
  var
    AItems: TCatalogItems;
    AItem: TCatalogItem;
    AImage: TImageItem;
    i: Integer;
    AGroupID: String;
  begin
    if ABurst.Count < 2 then  // a burst with less than 2 images is not a stack
      exit;

    AItems := TCatalogItems.Create(TCatalogItem, '');
    for i := 0 to ABurst.Count - 1 do
    begin
      ACatItem := AItems.Add as TCatalogItem;
      if not PublicCatalog.FindItemCombinedByGUID(ABurst.Strings[i], ACatItem) then
        ACatItem.Free;
    end;

    if AItems.Count < 2 then  // a burst with less than 2 images is not a stack
      exit;

    // store to temp list
    PublicCatalog.StoreItemsToTempList(AItems, True);
    try
      AGroupID := NewGUID;
      PublicCatalog.StackItemsInTempList(AItems, AGroupID, AItems.Items[0]);

      AStacks := AStacks + 1;
    finally
      PublicCatalog.RemoveItemsFromTempList(AItems);
    end;

    AItems.Free;
  end;

  procedure CreateStacks(AIndex: TStrings);
  var
    i: Integer;
    APrevDT, ADt: TDateTime;
    AImage: TImageItem;
    ABurst: TStringList;
  begin
    // find a burst
    // index is sorted by date

    ABurst := nil;

    APrevDT := -1;
    for i := 0 to AIndex.Count - 1 do
    begin
      AImage := AIndex.Objects[i];
      ADt := AImage.PhotoDate;

      if Abs(SecondsBetween(APrevDT, ADt)) <= cStackBurstDelta then
      begin
        // same burst
        ABurst.AddObject(AImage.GUID, AImage);
      end
      else
      begin
        // new burst
        if Assigned(ABurst) then
        begin
          StoreBurstAsStack(ABurst);
          FreeAndNil(ABurst);
        end;
        ABurst := TStringList.Create;
        ABurst.AddObject(AImage.GUID, AImage);
      end;

      APrevDT := ADt;
    end;

    if Assigned(ABurst) then
      StoreBurstAsStack(ABurst);

    if Assigned(ABurst) then
      FreeAndNil(ABurst);
  end;

var
  i: Integer;
  AIndex: TStringList;
  AImage: TImageItem;
  ADtS: String;
begin
  if Selected.Count = 1 then
  begin
    Say('Select at least 2 thumbnails to detect the Stack for');
    exit;
  end;

  AStacks := 0;
  AIndex := TStringList.Create;
  for i := 0 to Selected.Count - 1 do
  begin
    AImage := Selected.Items[i];

    ADtS := FormattedDateTime('yyyymmddhhnnss', AImage.PhotoDate);
    AIndex.AddObject(ADts, AImage);
  end;
  AIndex.Sort;

  CreateStacks(AIndex);
  AIndex.Free;

  Say('Created ' + IntToStr(AStacks) + ' stack(s)');

end;
