program DCleaner;

{$APPTYPE CONSOLE}

uses
  MaskUtils in 'MaskUtils.pas';


function GetDesktopPath(): string;
var s:  string;
begin
  SetLength(s, MAX_PATH);
  if not SHGetSpecialFolderPath(0, PChar(s), 0, true)
  then s := '';
  result := PChar(s);
end;

procedure FindClose(var F: TSearchRec);
begin
  if F.FindHandle <> INVALID_HANDLE_VALUE then
  begin
    MaskUtils.FindClose(F.FindHandle);
    F.FindHandle := INVALID_HANDLE_VALUE;
  end;
end;

Function TestWrite(Dir: String): Boolean;
var F: File;
begin
  If Dir[Length(Dir)] <> '\' Then Dir := Dir + '\';
  AssignFile(F, Dir + '%temp%');
{$I-}
  Rewrite(F, 1);
{$I+}
  Result := IOResult = 0;
  CloseFile(F);
  If Result Then DeleteFile(PChar(Dir + '%temp%'));
end;

var
  Console:    Boolean = False;
  S:          String;
  Mask:       String;
  M:          Array of PChar;
  iDir, oDir: String;
  n:          Integer;
  SR:         TSearchRec;
  MDir:       Boolean = False;
  //DD:         Array of String;

Procedure WriteLnC(S: String);
begin
  If Console Then WriteLn(S);
end;

function RemoveDir(const Dir: string): Boolean;
begin
  Result := RemoveDirectory(PChar(Dir));
end;

Function ExtractParamValue(S: String): String;
begin
  SetLength(Result,Length(S)-2);
  Move(S[3],Result[1],Length(Result));
end;

Function MCheck(S: String): Boolean;
var i: Integer;
begin
  Result := True;
  For i:=0 To High(M) do
    If StrSatisfy(S, M[i]) Then Exit;
  Result := False;
end;

Procedure GetMaskas;
var i, Count: Integer; Flag: Boolean;
begin
  Count := 0;
  Flag  := False;
  For i := 1 To Length(Mask) do
  begin
    If (Mask[i] <> ';') and not Flag Then
    begin
     Inc(Count);
     SetLength(M, Count);
     M[Count - 1] := @Mask[i];
     Flag := True;
    end else If Mask[i] = ';' Then
    begin
     Mask[i] := #0;
     Flag    := False;
    end;
  end;
end;

Procedure MoveFiles(const Dir, OutDir: String; MaskCheck: Boolean = True);
var SR: TSearchRec;
begin
  If FindFirst(Dir + '*',  faAnyFile XOR faDirectory, SR) <> 0 then Exit;
  Repeat
    If not MaskCheck or not MCheck(SR.Name) Then
    begin
      WriteLnC('Moved File:'#9 + SR.Name);
      MoveFile(PChar(Dir + SR.Name), PChar(OutDir + SR.Name));
    end;
  Until (FindNext(SR) <> 0);
  FindClose(SR);
end;

Procedure MoveFolders(const Dir, OutDir: String);
var SR: TSearchRec;
begin
  If FindFirst(Dir + '*', faDirectory, SR) <> 0 then Exit;
  Repeat
    If (SR.Name = '.') or (SR.Name = '..') or (SR.Attr <> faDirectory) Then
      Continue;
    If not DirectoryExists(OutDir + SR.Name) Then
      ForceDirectories(OutDir + SR.Name);
    MoveFiles(Dir + SR.Name + '\', OutDir + SR.Name + '\', False);
    WriteLnC('Moved Folder:'#9 + SR.Name);
    MoveFolders(Dir + SR.Name + '\', OutDir + SR.Name + '\');
    If not RemoveDir(Dir + SR.Name) Then
      WriteLnC('Can not delete a folder :(');
    //SetLength(DD, Length(DD)+1);
    //DD[High(DD)] := Dir + SR.Name;
  Until (FindNext(SR) <> 0);
  FindClose(SR);
end;

begin
  If ParamCount < 2 Then
    Exit;

  For n := 1 To ParamCount do
  begin
    S := ParamStr(n);
    If (Length(S) < 3) or (S[1] <> '-') Then continue;
    Case S[2] of
      'i': iDir := ExtractParamValue(S);
      'o': oDir := ExtractParamValue(S);
      'm': Mask := ExtractParamValue(S);
      'c': If S = '-console' Then Console := True;
    end;
  end;
  If not Console Then FreeConsole;


  WriteLnC('Directory Cleaner by HoRRoR o_O');
  WriteLnC('horror.cg@gmail.com ; ho-rr-or@mail.ru');
  WriteLnC('http://consolgames.ru/');
  If iDir = '' Then iDir := GetDesktopPath;
  If not DirectoryExists(iDir) Then
    Exit;
  If not DirectoryExists(oDir) Then
    ForceDirectories(oDir);
  If not DirectoryExists(oDir) Then
    Exit;
  If not TestWrite(oDir) Then
    Exit;


  If iDir[Length(iDir)] <> '\' Then
    iDir := iDir + '\';
  If oDir[Length(oDir)] <> '\' Then
    oDir := oDir + '\';

  WriteLnC('Input folder:'#9 + iDir);
  WriteLnC('Out folder:'#9 + oDir);
  WriteLnC('Maskas:    '#9 + Mask);

  GetMaskas;
  For n := 0 To High(M) do
  begin
    If M[n] = '\f' Then
    begin
      MDir := True;
      Break;
    end;
  end;

  MoveFiles(iDir, oDir);

  If not MDir Then
    MoveFolders(iDir, oDir);

  (*For n:=0 To High(DD) do
    If not RemoveDir(DD[n]) Then
      WriteLnC('Can not delete a folder ' + DD[n]); *)
end.
