{ Description: This script will migrate the existing contacts/people array as written by iView to
               People labels

  Original Author: Dirk Schiphorst
  Version history:
  1.0 - 23-03-2010 
      - Initial release. Based on iView Contacts to Keywords script by Hert
  1.1 - 31-01-2016
      - Updated by Andrew Certain for Photo Supreme v3.2
  1.21 - 21 dec 2018
      - Updated by Hert; removed message "Label not assigned"
  1.3 - 04 aug 2020 by Hert van Zwietering
      - Added dedicated progress and file only progress text
}

const
  cUpdateTags = 0;  // set to 1 to have metadata updated and EM/iView tag removed

function DetermineParentContainer: String;
var
  ACategory: TCatalogPropCategory;
  AProp: TCatalogItemProp;

begin
  result := PeopleGUID;  // By default, use the built-in People category

  {
  // alternative 1; find a category by name that should contain the places structure
  ACategory := TCatalogPropCategory.Create (nil);
  if PublicCatalog.EnumCategoryNamed ('People', ACategory) then  
    result := ACategory.GUID;
  ACategory.Free;
  }

  // alternative 2; find a catalog label by name that should contain the places structure
  {
  AProp := TCatalogItemProp.Create (nil);
  if PublicCatalog.FindPropByName ('My People', AProp, '', True) then 
    result := AProp.GUID;
  AProp.Free;
  }
end;

procedure Process_iView (ACatItem: TCatalogItem; var ATif: TTif; var AXmp: TXMP);
var
  i, j: Integer;
  ATag: TTifTag;
  AIVPeople: TMacroParam;
  AEntry: WideString;
  ASl: TStringList;
  AList: TStringList;
  AParentGUID: String;

begin
  AParentGUID := DetermineParentContainer;

  ASl := TStringList.Create;
  AList := TStringList.Create;

  for i := ATif.IPTCIFD.Tags.Count - 1 downto 0 do
  begin
    ATag := ATif.IPTCIFD.Tags.Items[i];

    if ATag.TagNumber = 118 then        // contacts
    begin
      if Trim(ATag.TagValue) = '' then        // skip empty contacts
        continue;

      ASl.CommaText := ATag.TagValue;        // the tag is comma separated by IDI
      for j := 0 to ASl.Count - 1 do
      begin
        if Trim(ASl.Strings[j]) = '' then
          continue;

        if AList.IndexOf (ASl.Strings[j]) = -1 then        // prevent dups
          AList.Add (ASl.Strings[j]);
      end;

      ATag.Free;
    end;
  end;

  // the list now contains all people from IPTC, now add the XMP people from the EM - iView schema (if available)
  AIVPeople := AXmp.FindDesignProperty ('http://ns.microsoft.com/expressionmedia/1.0/', 'expressionmedia:People');
  if AIVPeople = nil then
    AIVPeople := AXmp.FindDesignProperty ('http://ns.iview-multimedia.com/mediapro/1.0/', 'mediapro:People');
  if AIVPeople <> nil then
  begin
    // found, now process all items in the iView People array (it's an "XMP Bag" datatype)
    for i := 0 to AIVPeople.ArrayContent.Count - 1 do
    begin
      if Trim(Nvl(AIVPeople.ArrayContent.Items[i].Content, '')) = '' then
        continue;

      if AList.IndexOf (AIVPeople.ArrayContent.Items[i].Content) = -1 then        // prevent dups
        AList.Add (AIVPeople.ArrayContent.Items[i].Content);
    end;

    AIVPeople.Free;
  end;

  AProp := TCatalogItemProp.Create(nil);
  for i := 0 to AList.Count - 1 do
  begin
    // AProp.Clear;
    AEntry := AList.Strings[i];
    if not PublicCatalog.FindPropByName(AEntry, AProp, AParentGUID, true) then
    begin
      // create prop
      AProp.GUID         := NewGUID;                    // generate a new GUID
      AProp.PropName     := AEntry;
      PublicCatalog.StorePropToDatabase(AProp, AParentGUID, False);
    end;

    // add prop to image
    PublicCatalog.AddPropToItem(ACatItem, AProp, false, false);
  end;

  AProp.Free;
  ASl.Free;
  AList.Free;
end;

var
  ATif: TTif;
  AXmp: TXMP;
  AItem: TImageItem;
  i: Integer;
  ACatItem: TCatalogItem;
  AProgress: TxomProgress;
begin
  if Selected.Count = 0 then
  begin
    Say ('No images selected');
    exit;
  end;

  if not Ask ('This script will migrate Contacts/People entries as written with EM/iView to Catalog Labels. The original Contacts found (if any) will be permanently moved.' + CrLf2 + 'Are you sure you want to continue?') then
    exit;

  AProgress := TxomProgress.Create(nil);
  try
    AProgress.Cancel := False;
    AProgress.Caption := 'Migrate EM-iView Contacts to People';
    AProgress.ProgressBar := True;
    AProgress.Max := Selected.Count;
    AProgress.Show;

    AXmp := TXmp.Create (True);
    ATif := TTif.Create (nil);
    ACatItem := TCatalogItem.Create (nil);
    try
      //ATif.UseCache := False;
      for i := 0 to Selected.Count - 1 do
      begin
        AProgress.ProgressText := Selected.Items[i].FileNameOnly;
        AProgress.Pos := i + 1;
        if AProgress.Cancel then
          break;

        ATif.Reset;
        AXmp.Reset;

        ATif.FileName := Selected.Items[i].ExifFileName;
        ATif.Load (True, False);

        // now update the XMP
        if not PublicCatalog.FindImageCombined (Selected.Items[i], ACatItem, False, phtNone) then
        begin
          if not PublicCatalog.AddFile (Selected.Items[i], AcatItem, False) then
            Continue;
        end;

        PublicCatalog.LoadXMPForItem (ACatItem, AXmp, Options.CachedXMP);
        AXmp.InitializeFromTif (ATif, True, True, True, False, txusAll);

        Process_iView (ACatItem, ATif, AXmp);

        if cUpdateTags <> 0 then
          ATif.UpdateTags;
        PublicCatalog.SaveXMPForItem (ACatItem, AXmp, Options.CachedXMP);
      end;
    finally
      AXmp.Free;
      ACatItem.Free;
    end;

    AProgress.Hide;

    if AProgress.Cancel then
      Say ('Cancelled');
  finally
    AProgress.Free;
  end;

end;

