#!/usr/bin/python

# A script to create an AkabeiPackage object from the information Pacman stores.
#
#   Copyright (C) 2011 Lisa Vitolo <shainer@chakra-project.org>

#   This program is free software; you can redistribute it and/or
#   modify it under the terms of the GNU General Public
#   License as published by the Free Software Foundation; either
#   version 2 of the License, or (at your option) any later version.

from akabeipackage import *
import sys
import os

class PacmanPackageParser:
    
    def __init__(self, d, i, f):
        self.descFileName = d
        self.installFileName = i
        self.filesFileName = f

        self.desc = None
        self.install = None
        self.files = None

    def parsePackage(self):
        """Main public API. Returns True/False for success/failure."""

        if not self.descFileName:
            print("[!!] Found malformed package: no desc file.")
            return False

        self.desc = open(self.descFileName, "r")

        if self.installFileName:
            self.install = open(self.installFileName, "r")
        if self.filesFileName:
            self.files = open(self.filesFileName, "r")
        
        self.package = AkabeiPackage()
        
        # Used by the parse* functions
        self.state = ""
        
        result = self.parseDescription()
        # These are both optional files.
        self.parseInstall()
        self.parseFiles()
        return result
        
    def parseDescription(self):
        """Returns success/failure."""

        self.state = ""

        # Two required parameters for a package: NAME and
        # VERSION. If at least one is missing, returns False.
        hasName = False
        hasVersion = False
        
        for line in self.desc.readlines():
            line = line[:-1] # delete newline at the end
            
            if len(line) == 0:
                self.state = ""
                continue
            
            # lines in the form %SOMETHING% starts a section in the file
            if line[0] == "%":
                self.state = line[1:len(line)-1]
            else:
                if self.state == "NAME":
                    self.package.name = line
                    hasName = True
                elif self.state == "VERSION":
                    self.package.version = line
                    hasVersion = True
                elif self.state == "DESC":
                    self.package.description = line
                elif self.state == "GROUPS":
                    self.package.addGroup(line)
                elif self.state == "URL":
                    self.package.url = line
                elif self.state == "LICENSE":
                    self.package.addLicense(line)
                elif self.state == "ARCH":
                    self.package.arch = line
                elif self.state == "BUILDDATE":
                    self.package.builddate = int(line)
                elif self.state == "INSTALLDATE":
                    self.package.installdate = int(line)
                elif self.state == "PACKAGER":
                    self.package.packager = line
                elif self.state == "SIZE":
                    self.package.size = int(line)
                elif self.state == "DEPENDS":
                    self.package.addDependency(line)
                elif self.state == "OPTDEPENDS":
                    self.package.addOptional(line)
                elif self.state == "REASON":
                    if (int(line) == 1): # this means "installed as a dependency" in pacman
                        self.package.installreason = 2 # this means "installed as a dependency" in akabei                        
                elif self.state == "PROVIDES":
                    self.package.addProvide(line)
                elif self.state == "REPLACES":
                    self.package.addReplace(line)
                elif self.state == "CONFLICTS":
                    self.package.addConflict(line)

        if not hasName:
            print "[!!] Found malformed package with no name."
        if not hasVersion:
            print "[!!] Found malformed package with no version."

        return hasName and hasVersion                  

    # Installation scriptlet
    def parseInstall(self):
        if self.install == None:
            return
        
        self.package.addScriptlet(self.install.read())
    
    def parseFiles(self):
        if self.files == None:
            return
            
        self.state = ""
        packagefiles = {}
        
        for line in self.files.readlines():
            line = line[:-1]
            
            if len(line) == 0:
                self.state = ""
                continue
            
            if line[0] == "%":
                self.state = line[1:len(line)-1]
            else:
                if self.state == "FILES":
                    packagefiles[line] = ""
                if self.state == "BACKUP":
                    separatedLine = line.partition("\t")
                    packagefiles[separatedLine[0]] = separatedLine[2]
                    
        for pf in packagefiles:
            self.package.addFile(pf, packagefiles[pf])
                     
    def getPackage(self):
        return self.package
    
    def __del__(self):
        if self.desc != None:
            self.desc.close()
        if self.install != None:
            self.install.close()
        if self.files != None:
            self.files.close()

class AkabeiPackageParser(object):
    def __init__(self, dbConnection, packageRow):
        self._dbConnection = dbConnection
        self._packageRow = packageRow
        self._package = None

    def _parseVersion(self, version, epoch):
        if epoch > 0:
            return "%d:%s" % (epoch, version)

        return version

    def parsePackage(self):
        packageId = self._packageRow[0]

        self._package = AkabeiPackage()
        self._package.name = str(self._packageRow[1])
        self._package.version = self._parseVersion(self._packageRow[2], self._packageRow[3])
        self._package.filename = str(self._packageRow[4])
        self._package.description = self._packageRow[5]
        self._package.size = self._packageRow[6]
        self._package.installedsize = self._packageRow[7]
        self._package.md5sum = str(self._packageRow[8])
        self._package.url = str(self._packageRow[9])
        self._package.builddate = self._packageRow[10]
        self._package.arch = str(self._packageRow[11])
        self._package.packager = self._packageRow[12]
        self._package.flags = str(self._packageRow[13])
        self._package.screenshoturl = str(self._packageRow[14])
        self._package.installedreason = self._packageRow[15]
        self._package.installdate = self._packageRow[16]

        scriptQuery = 'SELECT * FROM scriptlets WHERE package=%d' % packageId
        depsQuery = 'SELECT * FROM depends WHERE package=%d' % packageId
        conflictsQuery = 'SELECT * FROM conflicts WHERE package=%d' % packageId
        providesQuery = 'SELECT * FROM provides WHERE package=%d' % packageId
        optionalQuery = 'SELECT * FROM optional WHERE package=%d' % packageId
        replacesQuery = 'SELECT * FROM replaces WHERE package=%d' % packageId
        mimetypesQuery = 'SELECT * FROM providesmimetype WHERE package=%d' % packageId
        groupsQuery = 'SELECT * FROM belongsgroup WHERE package=%d' % packageId
        filesQuery = 'SELECT * FROM files WHERE package=%d' % packageId
        licenseQuery = 'SELECT * FROM licensed WHERE package=%d' % packageId

        for script in self._dbConnection.execute(scriptQuery):
            self._package.addScriptlet(str(script[2]))

        for dep in self._dbConnection.execute(depsQuery):
            self._package.addDependency(str(dep[2]))

        for conflict in self._dbConnection.execute(conflictsQuery):
            self._package.addConflict(str(conflict[2]))

        for provide in self._dbConnection.execute(providesQuery):
            self._package.addProvide(str(provide[2]))

        for optdep in self._dbConnection.execute(optionalQuery):
            self._package.addOptional(str(optdep[2]))

        for replace in self._dbConnection.execute(replacesQuery):
            self._package.addReplace(str(replace[2]))

        for mimetype in self._dbConnection.execute(mimetypesQuery):
            self._package.addMimeType(str(mimetype[2]))

        for group in self._dbConnection.execute(groupsQuery):
            self._package.addGroup(str(group[1]))

        for f in self._dbConnection.execute(filesQuery):
            self._package.addFile(str(f[2]))

        for license in self._dbConnection.execute(licenseQuery):
            self._package.addLicense(str(license[1]))

        return True


    def getPackage(self):
        return self._package
