// 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, apache, options, appstream;

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

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

    if not OK then
        writeln ('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 ('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;

        // 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 CompareEnd (FileName, 'appdata.xml')
                or CompareEnd (FileName, 'metainfo.xml') then
                    License := GetMetadataLicense (FileName);

                MyFiles[Count].Actual := License;
            end
            else
                Writeln (FileName,' has unused license ', 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) or Option_Long)
                and (not CheckSPDX (Fname, Dep5, lc_Actual) or Option_Long)
                and (not CheckApache (Dep5, lc_Actual) or Option_Long)
                and not ContainsStr (Actual, 'Autoconf-data') then  // Exclude Autotools files
                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,16), '| ', PadRight(lc_Actual,16), ' ',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 ('No differences found');
end;


begin
    if not FileExists ('debian/copyright') then
    begin
        Writeln ('Cannot find the file; debian/copyright');
        Halt (1);
    end
    else
    begin
        GetOptions;

        if not Option_Struct or Option_Version then
            ShowVersions;

        if Option_Help then
            ShowHelp
        else
        if Option_Struct or not Option_Version then
        begin
            LoadSource;

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