unit uSendManyFilesInChunks;
{< this unit is to send many files in chunks;

On Create we have

     if (AOwner is TVisualFrame_HTTP)  then
     VisualFrame_HTTP:=(AOwner as TVisualFrame_HTTP);

     so be carefull here - give correct link

}

interface

uses
   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
   Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,Contnrs,uSendFileInChunks,
   uSendFileInChunks2,
   Vcl.Buttons, System.SyncObjs;

type
  TSendManyFilesInChunks = class(TDataModule)
  private
       { Private declarations }

    FUploadThreadsOL:TObjectList;
    FUploadFrameOL:TObjectList;


    FUploadFrameNameNumber:Integer;

    FSendFileInChunks:TSendFileInChunks;
    FSendFileInChunks2:TSendFileInChunks2;

    FFilePathesToSend:TStringList;
    {<FilePathes of Files to be send on Server}

    FCurrrentThreadsCount:integer;
    FMaxThreadsCount:integer;

    FIsKeep2Share:Boolean;


    FVisualMode:boolean;


    FExecuteCS:TCriticalSection;
    FPropertiesCS:TCriticalSection;




    procedure FOnUploadFrameButtonClick(Sender: TObject);


  public
    { Public declarations }



    constructor Create(AOwner:TComponent); override;
    destructor Destroy; override;


    procedure SendFilesOnServer(AFilePathes: TStringList);
    {<SendFilesOnServer}

    function IsSomeThreadsNotFinished:Boolean;

    property IsKeep2Share:Boolean read FIsKeep2Share write FIsKeep2Share;
    property VisualMode:boolean read FVisualMode write FVisualMode;
    property SendFileInChunks:TSendFileInChunks read FSendFileInChunks
    write FSendFileInChunks;
    property SendFileInChunks2:TSendFileInChunks2 read FSendFileInChunks2
    write FSendFileInChunks2;

  end;

//var
//  SendManyFilesInChunks: TSendManyFilesInChunks;



implementation

{%CLASSGROUP 'Vcl.Controls.TControl'}

uses uVisualFrame,uSendFileInChunksThread,uUploadFrame;
var VisualFrame_HTTP_UnitVar:TVisualFrame_HTTP;

{$R *.dfm}

{ TSendManyFilesInChunks }

constructor TSendManyFilesInChunks.Create(AOwner: TComponent);
begin
  inherited;


      if (AOwner is TVisualFrame_HTTP)  then
      VisualFrame_HTTP_UnitVar:=(AOwner as TVisualFrame_HTTP);

//      FSendFileInChunks:=TSendFileInChunks.Create(VisualFrame_HTTP);

      FUploadFrameNameNumber:=0;


      FUploadThreadsOL:=TObjectList.Create;
      FUploadThreadsOL.OwnsObjects:=true; // threads will be destroyed automatically

      FUploadFrameOL:=TObjectList.Create;
      FUploadFrameOL.OwnsObjects:=false;


      FFilePathesToSend:=TStringList.Create;
      FMaxThreadsCount:=5;

      FExecuteCS:=TCriticalSection.Create;
      FPropertiesCS:=TCriticalSection.Create;


end;

destructor TSendManyFilesInChunks.Destroy;
begin

FreeAndNil(FUploadThreadsOL);
FreeAndNil(FUploadFrameOL);
FreeAndNil(FFilePathesToSend);
FreeAndNil(FExecuteCS);
FreeAndNIl(FPropertiesCS);



  inherited;
end;








procedure TSendManyFilesInChunks.FOnUploadFrameButtonClick(Sender: TObject);
var
  i: integer;
begin

// identificating sender thread
 if (Sender is tbitbtn) then

  if ( (Sender as tbitbtn).Parent is TUploadFrame ) then

  with ( (Sender as tbitbtn).Parent as TUploadFrame ) do begin

    for i:= FUploadThreadsOL.Count-1 downto 0  do
     begin

      if Guidstring=TSendFileInChunksThread(FUploadThreadsOL[i]).Guidstring  then

        // terminating sender thread
        begin

          if not TSendFileInChunksThread(FUploadThreadsOL[i]).Finished then
          begin

          VisualFrame_HTTP_UnitVar.IdHTTP.Disconnect;
          TSendFileInChunksThread(FUploadThreadsOL[i]).Terminate;
          TSendFileInChunksThread(FUploadThreadsOL[i]).WaitFor;
          //TSendFileInChunksThread(FUploadThreadsOL[i]).Free; // Mistake ! FUploadThreadsOL owns objects

          FUploadThreadsOL.Delete(i);


          end;


          ShowMessage('Загрузка прекращена');


         // (FUploadFrameOL.Delete(i));
          // delete also other UploadFrame
          //((Sender as tbitbtn).Parent as TUploadFrame ).Free;

        end;


     end;


  end;


end;




function TSendManyFilesInChunks.IsSomeThreadsNotFinished: Boolean;

var j:integer;

begin

if FUploadThreadsOL.Count=0 then

begin
Result:=false;
Exit;
end;



Result:=false;

for j:=FUploadThreadsOL.Count-1 downto 0 do begin

                    if ( Assigned(TSendFileInChunksThread(FUploadThreadsOL[j])) )

                    and not

                    ( TSendFileInChunksThread(FUploadThreadsOL[j]).Finished ) then

                    begin

                    Result:=true; // Some thread is working
                    Break;


                    end;

end;





end;

procedure TSendManyFilesInChunks.SendFilesOnServer(AFilePathes: TStringList);
var

  I,j,k: Integer;

  newguid:TGUID;
  newguidstring:string;


begin



  // Deleting finished threads
  for j:=FUploadThreadsOL.Count-1 downto 0 do begin

                    if ( Assigned(TSendFileInChunksThread(FUploadThreadsOL[j])) )

                    and

                    ( TSendFileInChunksThread(FUploadThreadsOL[j]).Finished )

                      then

                      begin

                      if FVisualMode  then
                      begin



                       // clearing FUploadFrameOL from finished ones...
                       for i := FUploadFrameOL.Count-1 downto 0  do
                         begin

                          if TSendFileInChunksThread(FUploadThreadsOL[j]).Guidstring=
                             TUploadFrame(FUploadFrameOL[i]).Guidstring then

                             TUploadFrame(FUploadFrameOL[i]).Free;



                         end;

                      end;

                      FUploadThreadsOL.Delete(j);

                      end;



  end;



// Checking Number of Threads

FCurrrentThreadsCount:=FUploadThreadsOL.Count;

 if  (FCurrrentThreadsCount+AFilePathes.Count>FMaxThreadsCount)

  then

     begin
     ShowMessage('Превышено максимально возможное число ('+
     FMaxThreadsCount.ToString+
     ') одновременно загружаемых файлов. Попробуйте загрузить меньшее число файлов');
     Exit;
     end;









    for I := 0 to AFilePathes.Count-1 do
     begin

       Createguid(newguid);
       newguidstring:=newguid.ToString;

       if FVisualMode  then

       begin
            // Creating upload frames...

            j:=FUploadFrameOL.Add(TUploadFrame.Create(Self));

            with TUploadFrame(FUploadFrameOL[j]) do begin

              Name:='UploadFrame'+FUploadFrameNameNumber.ToString;
              Guidstring:=newguidstring;  // Objects are connected through guid
              Parent:=VisualFrame_HTTP_UnitVar.sbUploads;
              Align:=alTop;
              lFileName.Caption:=ExtractFileName(AFilePathes[i]);

              bAction.OnClick:=FOnUploadFrameButtonClick;



              Show;
              Inc(FUploadFrameNameNumber);

            end;
       end;



          //Creating Threads

           k:=FUploadThreadsOL.Add(TSendFileInChunksThread.Create(true));

           with TSendFileInChunksThread(FUploadThreadsOL[k]) do begin

           VisualFrame:=VisualFrame_HTTP_UnitVar;

           IsKeep2Share:=FIsKeep2Share;

           //SendFileInChunks:=FSendFileInChunks;
           SendFileInChunks2:=FSendFileInChunks2;

           TSendFileInChunksThread(FUploadThreadsOL[k]).
           IsKeep2Share:=FIsKeep2Share;

           FreeOnTerminate:=false; // !!!

           FilePath:=AFilePathes[i];

           Guidstring:=newguidstring; // Objects are connected through guid

           if FVisualMode  then
            begin
            UploadFrame:=TUploadFrame(FUploadFrameOL[j]);

            UploadFrameOL:=FUploadFrameOL;
            UploadThreadOL:=FUploadThreadsOL;
            end;



           Start;

           end;


       end;





//  VisualFrame_HTTP.Repaint;
//  VisualFrame_HTTP.Refresh;
//  VisualFrame_HTTP.Realign;

//  VisualFrame_HTTP.sbUploads.Repaint;
//  VisualFrame_HTTP.sbUploads.Refresh;
    VisualFrame_HTTP_UnitVar.sbUploads.Realign;


end;


end.
