' Gambas module file

Private $sRoot As String

Private $aComp As New String[]
Private $cComp As New Collection

Private $sVersion As String
Private $cPackage As Collection
Private $cFiles As Collection
Private $aDisable As String[]
Private $sDest As String
Private $aDscPackage As Collection[]
Private $dNow As Date

Private $sControlFile As String

Private $sTimeStamp As String
Private $sCommit As String
Private $cMerge As Collection
Private $bNoSharedObject000 As Boolean
Private $bNoLaFile As Boolean
Private $sBuildDepends As String

Private Sub AddIfNotExist(aStr As String[], sStr As String)

  If Not aStr.Exist(sStr) Then aStr.Add(sStr)

End

Private Sub LoadPackage(sPath As String) As Collection

  Dim hFile As File
  Dim sLine As String
  Dim iPos As Integer
  Dim cPackage As Collection

  cPackage = New Collection

  hFile = Open sPath For Read 
  For Each sLine In hFile.Lines
    sLine = Trim(sLine)
    If Not sLine Then Continue
    iPos = InStr(sLine, "=")
    If iPos = 0 Then Continue
    cPackage[Left(sLine, iPos - 1)] = UnQuote(Mid$(sLine, iPos + 1))
  Next
  Close #hFile

  Return cPackage

End

Private Sub InitComponents()

  Dim sPackage As String
  Dim sComp As String
  Dim hComp As CComponent
  Dim cPackage As Collection
  Dim sPath As String
  Dim sFile As String
  Dim sDesc As String
 
  $sRoot = File.Dir(File.Dir(File.Dir(Application.Path)))
  sDesc = Trim(File.Load("gambas-common-desc"))

  For Each sPackage In Dir("conf")
    
    If sPackage Ends "~" Then Continue
    cPackage = LoadPackage("conf" &/ sPackage)
    
    sComp = Mid$(sPackage, InStr(sPackage, "-") + 1)
    hComp = New CComponent
    hComp.Name = sComp
    hComp.Summary = cPackage["Summary"]
    If hComp.Summary Ends "." Then hComp.Summary = Left(hComp.Summary, -1)
    hComp.Description = sDesc & "\n\n" & cPackage["Description"]
    
    $cComp[sComp] = hComp
    $aComp.Add(sComp)

    If sComp Not Begins "gb-" Then Continue 
    sComp = Replace(sComp, "-", ".")
    
    hComp.Component = sComp
    hComp.Files.Add("usr/lib/gambas3/" & sComp & ".component")
    hComp.Files.Add("usr/share/gambas3/info/" & sComp & ".info")
    hComp.Files.Add("usr/share/gambas3/info/" & sComp & ".list")
    
  Next
  
  For Each sPath In RDir($sRoot)
    
    sFile = File.Name(sPath)
    If sFile Not Ends ".component" Then Continue
    
    If sFile = ".component" Then
      sComp = File.Name(File.Dir(sPath))
    Else If sFile Begins "gb." Then
      sComp = File.BaseName(sFile)
    Endif
    
    hComp = $cComp[Replace(sComp, ".", "-")]
    If Not hComp Then Continue

    If sFile = ".component" Then
      
      If Not hComp.Gambas Then
        
        hComp.Files.Add("usr/lib/gambas3/" & sComp & ".gambas")
        hComp.AddDepends($sRoot &/ sPath)
        If IsDir($sRoot &/ File.Dir(sPath) &/ ".hidden/control") Then hComp.AddControls()
        hComp.Gambas = True
        
      Endif
      
    Else If sFile Begins "gb." Then
      
      ' Gambas component included inside a native component
      If Dir(File.Dir($sRoot &/ sPath), "*.{c,cpp}").Count = 0 Then Continue
      
      ' 'gb.form.htmlview' has two alternatives source directories. Just one must be parsed.
      If Not hComp.Files.Exist("usr/lib/gambas3/" & sComp & ".so") Then
      
        hComp.Files.Add("usr/lib/gambas3/" & sComp & ".so")
        hComp.Files.Add("usr/lib/gambas3/" & sComp & ".so.0")
        hComp.Files.Add("usr/lib/gambas3/" & sComp & ".so.0.0.0")
        hComp.Files.Add("usr/lib/gambas3/" & sComp & ".la")
        hComp.AddDepends($sRoot &/ sPath)
        If IsDir($sRoot &/ File.Dir(sPath) &/ "control") Then hComp.AddControls()
        hComp.Native = True
        
        sPath = $sRoot &/ File.Dir(sPath) &/ File.BaseName(sPath)
        If Not hComp.Gambas And If Exist(sPath &/ ".project") Then
          
          hComp.Files.Add("usr/lib/gambas3/" & sComp & ".gambas")
          hComp.AddDepends($sRoot &/ sPath &/ ".component")
          If IsDir(sPath &/ ".hidden/control") Then hComp.AddControls()
          hComp.Gambas = True
  
        Endif
        
      Endif
      
    Endif

  Next
  
  $aComp.Sort()

End

Public Sub Main()

  Dim sDir As String
  Dim sVersion As String
  Dim sSrc As String
  Dim sName As String
  Dim cDefine As Collection
  
  InitComponents
  
  $dNow = Now
  $sVersion = Trim(File.Load($sRoot &/ "VERSION"))
  Exec ["git", "rev-parse", "HEAD"] To $sCommit
  $sCommit = Left($sCommit, 8)
  Exec ["git", "log", "-1", "--date=format:%Y%m%d", "--format=%ad"] To $sTimeStamp
  $sTimeStamp = Trim($sTimeStamp)
  
  ' ArchLinux
  
  InitSystem("archlinux")
  ParseFile("archlinux", "arch/PKGBUILD", "PKGBUILD")
  
  ' openSUSE

  InitSystem("opensuse")
  ParseFile("opensuse", "rpm/gambas-openSUSE.spec", "gambas-openSUSE_Tumbleweed.spec", ["version": "99"])
  InitSystem("opensuse")
  ParseFile("opensuse", "rpm/gambas-openSUSE.spec", "gambas-openSUSE_Leap_15.6.spec", ["version": "15.6"])
  ParseFile("opensuse", "rpm/gambas.rpmlintrc", "gambas-openSUSE.rpmlintrc")
  
  ' Fedora

  InitSystem("fedora")
  ParseFile("fedora", "rpm/gambas-Fedora.spec", "gambas-Fedora.spec", ["version": "99"])

  InitSystem("fedora")
  ParseFile("fedora", "rpm/gambas-Fedora.spec", "gambas-Fedora42.spec", ["version": "42"])
  ParseFile("fedora", "rpm/gambas.rpmlintrc", "gambas-fedora.rpmlintrc")
  '
  InitSystem("fedora")
  ParseFile("fedora", "rpm/gambas-Fedora.spec", "gambas-Fedora43.spec", ["version": "43"])
  ParseFile("fedora", "rpm/gambas.rpmlintrc", "gambas-fedora.rpmlintrc")
  '
  InitSystem("fedora")
  ParseFile("fedora", "rpm/gambas-Fedora.spec", "gambas-Fedora44.spec", ["version": "44"])
  ParseFile("fedora", "rpm/gambas.rpmlintrc", "gambas-fedora.rpmlintrc")

  ' Debian
  
  ParseFile("debian", "deb/changelog", $sRoot &/ ".obs/debian.changelog")
    
  For Each sVersion In ["debian-11", "debian-12", "debian-13", "debian-14", "ubuntu-20.04", "ubuntu-22.04", "ubuntu-24.04", "ubuntu-24.10", "ubuntu-25.04", "ubuntu-25.10", "ubuntu-26.04"]
  
    InitSystem("debian")
    
    sDir = Application.TempDir &/ "debian"
    Try Shell.RmDir(sDir)
    Try Mkdir sDir
    
    sSrc = "deb/debian"
    Shell.Copy("template" &/ sSrc, sDir)
    
    cDefine = ["version": sVersion]
    
    ParseFile("debian", sSrc &/ "control", sDir &/ "debian/control", cDefine)
    ParseFile("debian", sSrc &/ "rules", sDir &/ "debian/rules", cDefine)
    'ParseFile("debian", sSrc &/ "changelog", sDir &/ "debian/changelog", cDefine)
    
    Select Case sVersion
      Case Like "debian*"
        If sVersion = "debian-14" Then 
          sName = "Debian_Testing"
        Else
          sName = Replace(sVersion, "-", "_")
          sName = UCase(Left(sName)) & Mid$(sName, 2)
        Endif
      Case Like "ubuntu*"
        sName = Replace(sVersion, "-", "_")
        sName = "x" & UCase(Left(sName)) & Mid$(sName, 2)
      Default
        Error.Raise(sVersion & " not implemented")
    End Select
    
    Try Kill $sRoot &/ ".obs/debian-" & sName & ".tar.gz"
    Shell "cd " & Shell(sDir) & " && tar cfz " & Shell($sRoot &/ ".obs/debian-" & sName & ".tar.gz") & " ." Wait
    
    
    $sControlFile = "debian-" & sName & ".tar.gz"
    BrowseControlForDsc(sDir &/ "debian/control")
    ParseFile("debian", "deb/gambas.dsc", $sRoot &/ ".obs/gambas-" & sName & ".dsc", cDefine)
    
  Next
  
  Try Kill $sRoot &/ ".obs/gambas.dsc"
  Copy $sRoot &/ ".obs/gambas-Debian_11.dsc" To $sRoot &/ ".obs/gambas.dsc"

  Try Kill $sRoot &/ ".obs/debian.tar.gz"
  Copy $sRoot &/ ".obs/debian-Debian_11.tar.gz" To $sRoot &/ ".obs/debian.tar.gz"
  
  Print "Done."
  
End

Private Sub InitSystem(sSystem As String)

  $cPackage = New Collection
  $cFiles = New Collection
  $aDisable = ["all"]
  $cMerge = New Collection
  '$bNoSharedObject000 = sSystem <> "opensuse"
  $bNoSharedObject000 = False
  $bNoLaFile = sSystem = "debian"

End

Private Sub EvalExpression(sExpr As String, cDefine As Collection) As Boolean

  Dim aExpr As String[]
  Dim sValue As String
  Dim iComp As Integer
  Dim sOp As String

  aExpr = Split(sExpr, " ")
  If aExpr.Count = 1 Then
    If sExpr Ends "?" Then
      Return Not IsDisabled(Left(sExpr, -1))
    Else
      Return cDefine.Exist(sExpr)
    Endif
  Endif
  
  sValue = cDefine[aExpr[0]]
  
  If aExpr.Count = 3 Then
    sOp = aExpr[1]
    
    If sOp = "like" Then
    
      Return sValue Like aExpr[2]
    
    Else
      
      iComp = Comp(sValue, aExpr[2], gb.Natural)
      Select Case sOp
        Case "="
          Return iComp = 0
        Case "!="
          Return iComp <> 0
        Case ">"
          Return iComp > 0
        Case "<"
          Return iComp < 0
        Case ">="
          Return iComp >= 0
        Case "<="
          Return iComp <= 0
      End Select
      
    Endif
      
  Endif
  
  Error.Raise("Bad conditional expression")

End

Private Sub GetComponent(sComp As String) As CComponent

  Dim hComp As CComponent

  hComp = $cComp[Replace(sComp, ".", "-")]
  If Not hComp Then Error.Raise("Unknown component: " & sComp)
  Return hComp

End

Private Sub GetFiles(sComp As String) As String[]

  Dim aFiles As String[]
  Dim aComp As Variant[]
  Dim hComp As CComponent
  Dim sFile As String

  aFiles = New String[]

  aComp = $cMerge[sComp]
  If Not aComp Then aComp = [sComp]
    
  For Each sComp In aComp
  
    hComp = GetComponent(sComp)
    For Each sFile In hComp.Files
      If $bNoSharedObject000 Then
        If sFile Ends ".so.0.0" Then Continue
        If sFile Ends ".so.0.0.0" Then Continue 
      Endif
      If $bNoLaFile Then
        If sFile Ends ".la" Then Continue
      Endif
      aFiles.Add(sFile)
    Next
  
  Next
    
  Return aFiles.Sort()

End

Private Sub ParseFile(sSystem As String, sSrc As String, Optional sDest As String, cDefine As Collection)

  Dim sData As String
  Dim iPos As Integer
  Dim iPos2 As Integer
  Dim sResult As String
  Dim iPos3 As Integer
  Dim sCommand As String
  Dim sArg As String
  Dim sSubst As String
  Dim bSubst As Boolean
  Dim iCondLevel As Integer
  Dim iWaitLevel As Integer
  Dim sComp As String
  Dim bEatNewLine As Boolean
  Dim aComp As String[]
  Dim I As Integer
  Dim sPackage As String
  ' Dim bStop As Boolean

  ' If File.Name(sSrc) = "control" Then
  '   If cDefine["version"] = "debian-14" Then bStop = True
  ' Endif

  If Not sDest Then sDest = sSrc
  If sDest Not Begins "/" Then sDest = $sRoot &/ ".obs" &/ sDest
  $sDest = sDest
  
  If Not cDefine Then cDefine = New Collection

  Print "---- ["; sSystem; ":"; cDefine["version"]; "] Generating " & File.Name($sDest) & "..."

  sData = File.Load("template" &/ sSrc)
  
  Do
    
    Inc iPos

    If bEatNewLine Then
      iPos2 = InStr(sData, "\n", iPos)
      If IsSpace(Mid$(sData, iPos, iPos2 - iPos + 1)) Then iPos = iPos2 + 1
    Endif
    
    iPos2 = InStr(sData, "@{", iPos)
    
    If iPos2 = 0 Then Break
    
    iPos3 = InStr(sData, "}@", iPos2 + 1)
    If iPos3 = 0 Then Break
    
    If iWaitLevel = 0 Then sResult &= Mid$(sData, iPos, iPos2 - iPos)
    
    sCommand = Mid$(sData, iPos2 + 2, iPos3 - iPos2 - 2)
    iPos = InStr(sCommand, " ")
    If iPos Then
      sArg = RTrim(Mid$(sCommand, iPos + 1))
      sCommand = Left$(sCommand, iPos - 1)
    Else 
      sArg = ""
    Endif
    
    sSubst = ""
    bEatNewLine = False
    
    ' If bStop Then 
    '   Print "-------- "; sCommand;; sArg
    '   Print Mid$(sData, iPos2, 255)
    '   Print
    '   Stop
    ' Endif
    
    If sCommand Begins "--" And If sCommand Ends "--" Then
      
      ' Ignore comments
      bEatNewLine = True
      
    Else If sCommand = "endif" Then
      
      If iWaitLevel = iCondLevel Then iWaitLevel = 0
      Dec iCondLevel
      If iCondLevel < 0 Then Error.Raise("Unexpected @{endif}@")
      
      iPos = RInStr(sData, "\n", iPos2)
      If iPos = 0 Or If Not Trim(Mid$(sData, iPos + 1, iPos2 - iPos - 1)) Then bEatNewLine = True
    
    Else If sCommand = "else" Then
      
      If iWaitLevel = iCondLevel Then
        iWaitLevel = 0
      Else If iWaitLevel = 0 Then
        iWaitLevel = iCondLevel
      Endif
      bEatNewLine = True
      
    Else If iWaitLevel Then
      
      If sCommand = "if" Or If sCommand = "if-not" Then Inc iCondLevel
      Goto IGNORE_COMMAND
      
    Else If sCommand = "if" Then
      
      Inc iCondLevel
      If Not EvalExpression(sArg, cDefine) Then iWaitLevel = iCondLevel
      bEatNewLine = True
      
    Else If sCommand = "if-not" Then
      
      Inc iCondLevel
      If EvalExpression(sArg, cDefine) Then iWaitLevel = iCondLevel
      bEatNewLine = True
      
    Else
      
      If sCommand = "package" Then
        iPos = InStr(sArg, "\n")
        If iPos Then
          sPackage = Trim(Left(sArg, iPos - 1))
          If IsDisabled(sPackage) Then 
            Print "@{package} command ignored: '"; sPackage; "' is disabled."
            Goto IGNORE_COMMAND
          Endif
        Endif
      Endif
      
      Select Case sSystem
        
        Case "archlinux"
          bSubst = CommandArchLinux(sCommand, sArg, ByRef sSubst)
          
        Case "opensuse", "fedora"
          bSubst = CommandRpm(sCommand, sArg, ByRef sSubst)
        
        Case "debian", "ubuntu"
          bSubst = CommandDeb(sCommand, sArg, ByRef sSubst)
          
      End Select
      
      If bSubst Then
        
        Select Case sCommand
          
          Case "about"
            sSubst = "Generated by the 'gambas-package-config' tool on " & Date.ToRFC822($dNow)
          
          Case "version"
            sSubst = $sVersion
  
          Case "website-url"
            sSubst = "https://gambas.sourceforge.net"
            
          Case "git-url"
            sSubst = "https://gitlab.com/gambas/gambas"
            
          Case "git-repository"
            sSubst = "https://gitlab.com/gambas/gambas.git"
          
          Case "disable"
            For Each sComp In Split(sArg, " ")
              AddIfNotExist($aDisable, sComp)
            Next
            sSubst = ""
            bEatNewLine = True
      
          Case "enable"
            For Each sComp In Split(sArg, " ")
              iPos = $aDisable.Find(sComp)
              If iPos Then $aDisable.Remove(iPos)
            Next
            sSubst = ""
            bEatNewLine = True
            
          Case "merge"
            aComp = Split(sArg, " ")
            For I = 0 To aComp.Max
              sComp = aComp[I]
              GetComponent(sComp)
              If I Then AddIfNotExist($aDisable, sComp)
            Next
            $cMerge[aComp[0]] = aComp
            sSubst = ""
            bEatNewLine = True
      
          Case Else 
            sSubst = Mid$(sData, iPos2, iPos3 - iPos2 + 2)
            
        End Select
        
      Endif
      
    Endif
    
    sResult &= sSubst
    
  IGNORE_COMMAND:
    iPos = iPos3 + 1
    
  Loop

  sResult &= Mid$(sData, iPos)
  
  If iCondLevel Then Error.Raise("@{endif}@ command missing")
  
  File.Save(sDest, sResult)
  
End

Private Sub IsDisabled(sComp As String) As Boolean

  Dim I As Integer
  
  If Not $aDisable Then Return
  sComp = Replace(sComp, ".", "-")
  For I = 0 To $aDisable.Max
    If sComp Like $aDisable[I] Then Return True
  Next
  
End

Private Sub GetDependencies(sProject As String) As String[]

  Dim hFile As File
  Dim sLine As String
  Dim aComp As String[]
  Dim sComp As String

  aComp = New String[]
  
  hFile = Open sProject &/ ".project"
  For Each sLine In hFile.Lines
    If sLine Begins "Component=" Then
      sComp = Mid$(sLine, InStr(sLine, "=") + 1)
      If Not CComponent.IsExcluded(sComp) Then aComp.Add(sComp)
    Endif
  Next
  hFile.Close
  
  Return aComp.Sort()

End

Private Sub GetIDEDependencies() As String[]

  Dim aComp As String[]

  aComp = GetDependencies($sRoot &/ "app/src/gambas3")
  aComp.Insert(["runtime", "dev-tools", "gui-webview"], 0)
  If IsDisabled("gb-clipper2") Then 
    aComp.Add("gb-clipper")
  Else
    aComp.Add("gb-clipper2")
  Endif
  Return aComp

End

Private Sub GetAllDependencies(Optional bNoGui As Boolean) As String[]

  Dim aComp As String[]
  Dim sComp As String

  aComp = New String[]
  For Each sComp In $aComp
    If IsDisabled(sComp) Then Continue
    If bNoGui And If ComponentNeedsGUI(sComp) Then Continue
    aComp.Add(sComp)
  Next
  Return aComp

End

Private Sub CommandArchLinux(sCommand As String, sArg As String, ByRef sSubst As String) As String

  Dim aComp As String[]
  Dim I As Integer
  Dim iPos As Integer
  Dim sComp As String
  
  Select Case sCommand
    
    Case "package-version"
      sSubst = $sTimeStamp & "-" & $sCommit
  
    Case "package-list"
      aComp = New String[]
      For I = 0 To $aComp.Max
        If IsDisabled(Replace($aComp[I], "-", ".")) Then Continue
        aComp.Add("'gambas3-" & $aComp[I] & "'")
      Next
      sSubst = aComp.Join(" ")
      
    Case "package"
      
      If sArg Then
      
        iPos = InStr(sArg, "\n")
        If iPos = 0 Then Return True
        
        sCommand = Trim(Left(sArg, iPos - 1))
        sArg = Mid$(sArg, iPos + 1)
        
        If $cPackage.Exist(sCommand) Then Error.Raise(Subst("Package '&1' already declared", sCommand))
        $cPackage[sCommand] = True
        sSubst = MakeArchLinuxPackage(sCommand, sArg)
        
      Else
    
        sSubst = ""
        For Each sComp In $aComp
          sComp = Replace(sComp, "-", ".")
          If sComp Not Begins "gb." Then Continue
          If IsDisabled(sComp) Then Continue
          If $cPackage.Exist(sComp) Then Continue
          sSubst &= MakeArchLinuxPackage(sComp) & "\n\n"
        Next
        sSubst = RTrim(sSubst)
        
      Endif
    
    Case "desc"
      Try sSubst = Quote($cComp[sArg].Summary)
      
    Case "dependencies"
      
      If sArg = "ide" Then
        aComp = GetIDEDependencies()
      Else If sArg = "all" Then
        aComp = GetAllDependencies()
      Else If sArg = "nogui" Then
        aComp = GetAllDependencies(True)
      Else
        Return
      Endif
      
      For I = 0 To aComp.Max
        aComp[I] = "'gambas3-" & Replace(aComp[I], ".", "-") & "'"
      Next
      sSubst = aComp.Join(" ")
      
    Case Else 
      Return True
      
  End Select

End

Private Sub MakeArchLinuxPackage(sComp As String, Optional sArg As String) As String

  Dim aResult As New String[]
  Dim hComp As CComponent
  Dim sLine As String
  Dim sFile As String
  Dim aDepends As New String[]
  Dim sDepend As String
  Dim aLine As String[]
  
  hComp = $cComp[Replace(sComp, ".", "-")]
  If Not hComp Then Return
  
  aResult.Add("package_gambas3-" & Replace(sComp, ".", "-") & "() {")
  aResult.Add("  pkgdesc=" & Quote(hComp.Summary))
  
  If sArg Then
    For Each sLine In Split(sArg, "\n")
      sLine = Trim(sLine)
      aLine = Scan(sLine, "depends=(*)")
      If aLine.Count = 1 Then
        aDepends = Split(aLine[0], " ")
      Else
        aResult.Add(sLine)
      Endif
    Next
  Endif
  
  AddIfNotExist(aDepends, "'gambas3-runtime'")
  For Each sDepend In hComp.Depends
    AddIfNotExist(aDepends, "'gambas3-" & Replace(sDepend, ".", "-") & "'")
  Next
  aResult.Add("  depends=(" & aDepends.Join(" ") & ")")
  
  For Each sFile In GetFiles(hComp.Name)
    aResult.Add("  _install fakeinstall" &/ sFile)
  Next
  
  aResult.Add("}")
  
  Return aResult.Join("\n")

End

Private Sub CommandRpm(sCommand As String, sArg As String, ByRef sSubst As String) As String
  
  Dim aComp As String[]
  Dim I As Integer
  Dim iPos As Integer
  Dim sComp As String
  
  Select Case sCommand
    
    Case "package-version"
      sSubst = "-" & $sTimeStamp '& "-" & $sCommit
  
    Case "summary"
      Try sSubst = $cComp[sArg].Summary
      
    Case "desc"
      If sArg = "all" Then
        sSubst = "\n%description"
      Else
        sSubst = "\n%description " & sArg
      Endif
      Try sSubst &= "\n" & $cComp[sArg].Description
      
    Case "dependencies"
      
      If sArg = "ide" Then
        aComp = GetIDEDependencies()
      Else If sArg = "all" Then
        aComp = GetAllDependencies()
      Else If sArg = "nogui" Then
        aComp = GetAllDependencies(True)
      Else
        Return 
      Endif
      
      For I = 0 To aComp.Max
        aComp[I] = "Requires: %{name}-" & Replace(aComp[I], ".", "-") & " = %{version}"
      Next
      sSubst = aComp.Join("\n")
        
    Case "package"
      
      If sArg Then
      
        iPos = InStr(sArg, "\n")
        If iPos = 0 Then Return True
        
        sCommand = Trim(Left(sArg, iPos - 1))
        sArg = Mid$(sArg, iPos + 1)
        
        If $cPackage.Exist(sCommand) Then Error.Raise(Subst("Package '&1' already declared", sCommand))
        $cPackage[sCommand] = True
        sSubst = MakeRpmPackage(sCommand, sArg)
        
      Else
    
        sSubst = ""
        For Each sComp In $aComp
          sComp = Replace(sComp, "-", ".")
          If sComp Not Begins "gb." Then Continue
          If IsDisabled(sComp) Then Continue
          If $cPackage.Exist(sComp) Then Continue
          sSubst &= MakeRpmPackage(sComp) & "\n\n"
        Next
        sSubst = RTrim(sSubst)
        
      Endif
    
    Case "files"
      
      If sArg Then
      
        iPos = InStr(sArg, "\n")
        If iPos = 0 Then Return True
        
        sComp = Trim(Left(sArg, iPos - 1))
        sArg = Mid$(sArg, iPos + 1)

        If $cFiles.Exist(sComp) Then Error.Raise(Subst("Files '&1' already declared", sComp))
        $cFiles[sComp] = True
        sSubst = MakeRpmFiles(sComp, sArg)

      Else
        
        sSubst = ""
        For Each sComp In $aComp
          sComp = Replace(sComp, "-", ".")
          If sComp Not Begins "gb." Then Continue
          If IsDisabled(sComp) Then Continue
          If $cFiles.Exist(sComp) Then Continue
          sSubst &= MakeRpmFiles(sComp) & "\n\n"
        Next
        sSubst = RTrim(sSubst)
        
      Endif
      
    Case Else 
      Return True
      
  End Select
  
End

Private Sub MakeRpmPackage(sComp As String, Optional sArg As String) As String

  Dim aResult As New String[]
  Dim hComp As CComponent
  Dim sLine As String
  Dim bDepends As Boolean
  Dim aDepends As String[]
  Dim sDepend As String
  
  hComp = $cComp[Replace(sComp, ".", "-")]
  If Not hComp Then Return
  
  aResult.Add("%package " & Replace(sComp, ".", "-"))
  aResult.Add("Summary: " & hComp.Summary)
  
  If sArg Then
    For Each sLine In Split(sArg, "\n")
      aResult.Add(sLine)
      sLine = Trim(sLine)
      If sLine Begins "Requires: " Then bDepends = True
    Next
  Endif
  
  If Not bDepends Then 
    aDepends = ["Requires: %{name}-runtime = %{version}"]
    For Each sDepend In hComp.Depends
      aDepends.Add("Requires: %{name}-" & Replace(sDepend, ".", "-") & " = %{version}")
    Next
    aResult.Insert(aDepends)
  Endif
  
  aResult.Add("")
  aResult.Add("%description " & Replace(sComp, ".", "-"))
  aResult.Add(hComp.Description)
  
  Return aResult.Join("\n")

End

Private Sub MakeRpmFiles(sComp As String, Optional sArg As String) As String

  Dim aResult As New String[]
  Dim hComp As CComponent
  Dim sFile As String
  
  sComp = Replace(sComp, ".", "-")

  hComp = GetComponent(sComp)
  aResult.Add("%files " & hComp.Name)

  aResult.Add("%dir %{_datadir}/%{name}")
  If hComp.Controls Then aResult.Add("%dir %{_datadir}/%{name}/control")
  aResult.Add("%dir %{_datadir}/%{name}/info")
  aResult.Add("%dir %{_libdir}/%{name}")
  
  For Each sFile In GetFiles(sComp)
    sFile = Replace(sFile, "usr/lib/gambas3/", "%{_libdir}/%{name}/")
    sFile = Replace(sFile, "usr/share/gambas3/", "%{_datadir}/%{name}/")
    aResult.Add(sFile)
  Next
    
  If sArg Then aResult.Add(sArg)
  
  Return aResult.Join("\n")

End

Private Sub CommandDeb(sCommand As String, sArg As String, ByRef sSubst As String) As String
  
  Dim aComp As String[]
  Dim hComp As CComponent
  Dim iPos As Integer
  Dim sComp As String
  Dim aPackage As String[]
  Dim cPackage As Collection
  Dim I As Integer
  
  Select Case sCommand
    
    Case "package-version"
      sSubst = ""
      
    Case "source-version"
      sSubst = "+git." & $sTimeStamp
  
    Case "desc"
      hComp = $cComp[sArg]
      If Not hComp Then Return
      sSubst = hComp.GetDebianDescription().Join("\n")
      
    Case "dependencies"
      
      If sArg = "ide" Then
        aComp = GetIDEDependencies()
      Else If sArg = "all" Then
        aComp = GetAllDependencies()
      Else If sArg = "nogui" Then
        aComp = GetAllDependencies(True)
      Else
        
        Return
        
      Endif
      
      For I = 0 To aComp.Max
        aComp[I] = "gambas3-" & Replace(aComp[I], ".", "-") & " (>= ${binary:Version})"
      Next
      sSubst = aComp.Join(",")

    Case "package"
      
      If sArg Then
      
        iPos = InStr(sArg, "\n")
        If iPos = 0 Then Return True
        
        sCommand = Trim(Left(sArg, iPos - 1))
        sArg = Mid$(sArg, iPos + 1)
        
        If $cPackage.Exist(sCommand) Then Error.Raise(Subst("Package '&1' already declared", sCommand))
        $cPackage[sCommand] = True
        sSubst = MakeDebPackage(sCommand, sArg)
        
      Else
    
        sSubst = ""
        For Each sComp In $aComp
          sComp = Replace(sComp, "-", ".")
          If sComp Not Begins "gb." Then Continue
          If IsDisabled(sComp) Then Continue
          If $cPackage.Exist(sComp) Then Continue
          sSubst &= MakeDebPackage(sComp) & "\n\n"
        Next
        sSubst = RTrim(sSubst)
        MakeDebianFiles(File.Dir($sDest))
        
      Endif
      
    Case "dsc-binary"
      
      aPackage = New String[]
      For Each cPackage In $aDscPackage
        aPackage.Add(cPackage["name"])
      Next
      sSubst = aPackage.Sort().Join()
      
    Case "dsc-package-list"
      aPackage = New String[]
      For Each cPackage In $aDscPackage
        aPackage.Add(" " & cPackage["name"] & " deb " & cPackage["section"] & " optional arch=" & cPackage["architecture"])
      Next
      sSubst = "Package-list:\n" & aPackage.Join("\n")
    
    Case "dsc-build-depends"
      sSubst = $sBuildDepends
    
    Case "control-file"
      sSubst = $sControlFile
      
    Case Else 
      Return True
      
  End Select
  
End

Private Sub MakeDebPackage(sComp As String, Optional sArg As String) As String

  Dim aResult As New String[]
  Dim hComp As CComponent
  Dim sLine As String
  Dim aDepends As String[]
  Dim sDepend As String
  
  hComp = $cComp[Replace(sComp, ".", "-")]
  If Not hComp Then Return
  
  aResult.Add("Package: gambas3-" & Replace(sComp, ".", "-"))
  aResult.Add("Architecture: " & If(hComp.Native, "any", "all"))
  aResult.Add("Section: libdevel")
  
  aDepends = New String[]
  aDepends.Add("${misc:Depends}")
  If hComp.Native Then aDepends.Add("${shlibs:Depends}")
  aDepends.Add("gambas3-runtime (>= ${binary:Version})")
  For Each sDepend In hComp.Depends
    aDepends.Add("gambas3-" & Replace(sDepend, ".", "-") & " (>= ${binary:Version})")
  Next

  If sArg Then
    For Each sLine In Split(sArg, "\n")
      If Trim(sLine) Begins "Depends: " Then
        aDepends.Add(Trim(Mid(sLine, InStr(sLine, ":") + 1)))
        Continue 
      Endif
      aResult.Add(sLine)
    Next
  Endif
  
  aResult.Add("Depends: " & aDepends.Join(","))

  aResult.Insert(hComp.GetDebianDescription())
  
  Return aResult.Join("\n")

End

Private Sub MakeDebianFiles(sDir As String)

  Dim sComp As String
  Dim aFiles As String[]
  
  For Each sComp In $aComp
    
    If sComp Not Begins "gb-" Then Continue
    If IsDisabled(sComp) Then Continue
    
    aFiles = GetFiles(sComp)
    
    If aFiles.Count = 0 Then Continue
    File.Save(sDir &/ "gambas3-" & sComp & ".install", aFiles.Join("\n"))
    
  Next

End

Private Sub BrowseControlForDsc(sPath As String)

  Dim hFile As File
  Dim sLine As String
  Dim sPackage As String
  Dim cPackage As Collection
  Dim bBuildDepends As Boolean

  $aDscPackage = New Collection[]

  hFile = Open sPath For Input 
  For Each sLine In hFile.Lines
    
    sLine = RTrim(sLine)
    If Not sLine Then Continue
    
    If sLine Begins " " Then
      If bBuildDepends Then $sBuildDepends &= "\n" & RTrim(sLine)
    Else
      bBuildDepends = False
    Endif
    
    If sLine Begins "Package: " Then
      sPackage = Trim(Mid$(sLine, InStr(sLine, ": ") + 2))
      cPackage = New Collection
      cPackage["name"] = sPackage
      $aDscPackage.Add(cPackage)
    Else If sLine Begins "Architecture: " Then
      If cPackage Then cPackage["architecture"] = Trim(Mid$(sLine, InStr(sLine, ": ") + 2))
    Else If sLine Begins "Section: " Then
      If cPackage Then cPackage["section"] = Trim(Mid$(sLine, InStr(sLine, ": ") + 2))
    Else If sLine Begins "Build-Depends: " Then
      $sBuildDepends = sLine
      bBuildDepends = True
    Endif
  Next
  hFile.Close

End

Private Sub ComponentNeedsGUI(sComp As String) As Boolean

  Dim hComp As CComponent
  
  sComp = Replace(sComp, ".", "-")
  
  If sComp Begins "gb-gui" Then Return True
  If sComp Begins "gb-sdl" Then Return True
  If sComp Begins "gui" Then Return True
  If sComp = "all" Then Return True
  If sComp = "ide" Then Return True
  
  hComp = $cComp[sComp]
  If Not hComp Then Return
  
  If hComp.NeedsGUI Then Return True

  For Each sComp In hComp.Depends
    If ComponentNeedsGUI(sComp) Then Return True
  Next

End
