program slackbuilder;

{$mode objfpc}

uses
  Sysutils,
  BaseUnix,
  Unix;

const
  RsyncBin: String = 'rsync -r --stats -h --ignore-existing -c -z ';
  WgetBin: String = 'wget -nc ';
  InstallBin: String  = 'upgradepkg --install-new --reinstall ';
  Release: String  = '0.2.2';


procedure buildPkg(Path: String; Name: String; TempDir: String; Force: Boolean);

var
   Tarball: String;
   Url: String;
   S: Longint;
   A: String;
   Readme: TextFile;
   InfoFile: TextFile;
   Line: String;
   sb: String;
   sbCmd: String;

begin
     // Workaround for compiler (?)
     S := 0;
     if (S <> 0) then
        S := 0;


     sb := Path + Name + '.SlackBuild';
     sbCmd :=
           'cd ' +
           Path +
           ' && TAG=sb TMP=' +
           TempDir +
           ' OUTPUT=' + '~ ' +
           sb;

     AssignFile(Readme, Path + 'README');
     Reset(Readme);
     repeat
           Readln(Readme, Line);
           Writeln('# ' + Line);
     until(EOF(Readme));
     CloseFile(Readme);

     If (Force = False) then
        begin
             Writeln ('Install package "' + Name + '"? (y|n)');
             Write ('>');
             Readln (A);
        end
     else
         A := 'y';

     If (A = 'y') then
        begin
             AssignFile(InfoFile, Path + Name + '.info');
             Reset(InfoFile);
             repeat
                   Readln(InfoFile, Line);

                   If (Pos ('DOWNLOAD=', Line) <> 0) then
                      begin
                           Url := StringReplace(
                               StringReplace(
                               StringReplace(
                                             Line,
                                             'DOWNLOAD="',
                                             '',
                                             [rfReplaceAll, rfIgnoreCase]
                               ),
                               '"',
                               '',
                               [rfReplaceAll, rfIgnoreCase]
                           ),
                           '\',
                           '',
                           [rfReplaceAll, rfIgnoreCase]
                           );
                           Tarball :=  (ExtractFileName(Url));
                           S := fpSystem (
                             WgetBin +
                             Url +
                             ' -O ' + Path + Tarball
                           );

                           S := fpSystem ('chmod +x ' + sb);
                           S := fpSystem (sbCmd);
                           S := fpSystem (
                             'rm -fr ' +
                             TempDir +
                             ' &> /dev/null'
                           );
                           S := fpSystem (
                             'rm -fr ' + Path + Tarball + ' &> /dev/null'
                           );
                           S := fpSystem (InstallBin + '~/' + Name + '*sb.tgz');

                      end;

             until(EOF(InfoFile));
             CloseFile(InfoFile);
        end;
end;

procedure installPkg(
  RootDir: String; V: String; Pkg: String; TempDir: String; Force: Boolean
);

var
   Info : TSearchRec;
   Count : Longint;
   I : TSearchRec;
   C : Longint;
   Pattern1: String;
   Pattern2: String;
   Path: String;
   Dir: String;

Begin
     Count := 0;
     Pattern1 := RootDir + '/' + V + '/*';

     If (FindFirst (Pattern1, faAnyFile and faDirectory, Info) = 0) then
        begin
             Repeat
             Inc(Count);
             With Info do
             begin
                  If (Attr and faDirectory) = faDirectory then
                  begin
                       Pattern2 :=
                                RootDir +
                                '/' + V +
                                '/' + Name +
                                '/*' + Pkg + '*';
                       Dir := Name;
                       C := 0;
                       If (FindFirst (
                          Pattern2,
                          faAnyFile and faDirectory,
                          I
                       ) = 0) then
                       begin
                            Repeat
                                  Inc(C);
                                  With I do
                                  begin
                                       If (
                                          (Attr and faDirectory) = faDirectory
                                       ) then
                                          begin
                                               Path :=
                                                    RootDir +
                                                    '/' + V +
                                                    '/' + Dir +
                                                    '/' + Name + '/';
                                               Writeln (
                                                       '# ' +
                                                       Name +
                                                       ' (' + Dir + ')'
                                               );
                                               buildPkg (
                                                        Path,
                                                        Name,
                                                        TempDir,
                                                        Force
                                               );
                                          end;
                                  end;
                            Until FindNext(I) <> 0;
                       end;
                       FindClose(I);
                  end;
             end;
             Until FindNext(Info) <> 0;
        end;
     FindClose(Info);
     Writeln ();

end;

procedure findPkg(
  RootDir: String;
  V: String;
  Pkg: String;
  Install: Boolean;
  TempDir: String;
  Force: Boolean
);

var
   Info : TSearchRec;
   Count : Longint;
   I : TSearchRec;
   C : Longint;
   P : Longint;
   Pattern1: String;
   Pattern2: String;

Begin
     Count := 0;
     P := 0;
     Pattern1 := RootDir + '/' + V + '/*';

     If (FindFirst (Pattern1, faAnyFile and faDirectory, Info) = 0) then
        begin
             Repeat
             Inc(Count);
             With Info do
             begin
                  If (Attr and faDirectory) = faDirectory then
                  begin
                       Pattern2 :=
                       RootDir + '/' + V + '/' + Name + '/*' + Pkg + '*';
                       C := 0;
                       If (
                          FindFirst (
                                    Pattern2,
                                    faAnyFile and faDirectory,
                                    I
                          ) = 0
                       ) then
                       begin
                            Repeat
                                  Inc(C);
                                  With I do
                                  begin
                                       If (
                                          (Attr and faDirectory) = faDirectory
                                       ) then
                                          begin
                                               Inc(P);
                                               Write(P);
                                               Writeln (': ' + Name);
                                          end;
                                  end;
                            Until FindNext(I) <> 0;
                       end;
                       FindClose(I);
                  end;
             end;
             Until FindNext(Info) <> 0;
        end;

     FindClose(Info);
     Writeln ('Found ', P, ' matches.');
     if (P > 0) and (Install = True) then
        begin
             Writeln();
             installPkg(RootDir, V, Pkg, TempDir, Force);
        end ;
end;

var
   Slackware: TextFile;
   Version: String;
   V: String;
   Home: String;
   User: String;
   Mirror: String;
   Temp: String;
   RootDir: String;
   TempDir: String;
   Pkg: String;
   S: Longint;
   Force: Boolean = False;


begin

     // Workaround for compiler (?)
     S := 0;
     if (S <> 0) then
        S := 0;

     // Check Slackware version
     AssignFile(Slackware, '/etc/slackware-version');
     Reset(Slackware);
     repeat
           Readln(Slackware, Version);
     until(EOF(Slackware));
     CloseFile(Slackware);

     If (Pos ('13.37', Version) <> 0) then
        V := '13.37'
     Else If (Pos ('14.0', Version) <> 0) then
        V := '14.0'
     Else If (Pos ('14.1', Version) <> 0) then
        V := '14.1'
     Else If (Pos ('14.2', Version) <> 0) then
        V := '14.2'
     Else If (Pos ('15.0', Version) <> 0) then
        V := '15.0'
     else
         begin
              Writeln('Unknown Slackware version. Bye!');
              Halt;
         end;
     Mirror := 'rsync://rsync.slackbuilds.org/slackbuilds/' + V;

     // Check user
     User := fpGetenv('USER');
     If (User <> 'root') then
        begin
              Writeln('Try as root!');
              Halt;
        end;

     // Help
     If
        (Length(ParamStr(1)) < 1) or
        (ParamStr(1) = 'help') or (
                     (ParamStr(1) <> 'find') and
                     (ParamStr(1) <> 'sync') and
                     (ParamStr(1) <> 'install') and
                     (ParamStr(1) <> 'force-install') and
                     (ParamStr(1) <> 'version')
        ) then
        begin
              Writeln('Usage:');
              Writeln('     slackbuilder sync');
              Writeln('     slackbuilder {find|install|force-install} PACKAGE');
              Writeln('     slackbuilder help');
              Writeln('     slackbuilder version');
              Halt;
        end;

     // Version
     If(Length(ParamStr(1)) < 1) or (ParamStr(1) = 'version') then
        begin
              Writeln(Release);
              Halt;
        end;

     // Settings
     Home := fpGetenv('HOME');
     Temp := IntToStr(Random(1000000)) ;
     RootDir := Home + '/.slackbuilder';
     TempDir := RootDir + '/' + Temp;

     // Start
     write ('SlackBuilder ' + Release);
     Writeln (' (Slackware Linux ' + V + ')');
     Writeln ();

     // Make work directory
     If (DirectoryExists(RootDir) = False) then
        Mkdir (RootDir);

     // Main flow
     // Sync
     If(ParamStr(1) = 'sync') then
        begin
              Writeln('Syncing ' + V + ' branch from slackbuilds.org...');
              S := fpSystem (RsyncBin + Mirror + ' ' + RootDir);
              Halt;
        end;

     // Find
     If(ParamStr(1) = 'find') then
        begin
              If(length(ParamStr(2)) > 0) then
                 begin
                      Pkg := ParamStr(2);
                      Writeln ('Search results for "' + Pkg + '":');
                      findPkg(RootDir, V, Pkg, False, TempDir, Force);
                      Halt;
                 end;
        end;

     // Install
     If(ParamStr(1) = 'install') or (ParamStr(1) = 'force-install') then
        begin
              If(length(ParamStr(2)) > 0) then
                 begin

                      if (ParamStr(1) = 'force-install') then
                         Force := True;
                      Pkg := ParamStr(2);
                      findPkg(RootDir, V, Pkg, True, TempDir, Force);
                      Halt;
                 end;
        end;



end.
