// Reconcile DEP-5 debian/copyright to licensecheck
//
// Copyright : 2023-2025 P Blackman
// License   : BSD-2-clause
//

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

Uses cmem, StrUtils, SysUtils, Process, Classes, exclude, support, dep5,
     gpl, gpla, spdx, spdx2, dotzero, apache, gfdl, ntprsa, eclipse, psf,
     andor, options, appstream, rstrings, gettext;

procedure LoadSource;
var C, Posn     : Integer;
    OK          : Boolean;
    Line, S1    : AnsiString;
    SourceList  : tStringList;
begin
    if not Option_Struct then
    begin
        Writeln;
        Writeln (rsPST + '  ....'); // Parsing Source Tree
    end;

    OK := RunCommand('/usr/libexec/lrc-find', ['.'], S1,  [poUsePipes, poWaitOnExit]);

    if not OK then
        writeln (rsFps)

         // Failed to parse source tree
    else
    begin
        MangleName (S1);
        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 : String;
    LicenseList : tStringList;

begin
    if not Option_Struct then
        Writeln (rsRl + ' licensecheck ....');

    if Option_SPDX then
        OK := RunCommand('/usr/libexec/lrc-lc', ['spdx'], S,  [poUsePipes, poWaitOnExit])
    else
        OK := RunCommand('/usr/libexec/lrc-lc', ['debian'], S,  [poUsePipes, poWaitOnExit]);

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

        // Unmangle filenames
        for Count := 0 to High (MyFiles) do
            Unmanglename (MyFiles[Count].Fname);

        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, []);

            Count := 0;
            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
            begin
                if EndsStr ('appdata.xml' , FileName)
                or EndsStr ('metainfo.xml', FileName) then
                    License := GetMetadataLicense (FileName);

                MyFiles[Count].Actual := License;
            end
            else
                Writeln (FileName,' ' + rshul + ' ', License); // has unused license
        end;
        LicenseList.Free;
    end;
end;


procedure Compare;
var F : tFileLic;
    Header,
    GotOne,
    MisMatch,
    FalsePositive : Boolean;
    last_Dep5,
    Last_Actual : String;
begin
    Header      := False;
    GotOne      := False;
    MisMatch    := False;
    Last_Dep5   := '';
    Last_Actual := '';

    for F in MyFiles do
        with F do
            if (Actual = '') then
                // Nothing to see here
            else
            begin
                MisMatch := not SameText(Dep5, Actual);
                FalsePositive := false;

                if MisMatch and not IgnoreFile (Fname) then
                    FalsePositive :=
                           CheckGPL     (Fname, Dep5, Actual)
                        or CheckGPLa    (Fname, Dep5, Actual)
                        or CheckSPDX    (Fname, Dep5, Actual)
                        or CheckSPDX2   (Fname, Dep5, Actual)
                        or CheckApache  (Fname, Dep5, Actual)
                        or CheckGFDL    (Fname, Dep5, Actual)
                        or CheckEclipse (Fname, Dep5, Actual)
                        or CheckPSF2    (Fname, Dep5, Actual)
                        or CheckDotZero (Dep5, Actual)
                        or CheckNTPRSA  (Dep5, Actual)
                        or CheckANDOR   (Dep5, Actual)
                        or ContainsStr (Actual, 'Autoconf-data');

                if not IgnoreFile (Fname)
                and (Option_Long or MisMatch and not FalsePositive) then
                begin
                   if not Header and not Option_Struct then
                    begin
                        Writeln ('d/copyright      | licensecheck');
                        Writeln;
                        Header := True;
                    end;

                    if Option_Terse and (Dep5 = last_Dep5) and (Actual = Last_Actual) then
                        // skip this file
                    else
                    if Option_Struct then
                    begin
                        Writeln (Dep5);
                        Writeln (Actual);
                        Writeln (FName);
                        Writeln;
                    end
                    else
                        Writeln (PadRight(Dep5,17), '| ', PadRight(Actual,17), ' ',FName);

                    Last_Dep5   := Dep5;
                    Last_Actual := Actual;
                    GotOne      := GotOne or (MisMatch and not FalsePositive);
                end;
            end;

    if GotOne then
    begin
        Writeln;
        Halt (3);
    end
    else
    if not Option_Struct then
        Writeln (rsNdf); // No differences found
end;


begin
    TranslateResourcestrings('/usr/share/lrc/i18n/%s.mo');
    GetOptions;

    if Option_Help then
        ShowHelp
    else
    if Option_Version then
        ShowVersions
    else
    if not FileExists ('debian/copyright') then
    begin
        Writeln (rsCff + '; debian/copyright');
        Writeln;
        ShowHelp;
        Halt (1);
    end
    else
    begin
        if not Option_Struct then
            ShowVersions;

        LoadSource;

        if CopyRightFile then // Parse debian/copyright
        begin
            LoadExcludes;   // Load exclusions from usr/share & debian/
            LicenseCheck;   // Get licenses from licensecheck
            Compare;        // Do the check
        end
        else
            Halt (1);
    end;
end.
