unit XData.Wizard.Service;

{$I XData.inc}

interface

uses
  ToolsAPI,
  Vcl.Graphics,
  System.UITypes;

type
  TXDataServiceWizard = class(TNotifierObject, IOTAWizard,
    IOTARepositoryWizard, IOTARepositoryWizard60, IOTARepositoryWizard80,
    IOTARepositoryWizard160, {$IF COMPILERVERSION > 31}IOTARepositoryWizard190, {$IFEND}
    IOTAProjectWizard, IOTAProjectWizard100)
  private
    FIcon: TIcon;
  protected
    function BeforeExecute: Boolean;
    function GetConnectionProject: IOTAProject;
    function UnitExists(AUnitIdent: string): Boolean;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    // IOTAWizard
    procedure Execute;
    function GetIDString: string;
    function GetName: string;
    function GetState: TWizardState;
    procedure AfterSave;
    procedure BeforeSave;
    procedure Destroyed;
    procedure Modified;
    // IOTARepositoryWizard
    function GetAuthor: string;
    function GetComment: string;
    function GetGlyph: Cardinal;
    function GetPage: string;
    // IOTARepositoryWizard60
    function GetDesigner: string;
    // IOTARepositoryWizard80
    function GetGalleryCategory: IOTAGalleryCategory;
    function GetPersonality: string;
    // IOTARepositoryWizard160
    function GetFrameworkTypes: TArray<string>;
    function GetPlatforms: TArray<string>;
    // IOTARepositoryWizard190
    function GetSupportedPlatforms: TArray<string>;
    // IOTAProjectWizard
    // IOTAProjectWizard100
    function IsVisible(Project: IOTAProject): Boolean;
  end;

implementation

uses
  SysUtils, Classes, Windows,
  XData.Wizard.Service.Form,
  XData.Wizard.Service.CodeGenerator,
  XData.Design.SourceCreator;

{ TXDataServiceWizard }

procedure TXDataServiceWizard.AfterSave;
begin

end;

function TXDataServiceWizard.BeforeExecute: Boolean;
begin
  Result := True; // Can always execute this wizard
end;

function TXDataServiceWizard.GetConnectionProject: IOTAProject;
var
  ModuleServices: IOTAModuleServices;
  Module: IOTAModule;
  OwnerModule: IOTAModule;
begin
  Result := nil;
  ModuleServices := (BorlandIDEServices as IOTAModuleServices);
  Module := ModuleServices.CurrentModule;

  if Assigned(ModuleServices.MainProjectGroup) then
  begin
    Exit(ModuleServices.GetActiveProject);
  end;

  if Module <> nil then
  begin
    if Module.OwnerModuleCount > 0 then
    begin
      OwnerModule := Module.OwnerModules[0];
      if OwnerModule <> nil then
        if OwnerModule.QueryInterface(IOTAProject, Result) <> S_OK then
          Result := nil;
    end;
  end;

  if Result = nil then
    Result := ToolsApi.GetActiveProject;
end;

function TXDataServiceWizard.UnitExists(AUnitIdent: string): Boolean;
var
  Services: IOTAModuleServices;
  Module: IOTAModule;
  I: integer;
begin
  Result := False;
  if Supports(BorlandIDEServices, IOTAModuleServices, Services) then
  begin
    for I := 0 to Services.ModuleCount - 1 do
    begin
      Module := Services.Modules[I];
      if SameText(AUnitIdent + '.pas', ExtractFileName(Module.FileName)) then
      begin
        Result := True;
        Break;
      end;
    end;
  end;
end;

procedure TXDataServiceWizard.BeforeSave;
begin

end;

constructor TXDataServiceWizard.Create;
var
  CategoryManager : IOTAGalleryCategoryManager;
begin
  CategoryManager := (BorlandIDEServices as IOTAGalleryCategoryManager);

  CategoryManager.AddCategory(CategoryManager.FindCategory(sCategoryDelphiNew),
    'TMS XData', 'TMS XData');

  FIcon := nil;
end;

destructor TXDataServiceWizard.Destroy;
begin
  FIcon.Free;
  inherited;
end;

procedure TXDataServiceWizard.Destroyed;
begin

end;

procedure TXDataServiceWizard.Execute;
var
  WizardForm : TFServiceWizardForm;
  CodeGenerator: TXDataServiceCodeGenerator;
  Services: IOTAModuleServices;
  Module: IOTAModule;
  NewUnitIdent, NewClassName, NewFileName: string;
  ServiceUnit: TXDataServiceUnit;
  SourceCode, ContractUnitName: string;
  I: Integer;
begin
  if not BeforeExecute then
    Exit;

  WizardForm := TFServiceWizardForm.Create(nil);
  try
    if WizardForm.ShowModal = mrOK then
    begin
      if Supports(BorlandIDEServices, IOTAModuleServices, Services) then
      begin
        CodeGenerator := TXDataServiceCodeGenerator.Create(WizardForm.Settings);
        try
          CodeGenerator.Execute;
          ContractUnitName := '';
          for I := 0 to CodeGenerator.GeneratedCode.Units.Count - 1 do
          begin
            ServiceUnit := CodeGenerator.GeneratedCode.Units[I];

            Services.GetNewModuleAndClassName(ServiceUnit.Name, NewUnitIdent, NewClassName, NewFileName);
            if not UnitExists(ServiceUnit.Name) then
            begin
              NewFileName := StringReplace(NewFileName, NewUnitIdent, ServiceUnit.Name, [rfReplaceAll, rfIgnoreCase]);
              NewUnitIdent := ServiceUnit.Name;
              NewClassName := '';
            end;

            if (WizardForm.Settings.SeparetedUnits) and (I = 0) then
              ContractUnitName := NewUnitIdent;

            SourceCode := ServiceUnit.SourceCode;
            SourceCode := StringReplace(SourceCode, '{UNITNAME_INTERFACE}', ContractUnitName, [rfReplaceAll, rfIgnoreCase]);
            SourceCode := StringReplace(SourceCode, '{UNITNAME_IMPLEMENTATION}', NewUnitIdent, [rfReplaceAll, rfIgnoreCase]);
            SourceCode := StringReplace(SourceCode, '{UNITNAME}', NewUnitIdent, [rfReplaceAll, rfIgnoreCase]);

            Module := Services.CreateModule(TXDataServiceSourceCreator.Create(
              GetConnectionProject, NewUnitIdent, NewFileName, SourceCode));
          end;
        finally
          CodeGenerator.Free;
        end;
      end;
    end;
  finally
    WizardForm.Free;
  end;
end;

function TXDataServiceWizard.GetAuthor: string;
begin
  Result := 'TMS Software';
end;

function TXDataServiceWizard.GetComment: string;
begin
  Result := 'Creates a new TMS XData service';
end;

function TXDataServiceWizard.GetDesigner: string;
begin
  Result := dVCL;
end;

function TXDataServiceWizard.GetFrameworkTypes: TArray<string>;
begin
  Result := nil;
end;

function TXDataServiceWizard.GetGalleryCategory: IOTAGalleryCategory;
begin
  Result := (BorlandIDEServices as IOTAGalleryCategoryManager)
    .FindCategory('TMS XData');
end;

function TXDataServiceWizard.GetGlyph: Cardinal;
var
  ResName : string;
begin
  if not Assigned(FIcon) then begin
    FIcon := TIcon.Create;
    ResName := 'XDATAWIZARDSERVICEICON';
    FIcon.LoadFromResourceName(HInstance, ResName);
  end;

  Result := CopyIcon(FIcon.Handle);
end;

function TXDataServiceWizard.GetIDString: string;
begin
  Result := 'TMS.XData.Service';
end;

function TXDataServiceWizard.GetName: string;
begin
  Result := 'TMS XData Service';
end;

function TXDataServiceWizard.GetPage: string;
begin
  Result := 'TMS XData';
end;

function TXDataServiceWizard.GetPersonality: string;
begin
  Result := sDelphiPersonality;
end;

function TXDataServiceWizard.GetPlatforms: TArray<string>;
begin
  Result := nil;
end;

function TXDataServiceWizard.GetState: TWizardState;
begin
  Result := [wsEnabled];
end;

function TXDataServiceWizard.GetSupportedPlatforms: TArray<string>;
begin
  Result := nil;
end;

function TXDataServiceWizard.IsVisible(Project: IOTAProject): Boolean;
begin
  Result := True;
end;

procedure TXDataServiceWizard.Modified;
begin

end;

end.
