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

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

Uses cmem, StrUtils, SysUtils, Process, Classes, exclude, support,
     dep5, gpl, spdx, dotzero, apache, gfdl, 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 : Boolean;
    last_Dep5,
    lc_Actual,
    Last_Actual : String;
begin
    Header := False;
    GotOne := False;
    Last_Dep5 := '';
    Last_Actual := '';

    for F in MyFiles do
        with F do
        begin
            lc_Actual := Actual; // Cannot update F components in for loop

            if (lc_Actual <> '') and (not SameText(Dep5, lc_Actual) or Option_Long) then
                if not IgnoreFile (Fname)
                and not CheckGPL    (Fname, Dep5, lc_Actual)
                and not CheckSPDX   (Fname, Dep5, lc_Actual)
                and not CheckApache (Fname, Dep5, lc_Actual)
                and not CheckGFDL   (Fname, Dep5, lc_Actual)
                and not CheckDotZero (Dep5, lc_Actual)
                and not ContainsStr (Actual, 'Autoconf-data')  // *** Exclude Autotools licenses ***
                or Option_Long and not IgnoreFile (Fname) then
                begin
                    if not Header and not Option_Struct then
                    begin
                        Writeln ('d/copyright      | licensecheck');
                        Writeln;
                        Header := True;
                    end;
                    GotOne := GotOne or not SameText(Dep5, lc_Actual);

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

                    Last_Dep5 := Dep5;
                    Last_Actual := lc_Actual;
                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.
