#!/usr/bin/python
# -*- Python -*-
# $Id: z.py,v 1.4 2000/01/13 21:50:06 david Exp $

"""The following path modification will be unnecessary after (If)
dpkg-python is moved to a standard python module location; but it
won't hurt if we leave it anyway, since it's at the end of the
sys.path:"""
import sys
sys.path.append('/usr/lib/site-python/dpkg')

import dpkg_log
import modified_dpkg_packages
import string


def barf(text):
    print text
    print '***aborting***'
    exit(1)


def warn(text):
    print '*warning*:', text


def packages_from_file (inFileName, dpkg_logger):
    """answer a list of dictionaries (as constructed by dpkg_packages.read);
    each dictionary contains the fields of a package from inFileName"""
    inFile = open(inFileName)
    listOfDics = modified_dpkg_packages.read(inFile, dpkg_logger.log)
    inFile.close()
    return listOfDics


logger = dpkg_log.logger()

packages_available = packages_from_file("python-packages-available", logger)
#packages_tasks = packages_from_file("package-tasks", logger) #may be unnecessary now
tasks_control = packages_from_file("tasks", logger)
# each of those is a list of dictionaries


def dictionary_from_list(aList,keySelector):
    """answer a newly-constructed dictionary that maps elements of
    aList using keySelector of each list member as the key."""
    newDict = {}
    for element in aList:
        newDict[element[keySelector]] = element
    return newDict

"""create such a dictionary so we can look up packages_tasks pacakges
by package name"""
#dic_packages_tasks = dictionary_from_list(packages_tasks,'package') #obsolete?
dic_packages_available = dictionary_from_list(packages_available,'package')
dic_tasks_control = dictionary_from_list(tasks_control,'task')

class Task:
    """a Task has a collection of packages and a task name"""
    """and maybe a description"""
    """and maybe a Suppress: ... line, which means the Task is
    not actually created, but its pacakges are not listed as
    new; i.e. this way we acknowledge the existence of packages
    we don't want in any of the generated Task packages"""
    def __init__(self,name):
        self.__name = name
        self.__packages={}  #key is 'packagename', value is package dictionary
        self.__description=[] #a list of text lines

    def add_package(self,package):
        pname = package['package']
        if self.__packages.has_key(pname):
            print 'Ignoring attempt to add duplicate package', pname, 'to task', self.__name
        else:
            self.__packages[pname]=package

    def packages(self):
        return self.__packages

    def taskname(self):
        return self.__name

    def packagenames(self):
        return self.__packages.keys()

    def sorted_packagenames(self):
        temp = self.__packages.keys()
        temp.sort()
        return temp

    def set_description(self,list):
        self.__description = list

    def add_description_lines(self,listoftexts):
        for text in listoftexts:
            self.__description.append(text)

    def description(self):
        return self.__description


class TasksDic:
    """a TasksDic has a dictionary containing Tasks and knows
    how to create Tasks and add packages to them"""
    def __init__(self):
        self.__dic = {}

    def add_task(self,taskobject):
        tname = taskobject.taskname()
        if self.__dic.has_key(tname):
            print 'Ignoring attempt to add duplicate task', tname
        else:
            self.__dic[tname]=taskobject
        
    def add_package_to_task(self,package,taskname):
        if not self.__dic.has_key(taskname):
            self.__dic[taskname]=Task(taskname)
        self.__dic[taskname].add_package(package)
        
    def tasknames(self):
        return self.__dic.keys()
    
    def tasks(self):
        return self.__dic

    def sorted_tasknames(self):
        "reorder the task names, and each task's package names"
        temp = self.__dic.keys()
        temp.sort()
        return temp

#tasksDicFromPackageTasks = TasksDic() #this may be obsolete now
tasksDicFromTasks = TasksDic()

def task_string_parse(text):
    "answer a (possibly empty) list of task names"
    answer = []
    # hide commas, split words
    for word in string.split(string.replace(text,',',' ')):
        if word[0] == '#':
            break
        answer.append(word)
    return answer

def package_list_parse(list):
    """answer a list of package names from a list of lines containing
    package names and their descriptions, as in the tasks control file"""
    """e.g. ['blah -- this is the blah pacakge',
    'blork-whatfor -- this is the new and imporved BW package']
    becomes ['blah' 'blork-whatfor']"""
    
    answer = []
    #print list
    for line in list:
        answer.append(string.split(line)[0])
    return answer

"the old way"
"""for each package, find its task information, add it to its Task(s)
(using tasksDicFromPackageTasks so it creates Tasks as we encounter them)"""

#  for pkg in packages_available:
#      packagename = pkg['package']
#      taskdata = dic_packages_tasks.get(packagename)
#      if taskdata:
#          for taskname in task_string_parse(taskdata['tasks']):
#              tasksDicFromPackageTasks.add_package_to_task(pkg,taskname)
#      else:
#          print "uh-oh, no tasks data for package", packagename

"the new way"
"""for each task, add it to the tasksDicFromTasks, along with its
description and packages"""

for task in tasks_control:
    taskname = task['task']
    if tasksDicFromTasks.tasks().has_key(taskname):
        barf('sorry, we cannot have a duplicate task name: ' + taskname)
    newTask = Task(taskname)

    # instead of this we should make Task know how to process task,
    # and internalize all (most?) of the following ???

    if not task.has_key('suppress'):  # treat suppressed tasks differently -- is this the way to do it???
        tasksDicFromTasks.add_task(newTask)

        #--stopped here -- 07 Nov,, now what ???

    newTask.set_description(task['description'])

    for pkgname in package_list_parse(task['packages'][1]):
        if dic_packages_available.has_key(pkgname):
            thisPackage = dic_packages_available[pkgname]
        else:
            warn('be careful, package "' + pkgname+ '" may not be available')
            thisPackage = {'package': pkgname, 'description': ['(new)']}
            dic_packages_available[pkgname] = thisPackage
        newTask.add_package(thisPackage)
            

class TextFile:
    def __init__(self, filename):
        self.__filehandle = open(filename,"a")

    def writeLine(self, text):
        self.__filehandle.write(text + '\n')

    def close(self):
        self.__filehandle.close()
        self.__filehandle = None

def write_string_to_file(text, filename):
    """open filename (create, if necessary), append text, nl, and close it"""
    afile = TextFile(filename)
    afile.writeLine(text)
#    afile = open(filename,"a")
#    afile.write(text + '\n')
    afile.close()
    

"""write each task's package names to its dependencies file, properly formatted"""

#  "the old (maybe now obsolete) way"
#  for tname in tasksDicFromPackageTasks.tasknames():
#      task = tasksDicFromPackageTasks.tasks()[tname]
#      task_dependencies = "task-packages=" + string.join(task.sorted_packagenames() ,', ')
#      #for pkgname in task.packages().keys():
#      #    string.append (task_dependencies, (pkgname + ", "))
    
#      write_string_to_file(task_dependencies, tname + ".substvars.theoldway.in")

"the new way"
for rawtask in tasks_control: #to keep them in originally specified order
    tname = rawtask['task']
    if tasksDicFromTasks.tasks().has_key(tname):
        task = tasksDicFromTasks.tasks()[tname] #this is a Task object
        task_dependencies = string.join(task.sorted_packagenames() ,', ')
    
        #      write_string_to_file("task-packages=" + task_dependencies, tname + ".substvars.in")

        #      "the above is for comparison to the old way, now we do the real new way:"

        controlFile = TextFile('control.generated.tasks')
        controlFile.writeLine('Package: ' + tname)
        controlFile.writeLine('Architecture: all')
        controlFile.writeLine('Depends: ' + task_dependencies)
        description = task.description()
        controlFile.writeLine('Description: ' + description[0])
        for descLine in description[1]:
            controlFile.writeLine(descLine)
        controlFile.writeLine('')
        controlFile.close()
    
    


def maybe(pkg,key):
    # answer the value of key or '' if key not found
    if pkg.has_key(key):
        return pkg[key]
    return ''
    

"""report the tasks and their contents"""
#  print "<<<<<<<<THE OLD WAY>>>>>>>>"
#  for tname in tasksDicFromPackageTasks.sorted_tasknames():
#      task = tasksDicFromPackageTasks.tasks()[tname]
#      print ""
#      print "========================================="
#      print "Task: ", tname
#      print "===="
#      packagedic = task.packages()
#      for pname in task.sorted_packagenames():
#          package = packagedic[pname]
#          print package['package'], '--', package['description'][0]
#          #print '  +', maybe(package,'depends'), maybe(package,'recommends')
#          #print '  =', maybe(package,'suggests')
#          #print '  -', maybe(package,'conflicts')

#  print "<<<<<<<<THE NEW WAY>>>>>>>>"
for tname in tasksDicFromTasks.sorted_tasknames():
    task = tasksDicFromTasks.tasks()[tname]
    print ""
    print "========================================="
    print "Task: ", tname
    print "===="
    packagedic = task.packages()
    for pname in task.sorted_packagenames():
        package = packagedic[pname]
        print package['package'], '--', package['description'][0]
        #print '  +', maybe(package,'depends'), maybe(package,'recommends')
        #print '  =', maybe(package,'suggests')
        #print '  -', maybe(package,'conflicts')        

#------------------------------------
# not yet used.... but don't throw away yet:
#------------------------------------
class Package:
    def __init__(self,name):
        self.__dependers = [] # list of Packages that depend on me
        self.__recommenders = [] # list of Packages that recommend me
        self.__controlFileLines = [] # raw copy of the control file entry
        self.__controlFileDictionary = {}  #dict containing a key for each line

    def name(self):
        return self.__controlFileDictionary['Package']













