(************************************************************************
 *                                                                      *
 *   Ant Movie Catalog 4.x                                              *
 *   (C) 2000-2011 Antoine Potten, Mickaël Vanneufville                 *
 *   http://www.antp.be/software                                        *
 *                                                                      *
 ************************************************************************
 *                                                                      *
 *   This program is free software; you can redistribute it and/or      *
 *   modify it under the terms of the GNU General Public License        *
 *   as published by the Free Software Foundation; either version 2     *
 *   of the License, or (at your option) any later version.             *
 *                                                                      *
 *   This program is distributed in the hope that it will be useful,    *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of     *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *
 *   GNU General Public License for more details.                       *
 *                                                                      *
 ************************************************************************)

unit getscript_results;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, base, StdCtrls, ExtCtrls,

  ComCtrls, AntStringList, AntCorelButton, AntAutoHintLabel,

  movieclass, FileManager, fields;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

type
  TScriptResult = (srSave, srSaveAll, srSkip, srAbort);

  TScriptResultsWin = class(TBaseDlg)
    Messages: TAntStringList;
    lstValues: TListView;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btn3Click(Sender: TObject);
    procedure lstValuesDblClick(Sender: TObject);
    procedure lstValuesCustomDrawItem(Sender: TCustomListView;
      Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
    procedure lstValuesMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    FMovieOrig: TMovie;
    FMovieCopy: TMovie;
    FAllowedFields: TMovieFields;
    FAllowedCustomFields: TMovieFields;
    FAllowPicture: Boolean;
    FModifiedFields: TMovieFields;
    FModifiedCustomFields: TMovieFields;
    FModifiedPicture: Boolean;
    FSelectedFields: TMovieFields;
    FSelectedCustomFields: TMovieFields;
    FSelectedPicture: Boolean;
    FKeepSelectedFields: Boolean;
    FPictureURL: string;
    FCurrentCatalog: TFileManager;
    FCustomFieldsProperties: TCustomFieldsProperties;
  protected
    procedure LoadOptions; override;
    procedure SaveOptions; override;
  public
    procedure GenerateFields(CustomFieldsProperties: TCustomFieldsProperties); //Call it after create!
    procedure Init(const AllowedFields: TMovieFields; const AllowPicture: Boolean;
      const CurrentCatalog: TFileManager); //AllowedCustomFields set in CustomFieldsProperties!
    function Execute(const ShowWindow: Boolean; const ScriptName: string): TScriptResult;
    procedure CopyFrom(const AMovie: TMovie);
    procedure CopyTo(AMovie: TMovie; const AllowClear: Boolean);
    procedure SetField(const AField: TMovieField; const AValue: string);
    procedure SetCustomField(const AField: string; const AValue: string);
    function GetField(const AField: TMovieField): string;
    function GetCustomField(const AField: string): string;
    procedure SetPicture(AStream: TStream; const PicURL: string);
    procedure ImportPicture(FileName: string);
    procedure ExportPicture(Dir: string; PicName: string);
  end;

var
  ScriptResultsWin: TScriptResultsWin;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

implementation

{$R *.dfm}

uses
  CommCtrl,

  Global, functions_files, constValues, pictureform;

const
  msgResultsCaption = 0;
  msgClickPicture   = 1;
  msgRememberFields = 2;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.FormCreate(Sender: TObject);
begin
  FMovieCopy := TMovie.Create(nil);
  inherited;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.FormDestroy(Sender: TObject);
begin
  FMovieCopy.Free;
  inherited;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.GenerateFields(CustomFieldsProperties: TCustomFieldsProperties);
var
  NewItem: TListItem;
  f: Integer;
begin
  FCustomFieldsProperties := CustomFieldsProperties;
  FMovieCopy.CustomFields.Properties := CustomFieldsProperties;
  lstValues.Items.Clear;
  with lstValues.Items do
  begin
    BeginUpdate;
    try
      for f := fieldLow to fieldCount-1 do
        if not (f in VirtualFields) then
        begin
          NewItem := Add;
          NewItem.Caption := strFields[f];
          NewItem.Data := Pointer(f);
        end;
      NewItem := Add;
      NewItem.Caption := strFieldPicture;
      NewItem.Data := Pointer(fieldPicture);
      // Add CustomFields
      with FCustomFieldsProperties do
        for f := 0 to Count-1 do
        begin
          NewItem := lstValues.Items.Add;
          NewItem.Caption := Objects[f].FieldName + ' (' + Objects[f].FieldTag + ')';
          NewItem.Data := Pointer(customFieldLow+f);
        end;
    finally
      EndUpdate;
    end;
  end;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

function TScriptResultsWin.Execute(const ShowWindow: Boolean; const ScriptName: string): TScriptResult;
var
  i, f: Integer;
  s: string;
  CurItem: TListItem;
  DoubleSize: Double;
  CustomFieldProperties: TCustomFieldProperties;
begin
  if ShowWindow then
  begin
    Caption := Format(Messages.Strings[msgResultsCaption], [ScriptName, FMovieOrig.iNumber]);
    s := FMovieOrig.GetFormattedTitle;
    if s = '' then
      s := FMovieCopy.GetFormattedTitle;
    if s <> '' then
      Caption := Format('%s "%s"', [Caption, s]);
    for i := 0 to lstValues.Items.Count-1 do
    begin
      CurItem := lstValues.Items[i];
      f := Integer(CurItem.Data);
      if f in AllFields then
      begin
        CurItem.Caption := strFields[f];
        CurItem.SubItems.Clear;
        CurItem.SubItems.Add(FMovieOrig.GetFieldValue(f, True));
        if f in FModifiedFields then
        begin
          CurItem.SubItems.Add(FMovieCopy.GetFieldValue(f, True));
          CurItem.Checked := True;
        end
        else
        begin
          CurItem.SubItems.Add('');
          CurItem.Checked := False;
        end;
      end
      else
      if f in AllCustomFields then
      begin
        CustomFieldProperties := FCustomFieldsProperties.Objects[f-customFieldLow];
        CurItem.Caption := CustomFieldProperties.FieldName + ' (' + CustomFieldProperties.FieldTag + ')';
        CurItem.SubItems.Clear;
        CurItem.SubItems.Add(FMovieOrig.CustomFields.GetFieldValue(CustomFieldProperties.FieldTag, False, True));
        if f in FModifiedCustomFields then
        begin
          CurItem.SubItems.Add(FMovieCopy.CustomFields.GetFieldValue(CustomFieldProperties.FieldTag, False, True));
          CurItem.Checked := True;
        end
        else
        begin
          CurItem.SubItems.Add('');
          CurItem.Checked := False;
        end;
      end
      else
      if f = fieldPicture then
      begin
        CurItem.Caption := strFieldPicture;
        CurItem.SubItems.Clear;
        if FMovieOrig.strPicture <> '' then
        begin
          DoubleSize := FMovieOrig.GetPictureSize(ExtractFilePath(FCurrentCatalog.CurrentFile)) / 1024.0;
          CurItem.SubItems.Add(Format(Messages.Strings[msgClickPicture], [DoubleSize]));
        end
        else
          CurItem.SubItems.Add('');
        if FModifiedPicture then
        begin
          DoubleSize := FMovieCopy.GetPictureSize(ExtractFilePath(FCurrentCatalog.CurrentFile)) / 1024.0;
          CurItem.SubItems.Add(Format(Messages.Strings[msgClickPicture], [DoubleSize]));
          CurItem.Checked := True;
        end
        else
        begin
          CurItem.SubItems.Add('');
          CurItem.Checked := False;
        end;
      end;
    end;
    case ShowModal of
      mrYes:
        Result := srSave;
      mrYesToAll:
        Result := srSaveAll;
      mrNo:
        Result := srSkip;
      mrNoToAll,
      mrCancel:
        Result := srAbort;
    else
      raise Exception.Create('Unexpected result in TScriptResultsWin.Execute');
    end;
    if Result in [srSave, srSaveAll] then
    begin
      FSelectedFields := [];
      FSelectedCustomFields := [];
      FSelectedPicture := False;
      for i := 0 to lstValues.Items.Count-1 do
      begin
        CurItem := lstValues.Items[i];
        if CurItem.Checked then
        begin
          f := Integer(CurItem.Data);
          if f in AllFields then
            Include(FSelectedFields, f)
          else
          if f in AllCustomFields then
            Include(FSelectedCustomFields, f)
          else
          if f = fieldPicture then
            FSelectedPicture := True;
        end;
      end;
    end;
  end
  else
  begin
    if not FKeepSelectedFields then
    begin
      FSelectedFields := FModifiedFields;
      FSelectedCustomFields := FModifiedCustomFields;
      FSelectedPicture := FModifiedPicture;
    end;
    Result := srSaveAll;
  end;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.CopyFrom(const AMovie: TMovie);
begin
  FMovieOrig := AMovie;
  FModifiedFields := [];
  FModifiedCustomFields := [];
  FModifiedPicture := False;
  FMovieCopy.Assign(AMovie);
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.CopyTo(AMovie: TMovie; const AllowClear: Boolean);
var
  f: Integer;
  Ext, s: string;
  OutFile: TFileStream;
  OutFileName: TFileName;
  CustomFieldProperties: TCustomFieldProperties;
begin
  for f := fieldLow to fieldCount-1 do
    if f in FSelectedFields then
    begin
      if f in FModifiedFields then
      begin
        s := FMovieCopy.GetFieldValue(f);
        if (s <> '') or AllowClear then
          AMovie.SetFieldValue(f, s);
      end
      else
      begin
        if AllowClear then
          AMovie.SetFieldValue(f, '');
      end;
    end;
  with FCustomFieldsProperties do
    for f := 0 to Count-1 do
      if (f+customFieldLow) in FSelectedCustomFields then
      begin
        CustomFieldProperties := FCustomFieldsProperties.Objects[f];
        if (f+customFieldLow) in FModifiedCustomFields then
        begin
          s := FMovieCopy.CustomFields.GetFieldValue(CustomFieldProperties.FieldTag);
          if (s <> '') or AllowClear then
            AMovie.CustomFields.SetFieldValue(CustomFieldProperties.FieldTag, s);
        end
        else
        begin
          if AllowClear then
            AMovie.CustomFields.SetFieldValue(CustomFieldProperties.FieldTag, '');
        end;
      end;
  if FSelectedPicture and ((FMovieCopy.strPicture <> '') or AllowClear) then
  begin
    if FCurrentCatalog.CurrentFile <> '' then
    begin
      SetCurrentDir(ExtractFilePath(FCurrentCatalog.CurrentFile));
      if (AMovie.Picture = nil) and (AMovie.strPicture <> '') and (Pos('\', AMovie.strPicture) = 0) then
        DeleteFile(AMovie.strPicture);
    end;
    AMovie.Picture.Free;
    AMovie.Picture := nil;
    AMovie.strPicture := '';
    if (AMovie._thumb <> nil) then
      FreeAndNil(AMovie._thumb);
    AMovie._thumbError := 0;

    if FModifiedPicture and Assigned(FMovieCopy.Picture) then
    begin
      FMovieCopy.Picture.Seek(0, soFromBeginning);
      Ext := FMovieCopy.strPicture;
      if (Settings.rOptions.rMovieInformation.rPicImport.ScriptingMethod = 2 {copy and link}) and (FCurrentCatalog.CurrentFile <> '') then
      begin
        case Settings.rOptions.rMovieInformation.rPicImport.Naming of
          1:  OutFileName := Format('%d%s', [FMovieCopy.iNumber, Ext]);
          2:  OutFileName := Format('%s%s', [ValidateFileName(FMovieCopy.GetFormattedTitle), Ext]);
        else
          OutFileName := ChangeFileExt(ValidateFileName(Lowercase(Copy(FPictureURL, LastDelimiter('/\', FPictureURL) + 1, Length(FPictureURL)))), Ext);
        end;
        if Settings.rOptions.rMovieInformation.rPicImport.CatalogPrefix then
          OutFileName := Format('%s_%s', [ChangeFileExt(ExtractFileName(FCurrentCatalog.CurrentFile), ''), OutFileName]);
        AMovie.strPicture := OutFileName;
        try
          OutFile := TFileStream.Create(ExtractFilePath(FCurrentCatalog.CurrentFile) + OutFileName, fmCreate);
          try
            OutFile.Size := FMovieCopy.Picture.Size;
            OutFile.Seek(0, soFromBeginning);
            OutFile.CopyFrom(FMovieCopy.Picture, FMovieCopy.Picture.Size);
          finally
            OutFile.Free;
          end;
        except
          AMovie.strPicture := '';
        end;
      end else
      begin
        with AMovie do
        begin
          strPicture := Ext;
          Picture := TMemoryStream.Create;
          Picture.Seek(0, soFromBeginning);
          Picture.CopyFrom(FMovieCopy.Picture, FMovieCopy.Picture.Size);
        end;
      end;
      if (AMovie._thumb <> nil) then
        FreeAndNil(AMovie._thumb);
      AMovie._thumbError := 0;
    end;
    FCurrentCatalog.Modified := True;
  end;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.Init(const AllowedFields: TMovieFields; const AllowPicture: Boolean;
  const CurrentCatalog: TFileManager);
var
  f: Integer;
begin
  FAllowedFields := AllowedFields;

  FAllowedCustomFields := [];
  with FCustomFieldsProperties do
    for f := 0 to Count-1 do
    if not Objects[f].ExcludedInScripts then
      Include(FAllowedCustomFields, f+customFieldLow);

  FAllowPicture := AllowPicture;
  FCurrentCatalog := CurrentCatalog;
  FKeepSelectedFields := False;

end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.SetField(const AField: TMovieField; const AValue: string);
begin
  if AField in FAllowedFields then
  begin
    FMovieCopy.SetFieldValue(AField, AValue);
    Include(FModifiedFields, AField);
  end;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.SetCustomField(const AField: string; const AValue: string);
var
  Idx: Integer;
begin
  Idx := FCustomFieldsProperties.IndexOf(AField);
  if ((Idx+customFieldLow) in FAllowedCustomFields) then
  begin
    FMovieCopy.CustomFields.SetFieldValue(AField, AValue, False);
    Include(FModifiedCustomFields, Idx+customFieldLow);
  end;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

function TScriptResultsWin.GetField(const AField: TMovieField): string;
begin
  Result := FMovieCopy.GetFieldValue(AField, True);
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

function TScriptResultsWin.GetCustomField(const AField: string): string;
begin
  Result := FMovieCopy.CustomFields.GetFieldValue(AField, False, True);
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.SetPicture(AStream: TStream; const PicURL: string);
var
  Ext: string;
begin
  if FAllowPicture then
  begin
    Ext := GetRealPictureExt(AStream, extImage[extPNG], extImage[extJPG], extImage[extGIF], ExtractFileExt(PicURL));
    if Ext = '' then
      Exit;
    AStream.Seek(0, soFromBeginning);
    with FMovieCopy do
    begin
      Picture.Free;
      Picture := TMemoryStream.Create;
      Picture.CopyFrom(AStream, AStream.Size);
      strPicture := Ext;
    end;
    FModifiedPicture := True;
    FPictureURL := PicURL;
  end;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.ImportPicture(FileName: string);
var
  Stream: TFileStream;
begin
  SetCurrentDir(strDirApp);
  Stream := nil;
  FileName := ExpandFileName(FileName);
  if FileExists(FileName) then
    try
      Stream := TFileStream.Create(FileName, fmOpenRead);
      SetPicture(Stream, FileName);
    except
    end;
  Stream.Free;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.ExportPicture(Dir: string; PicName: string);
var
  Movie: TMovie;
  PicExt: string;
begin
  Movie := nil;
  if (FMovieCopy <> nil) and (FMovieCopy.strPicture <> '') then
    Movie := FMovieCopy
  else if (FMovieOrig <> nil) and (FMovieOrig.strPicture <> '') then
    Movie := FMovieOrig;
  if(Movie <> nil) then
  begin
    with Movie do
    begin
      if FCurrentCatalog.CurrentFile <> '' then
        SetCurrentDir(ExtractFilePath(FCurrentCatalog.CurrentFile));
      Dir := IncludeTrailingPathDelimiter(Dir);
      PicName := ValidateFileName(PicName);
      PicExt := ExtractFileExt(strPicture);
      if Picture <> nil then
      begin
        try
          Picture.SaveToFile(Dir + PicName + PicExt);
        except
        end;
      end else
      begin
        try
          CopyFile(PChar(ExpandFileName(strPicture)), PChar(Dir + PicName + PicExt), false);
        except
        end;
      end;
    end;
  end;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.btn3Click(Sender: TObject);
begin
  case MessageWin.Execute(Messages.Strings[msgRememberFields], mtConfirmation, [mbYes, mbNo, mbCancel]) of
    1:  FKeepSelectedFields := True;
    2:  FKeepSelectedFields := False;
  else
    Exit;
  end;
  ModalResult := mrYesToAll;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.lstValuesDblClick(Sender: TObject);
begin
  with (Sender as TListView) do
    if (Selected <> nil) then
      Selected.Checked := not Selected.Checked;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.lstValuesCustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
var
  f: Integer;
begin
  Sender.Canvas.Font.Color := clWindowText;
  if not (cdsSelected in State) and (Item <> nil) then
  begin
    f := Integer(Item.Data);
    if ((f in AllFields) and not (f in FModifiedFields)) or
      ((f in AllCustomFields) and not (f in FModifiedCustomFields)) or
      ((f = fieldPicture) and not (FModifiedPicture)) then
      Sender.Canvas.Font.Color := clGrayText;
  end;
  DefaultDraw := True;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.lstValuesMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  CurItem: TListItem;
  ti: TLVHitTestInfo;
  Mov: TMovie;
begin
  if (Button <> mbLeft) then
    Exit;
  CurItem := lstValues.Selected;
  if (CurItem = nil) or (Integer(CurItem.Data) <> FieldPicture) then
    Exit;
  FillChar(ti, SizeOf(ti), #0);
  ti.pt.X := X;
  ti.pt.Y := Y;
  if lstValues.Perform(LVM_SUBITEMHITTEST, 0, LParam(@ti)) <> -1 then
  begin
    case ti.iSubItem of
      1:  Mov := FMovieOrig;
      2:  Mov := FMovieCopy;
    else
      Mov := nil;
    end;
    if Mov <> nil then
    begin
      PictureWin := TPictureWin.Create(Self);
      try
        PictureWin.CenterWindow := True;
        SetCurrentDir(ExtractFilePath(FCurrentCatalog.CurrentFile));
        if Mov.Picture = nil then
          PictureWin.Execute(Mov.GetFormattedTitle, Mov.strPicture)
        else
          PictureWin.Execute(Mov.GetFormattedTitle, Mov.Picture, Mov.strPicture);
      finally
        FreeAndNil(PictureWin)
      end;
    end;
  end;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.LoadOptions;
begin
  with Settings.rScripts.rResults do
  begin
    Self.Width := WindowWidth;
    Self.Height := WindowHeight;
  end;
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

procedure TScriptResultsWin.SaveOptions;
begin
  with Settings.rScripts.rResults do
  begin
    WindowWidth := Self.Width;
    WindowHeight := Self.Height;
  end;
end;

end.
