unit uFactuGES_App;

interface

uses
  SysUtils, Classes, Forms, uBizUsuarios, uBizEmpresas, uBizEjercicios, uControllerBase,
  uEmpresasController, uUsuariosController, uHostManager, uConfiguracionController,
  uBizEmpresasTiendas, uModuleController;

const
  CTE_PERFIL_ADMINISTRADOR = 2;
  CTE_PREFIL_GERENCIA = 3;
  CTE_PERFIL_VENDEDOR = 4;
  CTE_PREFIL_LOGISTICA = 5;

type
  TAppFactuGES_Event = procedure;

  IAppSplashForm = interface
    ['{9905DF57-4476-42E6-A7CD-B1479A84E220}']
    procedure Show;
    procedure Hide;
    procedure Update;
    function GetMensaje: String;
    procedure SetMensaje(const AMensaje : String);
    property Mensaje : String read GetMensaje write SetMensaje;
  end;

  IAppFactuGES = interface
    ['{FB6A0F3C-C1D1-462D-AFD4-2A368F85E920}']
    function GetMainForm: TCustomForm;
    function GetEmpresasController: IEmpresasController;
    function GetUsuariosController: IUsuariosController;
    function GetAppName: String;
    function GetAppFullName: String;
    function GetAppVersion: String;
    function GetUsuarioActivo: IBizUsuario;
    function GetEmpresaActiva: IBizEmpresa;
    function GetTiendaActiva: IBizEmpresaTienda;
    function GetEjercicioActivo: IBizEjercicio;
    function GetModuleManager : THostManager;
    function GetTerminated: Boolean;
    function GetConfiguracionController : IConfiguracionController;
    function GetFormaPagoDocumentos: String;
    function GetObservacionesDocumentos: String;
    function GetCondicionesDocumentos: String;
    function GetCalidadesDocumentos: String;
    procedure SetFormaPagoDocumentos(const Value: String);
    procedure SetObservacionesDocumentos(const Value: String);
    procedure SetCondicionesDocumentos(const Value: String);
    procedure SetCalidadesDocumentos(const Value: String);

    function GetLoadModulesEvent : TAppFactuGES_Event;
    procedure SetLoadModulesEvent (ALoadModulesEvent : TAppFactuGES_Event);

    function GetDoMainFormEvent : TAppFactuGES_Event;
    procedure SetDoMainFormEvent (AMainFormEvent : TAppFactuGES_Event);

    function GetDoRefreshMainFormEvent : TAppFactuGES_Event;
    procedure SetDoRefreshMainFormEvent (ARefreshMainFormEvent : TAppFactuGES_Event);

    function GetAppSplashForm : IAppSplashForm;
    procedure SetAppSplashForm (AAppSplashForm : IAppSplashForm);

    procedure SeleccionarEmpresa;
    procedure CambiarEmpresa(const AIDEmpresa : Integer);
    procedure CambiarEmpresaPorDefecto;
    procedure CambiarEjercicio(const AIDEmpresa : Integer);

    procedure ShowSplashForm;
    procedure HideSplashForm;

    procedure Run;
    procedure Terminate;

    function GetModule(AModuleName: String): TModuleController;

    procedure Configurar;

    property AppVersion : String read GetAppVersion;
    property AppName : String read GetAppName;
    property AppFullName : String read GetAppFullName;
    property MainForm : TCustomForm read GetMainForm;
    property EmpresaActiva : IBizEmpresa read GetEmpresaActiva;
    property TiendaActiva : IBizEmpresaTienda read GetTiendaActiva;
    property EjercicioActivo : IBizEjercicio read GetEjercicioActivo;
    property UsuarioActivo : IBizUsuario read GetUsuarioActivo;
    property EmpresasController : IEmpresasController read GetEmpresasController;
    property UsuariosController : IUsuariosController read GetUsuariosController;
    property AppSplashForm : IAppSplashForm read GetAppSplashForm write SetAppSplashForm;
    property ModuleManager : THostManager read GetModuleManager;
    property DoMainFormEvent : TAppFactuGES_Event read GetDoMainFormEvent write SetDoMainFormEvent;
    property DoLoadModulesEvent : TAppFactuGES_Event read GetLoadModulesEvent write SetLoadModulesEvent;
    property DoRefreshMainFormEvent : TAppFactuGES_Event read GetDoRefreshMainFormEvent write SetDoRefreshMainFormEvent;
    property Terminated : Boolean read GetTerminated;
    property Configuracion : IConfiguracionController read GetConfiguracionController;
    property FormaPagoDocumentos : String read GetFormaPagoDocumentos write SetFormaPagoDocumentos;
    property ObservacionesDocumentos : String read GetObservacionesDocumentos write SetObservacionesDocumentos;
    property CondicionesDocumentos : String read GetCondicionesDocumentos write SetCondicionesDocumentos;
    property CalidadesDocumentos : String read GetCalidadesDocumentos write SetCalidadesDocumentos;
  end;


  TAppFactuGES = class(TInterfacedObject, IAppFactuGES)
  private
    FEmpresasController : IEmpresasController;
    FUsuariosController: IUsuariosController;
    FEmpresaActiva: IBizEmpresa;
    FTiendaActiva: IBizEmpresaTienda;
    FEjercicioActivo: IBizEjercicio;
    FConfiguracionController : IConfiguracionController;
    FFormaPagoDocumentos: String;
    FObservacionesDocumentos: String;
    FCondicionesDocumentos: String;
    FCalidadesDocumentos: String;

    FAppSplashForm : IAppSplashForm;
    FHostManager : THostManager;
    FTerminated : Boolean;

    FDoMainFormEvent: TAppFactuGES_Event;
    FDoLoadModulesEvent: TAppFactuGES_Event;
    FDoRefreshMainFormEvent: TAppFactuGES_Event;

    function GetMainForm: TCustomForm;
    function GetEmpresasController: IEmpresasController;
    function GetUsuariosController: IUsuariosController;
    function GetAppName: String;
    function GetAppFullName: String;
    function GetAppVersion: String;
    function GetUsuarioActivo: IBizUsuario;
    function GetEmpresaActiva: IBizEmpresa;
    function GetTiendaActiva: IBizEmpresaTienda;
    function GetEjercicioActivo: IBizEjercicio;
    function GetModuleManager : THostManager;
    function GetTerminated: Boolean;
    function GetConfiguracionController : IConfiguracionController;
    function GetFormaPagoDocumentos: String;
    function GetObservacionesDocumentos: String;
    function GetCondicionesDocumentos: String;
    procedure SetFormaPagoDocumentos(const Value: String);
    procedure SetObservacionesDocumentos(const Value: String);
    procedure SetCondicionesDocumentos(const Value: String);

    function GetLoadModulesEvent : TAppFactuGES_Event;
    procedure SetLoadModulesEvent (ALoadModulesEvent : TAppFactuGES_Event);

    function GetDoMainFormEvent : TAppFactuGES_Event;
    procedure SetDoMainFormEvent (AMainFormEvent : TAppFactuGES_Event);

    function GetDoRefreshMainFormEvent : TAppFactuGES_Event;
    procedure SetDoRefreshMainFormEvent (ARefreshMainFormEvent : TAppFactuGES_Event);

    function GetAppSplashForm : IAppSplashForm;
    procedure SetAppSplashForm (AAppSplashForm : IAppSplashForm);

    procedure AfterLoadModule(Sender: TObject; AModuleInfo: TModuleInfo);
    procedure RegisterModule(AModuleInfo : TModuleInfo);
    procedure BuscarTiendaPorDefecto;
    function GetCalidadesDocumentos: String;
    procedure SetCalidadesDocumentos(const Value: String);

  protected
    procedure DoMainForm;
    procedure DoRefreshMainForm;

    procedure CargarModulos;
    procedure ShowSplashForm;
    procedure HideSplashForm;
    procedure UpdateSplashForm;

  public
    constructor Create; virtual;
    destructor Destroy; override;

    procedure Run;
    procedure Terminate;

    procedure Configurar;

    procedure SeleccionarEmpresa;
    procedure CambiarEmpresa(const AIDEmpresa : Integer);
    procedure CambiarEmpresaPorDefecto;
    procedure CambiarEjercicio(const AIDEmpresa : Integer);

    function GetModule(AModuleName: String): TModuleController;    

    property AppVersion : String read GetAppVersion;
    property AppName : String read GetAppName;
    property AppFullName : String read GetAppFullName;
    property MainForm : TCustomForm read GetMainForm;
    property EmpresaActiva : IBizEmpresa read GetEmpresaActiva;
    property TiendaActiva : IBizEmpresaTienda read GetTiendaActiva;
    property EjercicioActivo : IBizEjercicio read GetEjercicioActivo;
    property AppSplashForm : IAppSplashForm read GetAppSplashForm write SetAppSplashForm;
    property UsuarioActivo : IBizUsuario read GetUsuarioActivo;
    property EmpresasController : IEmpresasController read GetEmpresasController;
    property UsuariosController : IUsuariosController read GetUsuariosController;
    property ModuleManager : THostManager read GetModuleManager;
    property DoMainFormEvent : TAppFactuGES_Event read GetDoMainFormEvent write SetDoMainFormEvent;
    property DoLoadModulesEvent : TAppFactuGES_Event read GetLoadModulesEvent write SetLoadModulesEvent;
    property DoRefreshMainFormEvent : TAppFactuGES_Event read GetDoRefreshMainFormEvent write SetDoRefreshMainFormEvent;
    property Terminated : Boolean read GetTerminated;
    property Configuracion : IConfiguracionController read GetConfiguracionController;
    property FormaPagoDocumentos : String read GetFormaPagoDocumentos write SetFormaPagoDocumentos;
    property ObservacionesDocumentos : String read GetObservacionesDocumentos write SetObservacionesDocumentos;
    property CondicionesDocumentos : String read GetCondicionesDocumentos write SetCondicionesDocumentos;
    property CalidadesDocumentos : String read GetCalidadesDocumentos write SetCalidadesDocumentos;
  end;

var
  AppFactuGES : IAppFactuGES;

implementation
{$INCLUDE ..\FactuGES.inc}

uses
  Windows, Dialogs, JSDialog, JSDialogs, uDialogUtils, cxControls, uUsuariosViewRegister, uDMBase,
  uEmpresasViewRegister, uEjerciciosController, uAppInfoUtils;

procedure TAppFactuGES.CambiarEjercicio(const AIDEmpresa: Integer);
var
  Aux : IBizEjercicio;
  AEjerciciosController: IEjerciciosController;
begin
  AEjerciciosController := TEjerciciosController.Create;
  try
    Aux := AEjerciciosController.BuscarActivo(AIDEmpresa);
    if Assigned(Aux) then
    begin
      Aux.DataTable.Active := True;
      if not Aux.IsEmpty then
        FEjercicioActivo := Aux
      else
        FEjercicioActivo := Nil;
    end;
  finally
    AEjerciciosController := Nil;
  end;
end;

procedure TAppFactuGES.CambiarEmpresa(const AIDEmpresa: Integer);
var
  Aux : IBizEmpresa;
begin
  Aux := EmpresasController.Buscar(AIDEmpresa);
  if Assigned(Aux) then
  begin
    Aux.DataTable.Active := True;
    if not Aux.IsEmpty then
       FEmpresaActiva := Aux;
  end;

  if Assigned(FEmpresaActiva) then
  begin
     dmBase.dxPrintStyleManager1Style1.PrinterPage.PageFooter.LeftTitle.Clear;
     dmBase.dxPrintStyleManager1Style1.PrinterPage.PageFooter.LeftTitle.Add(FEmpresaActiva.NOMBRE);
  end;
  
  //Establece el ejercicio activo de la empresa activa
  CambiarEjercicio(AIDEmpresa);
  BuscarTiendaPorDefecto;
end;

procedure TAppFactuGES.CambiarEmpresaPorDefecto;
var
  AEmpresas : IBizEmpresa;
begin
  AEmpresas := FEmpresasController.BuscarTodos;
  try
    AEmpresas.DataTable.Active := True;
    if AEmpresas.DataTable.RecordCount > 0 then
      CambiarEmpresa(AEmpresas.ID);
    AEmpresas.DataTable.Active := False;
  finally
    AEmpresas := NIL;
  end;
end;

procedure TAppFactuGES.CargarModulos;
begin
  if not Assigned(FDoLoadModulesEvent) then
    raise Exception.Create('Evento para la carga de los módulos de la aplicación no asignado (CargarModulos)');

  FDoLoadModulesEvent();
end;

procedure TAppFactuGES.Configurar;
begin
  FConfiguracionController.ConfigurarAplicacion;
  FConfiguracionController.AplicarConfiguracion;
end;

procedure TAppFactuGES.BuscarTiendaPorDefecto;
begin
  //OJO -> MIRAR SIEMPRE QUE EL VENDEDOR TENGA ASOCIADA UNA TIENDA Y UN USUARIO EXISTENTE
  //Nos devuelve el id de la tienda a la que pertenece el vendedor que tiene asignado
  //el usuario con el que ha accedido a la aplicación.
  //Esto funciona mientras la relación sea 1 a 1, cuando sea 1 a n (un usuario pertenece a varios vendedores deja de funcionar)
  FTiendaActiva := EmpresasController.DarTiendaUsuario(EmpresaActiva, UsuarioActivo.ID);

  Assert(Assigned(FTiendaActiva));

  if Assigned(FTiendaActiva) then
    FTiendaActiva.DataTable.Open;
end;

constructor TAppFactuGES.Create;
begin
  FTerminated := False;
  FDoMainFormEvent := NIL;
  FDoLoadModulesEvent := NIL;
  FAppSplashForm := NIL;
  FEmpresaActiva := NIL;
  FUsuariosController := NIL; // Se crea la primera vez que se usa
  FEmpresasController := NIL; // Se crea la primera vez que se usa

  FHostManager := THostManager.Create(NIL);
  with FHostManager do
  begin
    OnAfterLoad := AfterLoadModule;
    // Ruta por defecto de los módulos
    BPLPath := ExtractFilePath(Application.ExeName) + PathDelim;
  end;

  FConfiguracionController := TConfiguracionController.Create;
end;

destructor TAppFactuGES.Destroy;
begin
  FAppSplashForm := NIL;

  FHostManager.UnloadModules;

  FreeAndNIL(FHostManager);

  FConfiguracionController := NIL;

  FTiendaActiva := NIL;
  FEjercicioActivo := NIL;
  FEmpresaActiva := NIL;

  FUsuariosController := NIL;
  FEmpresasController := NIL;

  inherited;
end;

procedure TAppFactuGES.DoMainForm;
begin
  if not Assigned(FDoMainFormEvent) then
    raise Exception.Create('Evento para la creación del formulario principal no asignado (DoMainForm)');

  FDoMainFormEvent();
end;

procedure TAppFactuGES.DoRefreshMainForm;
begin
  if not Assigned(FDoRefreshMainFormEvent) then
    raise Exception.Create('Evento para el refresco del formulario principal no asignado (DoRefreshMainForm)');

  DoRefreshMainFormEvent();
end;

function TAppFactuGES.GetMainForm: TCustomForm;
begin
  Result := Application.MainForm;
end;

function TAppFactuGES.GetDoMainFormEvent: TAppFactuGES_Event;
begin
  Result := FDoMainFormEvent;
end;

function TAppFactuGES.GetDoRefreshMainFormEvent: TAppFactuGES_Event;
begin
  Result := FDoRefreshMainFormEvent;
end;

function TAppFactuGES.GetAppFullName: String;
begin
  Result := uAppInfoUtils.GetAppFullName;  
end;

function TAppFactuGES.GetAppName: String;
begin
  Result := uAppInfoUtils.GetAppName; 
end;

function TAppFactuGES.GetAppSplashForm: IAppSplashForm;
begin
  Result := FAppSplashForm;
end;

function TAppFactuGES.GetAppVersion: String;
begin
  Result := uAppInfoUtils.GetAppVersion; 
end;

function TAppFactuGES.GetCalidadesDocumentos: String;
begin
  Result := FCalidadesDocumentos;
end;

function TAppFactuGES.GetCondicionesDocumentos: String;
begin
  Result := FCondicionesDocumentos;
end;

function TAppFactuGES.GetConfiguracionController: IConfiguracionController;
begin
  Result := FConfiguracionController;
end;

function TAppFactuGES.GetEjercicioActivo: IBizEjercicio;
begin
  Result := FEjercicioActivo;
end;

function TAppFactuGES.GetEmpresaActiva: IBizEmpresa;
begin
  Result := FEmpresaActiva
end;

function TAppFactuGES.GetEmpresasController: IEmpresasController;
begin
  if not Assigned(FEmpresasController) then
    FEmpresasController := TEmpresasController.Create;

  Result := FEmpresasController;
end;

function TAppFactuGES.GetFormaPagoDocumentos: String;
begin
  Result := FFormaPagoDocumentos;
end;

function TAppFactuGES.GetLoadModulesEvent: TAppFactuGES_Event;
begin
  Result := FDoLoadModulesEvent;
end;

function TAppFactuGES.GetModule(AModuleName: String): TModuleController;
var
  i : integer;
begin
  Result := NIL;
  for i := 0 to ModuleManager.ModulesCount - 1 do
    if ModuleManager.Modules[i].Module.ModuleName = AModuleName then
    begin
      Result := ModuleManager.Modules[i].Module;
      Break;
    end;
end;

function TAppFactuGES.GetModuleManager: THostManager;
begin
  Result := FHostManager;
end;

function TAppFactuGES.GetObservacionesDocumentos: String;
begin
  Result := FObservacionesDocumentos;
end;

function TAppFactuGES.GetTerminated: Boolean;
begin
  Result := FTerminated;
end;

function TAppFactuGES.GetTiendaActiva: IBizEmpresaTienda;
begin
  Result := FTiendaActiva;
end;

function TAppFactuGES.GetUsuarioActivo: IBizUsuario;
begin
  Result := UsuariosController.CurrentUser;
end;

function TAppFactuGES.GetUsuariosController: IUsuariosController;
begin
  if not Assigned(FUsuariosController) then
    FUsuariosController := TUsuariosController.Create;

  Result := FUsuariosController;
end;

procedure TAppFactuGES.HideSplashForm;
begin
  if Assigned(FAppSplashForm) then
    FAppSplashForm.Hide;
end;

procedure TAppFactuGES.AfterLoadModule(Sender: TObject;
  AModuleInfo: TModuleInfo);
begin
  RegisterModule(AModuleInfo);
end;

procedure TAppFactuGES.RegisterModule(AModuleInfo: TModuleInfo);
begin
  if Assigned(FAppSplashForm) then
    FAppSplashForm.Mensaje := 'Cargando ''' + AModuleInfo.Module.ModuleName + '''...';
end;

procedure TAppFactuGES.Run;
begin
  FConfiguracionController.AplicarConfiguracion;
  if UsuariosController.StartLogin then
  begin
    ShowHourglassCursor;
    try
      ShowSplashForm;
      CargarModulos;
      DoMainForm;
      SeleccionarEmpresa;
      DoRefreshMainForm;  
    finally
      HideHourglassCursor;
      HideSplashForm;
    end;
    Application.Run;
  end;
  Terminate;
end;

procedure TAppFactuGES.SetDoMainFormEvent(
  AMainFormEvent: TAppFactuGES_Event);
begin
  FDoMainFormEvent := AMainFormEvent;
end;

procedure TAppFactuGES.SetDoRefreshMainFormEvent(
  ARefreshMainFormEvent: TAppFactuGES_Event);
begin
  FDoRefreshMainFormEvent := ARefreshMainFormEvent; 
end;

procedure TAppFactuGES.SetFormaPagoDocumentos(const Value: String);
begin
  FFormaPagoDocumentos := Value;
end;

procedure TAppFactuGES.SeleccionarEmpresa;
var
  JsDialog: TJSDialog;
  AEmpresas: IBizEmpresa;
  AEmpresasController: IEmpresasController;
begin
  JsDialog := TJSDialog.Create(nil);
  try
    JsDialog.Content.Add('Selección de empresa');
    JsDialog.Instruction.Text := 'Elija la empresa con la que desea trabajar.';
    JsDialog.DialogOptions := [doCommandLinks, doModal];
    JsDialog.ButtonBar.Buttons := [cbCancel];
    JsDialog.Width := 600;

    //Añadimos las diferentes empresas que existan
    AEmpresasController := TEmpresasController.Create;
    AEmpresas := AEmpresasController.BuscarTodos(AppFactuGES.UsuarioActivo.ID_PERFIL);
    AEmpresas.DataTable.Active := True;

    AEmpresas.Datatable.First;
    while not AEmpresas.Datatable.eof do
    begin
      with JsDialog.CustomButtons.Add do
      begin
         Caption := AEmpresas.NIF_CIF + ' - ' + AEmpresas.NOMBRE;
         Value := AEmpresas.ID;
      end;
      AEmpresas.DataTable.Next;
    end;
    AEmpresas.DataTable.First;

    {$IFDEF MULTIEMPRESA}
    if JsDialog.Execute <> IDCANCEL then
       if JsDialog.CustomButtonResult > 0 then
          CambiarEmpresa(JsDialog.CustomButtonResult);
    {$ELSE}
    CambiarEmpresa(AEmpresas.ID);
    {$ENDIF}

  finally
    FreeAndNIL(JsDialog);
    AEmpresasController:= NIL;
    AEmpresas := NIL;
  end;
end;

procedure TAppFactuGES.SetAppSplashForm(AAppSplashForm: IAppSplashForm);
begin
  FAppSplashForm := AAppSplashForm;
end;

procedure TAppFactuGES.SetCalidadesDocumentos(const Value: String);
begin
  FCalidadesDocumentos := Value;
end;

procedure TAppFactuGES.SetCondicionesDocumentos(const Value: String);
begin
  FCondicionesDocumentos:= Value;
end;

procedure TAppFactuGES.SetLoadModulesEvent(
  ALoadModulesEvent: TAppFactuGES_Event);
begin
  FDoLoadModulesEvent := ALoadModulesEvent;
end;

procedure TAppFactuGES.SetObservacionesDocumentos(const Value: String);
begin
  FObservacionesDocumentos:= Value;
end;

{procedure TAppFactuGES.setVAR_IDTIENDA(AValue: Integer);
begin
  FVAR_IDTIENDA := Avalue;
end;

procedure TAppFactuGES.setVAR_TIENDA(AValue: String);
begin
  FVAR_TIENDA := Avalue;
end;}

procedure TAppFactuGES.ShowSplashForm;
begin
  if Assigned(FAppSplashForm) then
  begin
    FAppSplashForm.Show;
    FAppSplashForm.Update;
  end;
end;

procedure TAppFactuGES.Terminate;
begin
  ModuleManager.UnloadModules;
  FTerminated := True;
end;

procedure TAppFactuGES.UpdateSplashForm;
begin
  FAppSplashForm.Update;
end;

initialization
  // Pongo esto aquí por ahora
  AppFactuGES := NIL;
  
  uUsuariosViewRegister.RegisterViews;
  uEmpresasViewRegister.RegisterViews;

finalization
  // Pongo esto aquí por ahora
  AppFactuGES := NIL;

  uUsuariosViewRegister.UnregisterViews;
  uEmpresasViewRegister.UnregisterViews;

end.
