// Reconcile DEP-5 debian/copyright to licensecheck report on source tree
//
// Copyright : 2023 P Blackman
// License   : BSD-2-clause
//

program lrc;
{$mode delphi}
{$linklib c}

Uses StrUtils, SysUtils, Process, Classes;

const WhiteSpace :  set of Char = [' ',Chr(9)]; // Space & Tab

type
    tFileLic =
    record
        FName,
        Dep5,
        Actual : AnsiString
    end;

var
    MyFiles : array of tFileLic;


procedure LoadSource;
var C, Posn     : Integer;
    OK          : Boolean;
    Line, S1,S2 : AnsiString;
    SourceList  : tStringList;
begin
    Writeln;
    Writeln ('Parsing Source Tree ....');
    OK := RunCommand('/usr/libexec/lrc-find', ['.'], S1,  [poUsePipes, poWaitOnExit]);

    if not OK then
        writeln ('Failed to parse source tree')
    else
    begin
        S2 := ReplaceStr (S1, ' ', '\'); // maybe spaces in filenames (segments then treated as separate files!)
        S1 := ReplaceStr (S2, ',', '"');
        SourceList := tStringList.Create;
        SourceList.text := S1;

        SetLength (MyFiles, SourceList.Count);
        for C := 0 to SourceList.Count -1 do
        begin
            Posn             := 3; // Strip leading ./
            Line             := SourceList.Strings[C];
            MyFiles[C].Fname := ExtractSubstr (Line, Posn, []);
            MyFiles[C].Dep5  := '';
            MyFiles[C].Actual:= '';
        end;

        SourceList.free;
    end;
end;


procedure LicenseCheck;
var L, Posn, Count : Integer;
    OK, Match : Boolean;
    Line, S,
    FileName,
    License : ansistring;
    LicenseList : tStringList;

begin
    Writeln ('Running licensecheck ....');
    OK := RunCommand('/usr/libexec/lrc-lc', [], S,  [poUsePipes, poWaitOnExit]);

    if not OK then
        writeln ('Failed to run licensecheck')
    else
    begin
        Writeln;
        LicenseList := tStringList.Create;
        LicenseList.text := s;
        Count := 0;

        for L := 0 to LicenseList.Count -1 do
        begin
            Line := LicenseList.Strings [L];
            Posn      := 4; // Strip leading .//
            FileName := ExtractSubstr (Line, Posn, [Chr(9)]);
            License  := ExtractSubstr (Line, Posn, []);

            Match    := FileName = MyFiles[Count].Fname;
            While not Match and (count < High (MyFiles)) do
            begin
                Count := Count +1;
                Match := FileName = MyFiles[Count].Fname;
            end;

            If match then
                MyFiles[Count].Actual := License
            else
                Writeln ('Unused license ', License);
        end;
        LicenseList.free;
    end;
end;

// These files often contain licenses for other files
function IgnoreFile (Fname : String) : Boolean;
var FullName, ShortName, FileExt : String;
begin
    Fullname := ExtractFileName(Fname);

    FileExt := ExtractFileExt (FullName);

    if FileExt = '' then
        Shortname := FullName
    else
        ShortName := ReplaceStr( Fullname, FileExt, '');

    result := ContainsText (ShortName, 'copyright') or
              ContainsText (ShortName, 'copying') or
              ContainsText (ShortName, 'license') or
              ContainsText (ShortName, 'readme') or
              ContainsText (ShortName, 'authors') or
              ContainsText (ShortName, 'about') or
              ContainsText (ShortName, 'appdata') or
              ContainsText (ShortName, 'metainfo') or
              ContainsText (ShortName, 'dep5');
end;

{$INCLUDE dep5.pp}
{$INCLUDE gpl.pp}

procedure Compare;
var F : tFileLic;
    GotOne : Boolean;
    S1,S2 : String;
begin
    GotOne := false;
    for F in MyFiles do
        with F do
            if (Actual <> '') and (CompareText(Dep5, Actual) <> 0) then
                if not IgnoreFile (Fname)
                and not CheckGPL (Fname, Dep5, Actual) then
                begin
                    if not GotOne then
                    begin
                        Writeln ('d/copyright     | licensecheck');
                        Writeln;
                    end;
                    GotOne := true;

                    S1 := ReplaceStr (Fname, '\', ' ');
                    S2 := ReplaceStr (S1, '"', ',');

                    Writeln (PadRight(Dep5,16), '| ', PadRight(Actual,16), ' ',S2);
                end;

    if GotOne then
    begin
        Writeln;
        Halt (3);
    end
    else
        Writeln ('No differences found');
end;


begin
    if not FileExists ('debian/copyright') then
    begin
        Writeln ('Cannot find the file; debian/copyright');
        Halt (1);
    end
    else
    begin
        LoadSource;    // Read in source tree

        if CopyRightFile then // Parse debian/copyright
        begin
            LicenseCheck;  // get licenses from licensecheck
            Compare;
        end
        else
            Halt (1);
    end;
end.
