unit ConnectionManager;
interface

uses TypeDefs, DataAccess, Access_OniArchive, Access_OUP_ADB, Access_OniSplitArchive;

type
  TConnections = array of TDataAccess;

  TConnectionListChangedEvent = procedure of object;

  
  TConnectionManager = class
  private
    FConnections: TConnections;
    FLastID:      Integer;
    FConnectionListChanged: TConnectionListChangedEvent;
    function GetConnectionCount: Integer;
    function GetConnection(ConnectionID: Integer): TDataAccess;
    function GetConnectionByIndex(Index: Integer): TDataAccess;
    function GetConnectionIndex(ConnectionID: Integer): Integer;
    procedure RemoveConnection(ArrayIndex: Integer);
  protected
  public
    property Count: Integer read GetConnectionCount;
    property Connection[ConnectionID: Integer]: TDataAccess read GetConnection;
    property ConnectionByIndex[Index: Integer]: TDataAccess read GetConnectionByIndex;
    property ConnectionIndexByID[ConnectionID: Integer]: Integer read GetConnectionIndex;
    property OnCoonnectionListChanged: TConnectionListChangedEvent read FConnectionListChanged write FConnectionListChanged;

    constructor Create;
    function Close: Boolean;

    function OpenConnection(FileName: String; var Msg: TStatusMessages): Integer;
    function CloseConnectionByIndex(Index: Integer; var Msg: TStatusMessages): Boolean; overload;
    function CloseConnection(ID: Integer; var Msg: TStatusMessages): Boolean; overload;
    function CloseConnection(FileName: String; var Msg: TStatusMessages): Boolean; overload;
    function FileOpened(FileName: String): Integer;
  published
  end;


var
  ConManager: TConnectionManager;


implementation
uses
  SysUtils, Dialogs;

(*
 Implementation of TConnectionManager
*)


function TConnectionManager.GetConnectionCount: Integer;
begin
  Result := Length(FConnections);
end;

function TConnectionManager.GetConnectionIndex(ConnectionID: Integer): Integer;
var
  i: Integer;
begin
  Result := -1;
  if Count > 0 then
    for i := 0 to Count - 1 do
      if ConnectionByIndex[i].ConnectionID = ConnectionID then
      begin
        Result := i;
        Break;
      end;
end;

function TConnectionManager.GetConnection(ConnectionID: Integer): TDataAccess;
var
  i: Integer;
begin
  Result := nil;
  if Length(FConnections) > 0 then
  begin
    for i := 0 to High(FConnections) do
    begin
      if FConnections[i].ConnectionID = ConnectionID then
      begin
        Result := FConnections[i];
        Break;
      end;
    end;
    if i = Length(FConnections) then
      ShowMessage('Couldn''t find specified ConnectionID (' +
          IntToStr(ConnectionID) + '). Please contact developer!!!');
  end;
end;


function TConnectionManager.GetConnectionByIndex(Index: Integer): TDataAccess;
begin
  Result := nil;
  if index < Length(FConnections) then
  begin
    Result := FConnections[index];
  end;
end;

constructor TConnectionManager.Create;
begin
  inherited;
  FLastID := 0;
end;

function TConnectionManager.Close: Boolean;
begin
  Result := False;
  if Length(FConnections) > 0 then
    Exit;

  inherited;
end;



function TConnectionManager.OpenConnection(FileName: String; var Msg: TStatusMessages): Integer;
var
  i: Integer;
  ext: String;
  backend: TDataBackend;
  CreateMsg: TStatusMessages;
begin
  Msg := SM_UnknownError;
  Result := -1;

  if Length(FConnections) > 0 then
  begin
    for i := 0 to High(FConnections) do
    begin
      if FConnections[i].FileName = FileName then
      begin
        Result := FConnections[i].ConnectionID;
        Msg := SM_AlreadyOpened;
        Exit;
      end;
    end;
  end;

  if not FileExists(FileName) then
  begin
    Msg := SM_FileNotFound;
    Exit;
  end;

  ext := UpperCase(ExtractFileExt(FileName));

  if ext = '.OLDB' then
    backend := DB_ADB
  else if ext = '.DAT' then
    backend := DB_ONI
  else if ext = '.ONI' then
    backend := DB_ONISPLIT
  else
  begin
    Msg := SM_UnknownExtension;
    Exit;
  end;

  SetLength(FConnections, Length(FConnections) + 1);
  i := High(FConnections);
  case backend of
    DB_ONI:
      FConnections[i] := TAccess_OniArchive.Create(FileName, FLastID + 1, CreateMsg);
    DB_ADB:
      FConnections[i] := TAccess_OUP_ADB.Create(FileName, FLastID + 1, CreateMsg);
    DB_ONISPLIT:
      FConnections[i] := TAccess_OniSplitArchive.Create(FileName, FLastID + 1, CreateMsg);
  end;

  if CreateMsg = SM_OK then
  begin
    FLastID := FConnections[i].ConnectionID;
    Result := FLastID;
    Msg := SM_OK;
  end
  else
  begin
    FConnections[i].Close;
    FConnections[i] := nil;
    SetLength(FConnections, Length(FConnections) - 1);
    Msg := CreateMsg;
  end;
end;


procedure TConnectionManager.RemoveConnection(ArrayIndex: Integer);
var
  i: Integer;
begin
  if Length(FConnections) > 1 then
  begin
    for i := ArrayIndex to High(FConnections) - 1 do
    begin
      FConnections[i] := FConnections[i + 1];
    end;
  end;
  SetLength(FConnections, Length(FConnections) - 1);
end;

function TConnectionManager.CloseConnectionByIndex(Index: Integer; var Msg: TStatusMessages): Boolean;
begin
  Msg := SM_UnknownError;
  Result := False;

  if Index < Length(FConnections) then
  begin
    FConnections[Index].Close;
    RemoveConnection(Index);
    Msg := SM_OK;
    Result := True;
  end;
end;

function TConnectionManager.CloseConnection(ID: Integer; var Msg: TStatusMessages): Boolean;
var
  i: Integer;
begin
  Msg := SM_UnknownError;
  Result := False;

  if Length(FConnections) > 0 then
  begin
    for i := 0 to High(FConnections) do
    begin
      if FConnections[i].ConnectionID = ID then
      begin
        FConnections[i].Close;
        RemoveConnection(i);
        Msg := SM_OK;
        Result := True;
        Exit;
      end;
    end;
  end;
end;

function TConnectionManager.CloseConnection(FileName: String; var Msg: TStatusMessages): Boolean;
var
  i: Integer;
begin
  Msg := SM_UnknownError;
  Result := False;

  if Length(FConnections) > 0 then
  begin
    for i := 0 to High(FConnections) do
    begin
      if FConnections[i].FileName = FileName then
      begin
        FConnections[i].Close;
        RemoveConnection(i);
        Msg := SM_OK;
        Result := True;
        Exit;
      end;
    end;
  end;
end;


function TConnectionManager.FileOpened(FileName: String): Integer;
var
  i: Integer;
begin
  Result := -1;
  if Length(FConnections) > 0 then
    for i := 0 to High(FConnections) do
      if FConnections[i].FileName = FileName then
      begin
        Result := FConnections[i].ConnectionID;
        Exit;
      end;
end;


initialization
  ConManager := TConnectionManager.Create;
finalization
  ConManager.Free;
end.
