{
  Script: Analyse Exif Data
  Purpose: Create Exif statistics for the selected thumbnails

  Version Number: 1.2
  Version Author: H. van Zwietering
  Version Date: 6 dec 2017
}
const
  cTags = 'ISOSpeedRatings,FNumber,FocalLength,LensInformation';

  procedure DumpContent (AContainer: TidElement; AWithSave: Boolean);
  var
    i, j: Integer;
    AElemContainer, AElem: TidElement;
    AOutput: TTntStringList;
    ASaveDialog: TSaveDialog;
  begin
    AOutput := TTntStringList.Create;
    try
      for i := 0 to AContainer.Elements.Count - 1 do
      begin
        AElemContainer := AContainer.Elements.Items[i];

        for j := 0 to AElemContainer.Elements.Count - 1 do
        begin
          AElem := AElemContainer.Elements.Items[j];

          // CSV formatted
          AOutput.Add ('"' + AElemContainer.Name + '","' + AElem.Name + '",' + IntToStr (AElem.Value));
        end;
      end;

      if AWithSave then
      begin
        ASaveDialog := TSaveDialog.Create(nil);
        try
          if ASaveDialog.Execute then
          begin
            AOutput.SaveToFile (UTF8Decode(ASaveDialog.FileName));
            Say (Format('Result is saved as %s', [UTF8Decode(ASaveDialog.FileName)]));
          end;
        finally
          ASaveDialog.Free;
        end;
      end;
    finally
      AOutput.Free;
    end;
  end;

  function PrepareContainer (AContainer: TidElement): Boolean;
  var
    ATif: TTif;
    t, i: Integer;

    ATags: TStringList;

    AElemContainer: TidElement;
    AElem: TidElement;
    AVal: Variant;

    AXmp: TXMP;
    AProgress: TxomProgress;
  begin
    result := False;

    AProgress := TxomProgress.Create(nil);
    ATags := TStringList.Create;

      ATags.CommaText := cTags;

      // create the placeholders
      for t := 0 to ATags.Count - 1 do
      begin
        ATags.Strings[t] := Trim(ATags.Strings[t]);

        AElemContainer := AContainer.Elements.Add;
        AElemContainer.Name := ATags.Strings[t];
        ATags.Objects[t] := AElemContainer;
      end;

      AProgress.Caption := 'Analyse Exif Data';
      AProgress.Cancel := False;
      AProgress.Max := Selected.Count;
      AProgress.Pos := 0;
      AProgress.Show;

      // process every item
      for i := 0 to Selected.Count - 1 do
      begin
        AProgress.ProgressText := Selected.Items[i].FileNameOnly;
        AProgress.Pos := i + 1;

        ATif := TTif.Create(nil);        // the embedded meta processor
        try
          ATif.FileName := Selected.Items[i].ExifFileName;
          if not Selected.Items[i].MediumLoaded then
          begin
            AXmp := TXMP.Create(False);
            try
              Catalog.LoadXMPForImage (Selected.Items[i], AXmp, True);
              AXmp.PushToTif (ATif);
            finally
              AXmp.Free;
            end;
          end
          else
            ATif.Load (True, False);

          if ATif.HasExif then
          begin
            for t := 0 to ATags.Count - 1 do
            begin
              AElemContainer := ATags.Objects[t];

              AVal := ATif.TagValueByName (ATags.Strings[t], [itBase, itExif, itIPTC, itInterExif, itGps, itMakerNotes], False);
              AElem := AElemContainer.Elements.FindNamed(AVal);
              if AElem = nil then
              begin
                AElem := AElemContainer.Elements.Add;
                AElem.Name := AVal;
                AElem.Value := 0;
              end;
              AElem.Value := AElem.Value + 1;
            end;
          end;
        finally
          ATif.Free;
        end;

        if AProgress.Cancel then
          break;
      end;

      result := not Progress.Cancel;

    ATags.Free;
    AProgress.Free;
  end;


var
  AContainer: TidElement;
begin
  if Selected.Count = 0 then
  begin                 
    Say ('No thumbnails selected');
    exit;
  end;

  AContainer := TidElement.Create(nil);

    if not PrepareContainer(AContainer) then
      Say ('Cancelled. You can still save the analysed data up to the moment you cancelled it.');

    DumpContent (AContainer, True);

  AContainer.Free;
end;
