# Copyright (C) 1998,1999  marduk <marduk@python.net>
#
# 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

# $Id: rptlib.py,v 1.8 1999/03/12 04:56:05 marduk Exp $

# $Log: rptlib.py,v $
# Revision 1.8  1999/03/12 04:56:05  marduk
# Added ability to warn of old versions of linbot/plugins
# Added patch to enable file:// to work with OS/2
#
# Revision 1.7  1999/03/11 04:51:28  marduk
# Added version module.
#
# Revision 1.6  1999/03/11 02:30:00  marduk
# Added debugio module to handle debugging and IO
#
# Revision 1.5  1999/02/26 01:12:15  marduk
# -o option Created directory if does not exist.
#
# Revision 1.4  1999/02/21 16:39:44  marduk
# 1.0b8
#
# Revision 1.3  1999/01/10 01:02:04  marduk
# Linbot 1.0b6
#
# Revision 1.2  1998/12/31 03:49:08  marduk
# This is linbot 1.0b5.  See CHANGES
#
# Revision 1.1.1.1  1998/12/20 23:17:12  marduk
# initial 1.0
#


__version__ = '1.0'
__author__ = 'marduk@python.net'

import sys
import linbot
import urllib
import string
import os
import debugio
import version

Link = linbot.Link
linkList = Link.linkList
config = linbot.config
proxies = config.PROXIES

problem_db = {}

# get the stylesheet for insertion,
# Note that I do it this way for two reasons.  One is that Netscape reportedly
# handles stylesheets better when they are inlined.  Two is that people often
# forget to put linbot.css in the output directory.
if proxies is None:
    proxies = urllib.getproxies()
opener = urllib.FancyURLopener(proxies)
opener.addheaders = [('User-agent','Linbot ' + version.linbot)]
try:
    stylesheet =  opener.open(config.STYLESHEET).read()
except:
    stylesheet = ''

def get_title(url):
    """ returns the title of a url if it is not None, else returns url
    note that this implies linkList[url] """
    link=linkList[url]
    if link.title is None:
	return url
    return link.title

def make_link(url,text):
    """Return an <A>nchor to a url with <text>.  If url is in the Linklist and
    is external, insert "class=external" in the <A> tag."""
    url = str(url) # because sometimes I lazily pass a Link object.
    mystring = '<a href="' + url + '"'
    try:
	external = linkList[url].external
    except KeyError:
	external = 0
    if external:
	mystring = mystring + ' class="external"'
    else:
	mystring = mystring + ' class="internal"'
    mystring = mystring + '>' + text + '</a>'
    return mystring

def add_problem(type,link):
    """ add a problem to the 'problems' database.  Will not add external links"""
    if link.external: return
    global problem_db
    author = link.author
    if problem_db.has_key(author):
	problem_db[author].append((type,link))
    else:
	problem_db[author]=[(type,link)]

def sort_by_age(a,b):
    """ sort helper for url's age.  a and b are urls in linkList """
    aage, bage = linkList[a].age, linkList[b].age
    if aage < bage:
	return -1
    if aage == bage:
	return sort_by_author(a,b)
    return 1

def sort_by_rev_age(a,b):
    aage, bage = linkList[a].age, linkList[b].age
    if aage > bage:
	return -1
    if aage == bage:
	return sort_by_author(a,b)
    return 1

def sort_by_author(a,b):
    aauthor,bauthor = `linkList[a].author`, `linkList[b].author`
    if aauthor < bauthor:
	return -1
    if aauthor == bauthor:
	return 0
    return 1

def sort_by_size(a,b):
    asize, bsize = linkList[a].totalSize, linkList[b].totalSize
    if asize < bsize:
	return 1
    if asize == bsize:
	return 0
    return -1

def main_index():
    tmp = sys.stdout
    fp = open_file(config.MAIN_FILENAME)
    sys.stdout=fp
    
    print '<html>'
    print '<head>'
    print '<title>Linbot report for "%s"</title>' % get_title(`Link.base`)
    print '<style type="text/css">'
    print '<!-- /* hide from old browsers */'
    print stylesheet
    print ' --> </style>'
    print '</head>'
    print '<frameset COLS="%s,*" border=0 framespacing=0>' \
	  % config.NAVBAR_WIDTH
    print '<frame name="navbar" src="%s" marginwidth=0 marginheight=0 frameborder=0>' \
	  % config.NAVBAR_FILENAME
    print '<frame name="main" src="%s" frameborder=0>' % (linbot.plugins[0]+'.html')
    print '</frameset>'
    print '</html>'
    fp.close()
    sys.stdout = tmp


def nav_bar(plugins):
    # navigation bar
    fp=open_file(config.NAVBAR_FILENAME)
    stdout = sys.stdout
    sys.stdout = fp
    print '<html>\n<head>'
    print '\t<title>navbar</title>'
    print '<style type="text/css">'
    print '<!-- /* hide from old browsers */'
    print stylesheet
    print ' --> </style>'
    print '\t<base target="main">'
    print '</head>'
    print '<body class="navbar">'
    print '<div align=center>'
    print '<table cellpadding="%s" cellspacing="%s">' \
	  % (config.NAVBAR_PADDING, config.NAVBAR_SPACING)
    # title
    print '<tr><th class="home">',
    print '<a target="_top" href="%s" onMouseOver="window.status=\'Linbot Home Page\'; return true;">Linbot %s</a></th></tr>' \
	  % (version.home, version.linbot)

    # labels pointing to each individual page
    for plugin in plugins + ['problems']:
	debugio.write('\t' + plugin,file=stdout)
	filename = plugin + '.html'
	print '<tr><th>',
	report = __import__('plugins.' + plugin, globals(), locals(), [plugin])
	print '<strong><a href="%s" onMouseOver="window.status=\'%s\'; return true">%s</a></strong>' \
	      % (filename, report.__doc__, report.title),
	print '</th></tr>'

	# create the file we just pointed to
	tmp = sys.stdout
	fp = open_file(filename)
	sys.stdout = fp
	doTopMain(report)
	report.generate()
	report_version = report.__version__
	if config.WARN_OLD_VERSION:
	    check_and_warn(plugin,report_version)
	doBotMain()
	fp.close()
	sys.stdout = tmp
    
    print
    print '</table>'
    print '</div>'
    print '</body>'
    print '</html>'

    fp.close()
    sys.stdout = stdout

def open_file(filename):
    """ given config.OUTPUT_DIR checks if the directory already exists; if not, it creates it, and then opens         filename for writing and returns the file object """
    if os.path.isdir (config.OUTPUT_DIR) == 0:
        os.mkdir(config.OUTPUT_DIR)
    return open(config.OUTPUT_DIR + filename,'w')
    
def doTopMain(report):
    """top part of html files in main frame prints to stdout"""
    print '<html>'
    print '<head><title>%s</title>' % report.title
    print '<style type="text/css">'
    print '<!-- /* hide from old browsers */'
    print stylesheet
    print ' --> </style>'
    print '<meta name="Author" content="Linbot ' + version.linbot + '">' 
    print '</head>'
    print '<body class="%s">' % string.split(report.__name__,'.')[1]  
    print '<p class="logo"><a '
    print 'href="%s"><img src="%s" border=0 alt=""></a></p>' % (Link.base, config.LOGO_HREF)
    print '\n<h1 class="basename">'
    print '\t<a href="%s">%s</a>' \
	  % (`Link.base`, get_title(`Link.base`))
    print '</h1>'
    print '\n\n<table width="100%" cellpadding=4>'
    print '\t<tr><th class="title">%s</th></tr>\n</table>\n' % report.title

def doBotMain():
    """ bottom part of html files in main frame"""
    print 
    print '<hr>'
    print '<p class="footer">'
    print '<em>Generated %s by <a target="_top" href="%s">Linbot %s</a></em></p>' \
	  % (linbot.start_time,version.home, version.linbot)
    print '</body>'
    print '</html>'


def read_registry(url):
    """Read file referenced by url and return a registry object.

       The registry object is just a dictionary.  The key an individual
       module name.  The value is a tuple consisting of the latest version
       and the url where it can be retrieved.  e.g.:
       registry['mymodule'] = ('1.0','http://www.mymodule.com/')
    """
    registry = {}
    lines =  opener.open(url).readlines()
    opener.close()
    for line in lines:
	fields = string.split(line)
	if len(fields) != 3: continue
	registry[fields[0]] = fields[1:]
	
    return registry

def check_and_warn(plugin,plugin_version):
    """Check to see if Linbot and plugin are up to date if so write it in
       the report.
    """

    old_linbot = 0
    old_plugin = 0

    # first check to see if linbot is up to date
    try:
	if version.linbot != registry['linbot'][0]:
	    old_linbot = 1
    except KeyError:
	pass
    try:
	if plugin_version != registry[plugin][0]:
	    old_plugin = 1
    except KeyError:
	pass
    
    if (old_plugin + old_linbot):
	print '<table class="warning" cellpadding="4" cellspacing="0" border="0">'
	print '<tr><td><strong>Warning:</strong> ',
	if old_linbot:
	    print 'The version of Linbot you are using (%s) is outdated.' \
		  % version.linbot,
	    print 'You may download the latest version, %s, at ' \
		  % registry['linbot'][0],
	    print '<a href="%s" target="_top">%s</a>.<br><br>' \
		  % (registry['linbot'][1],registry['linbot'][1])
	if old_plugin:
	    print 'The %s plugin used to generate this report is outdated.' \
		  % plugin,
	    print 'This version is %s.  The latest version is %s ' \
		  % (plugin_version, registry[plugin][0]),
	    print 'And may be downloaded at <a href="%s" target="_top">%s</a>.<br>' \
		  % (registry[plugin][1],registry[plugin][1])
	print '</td></tr></table>'

if config.WARN_OLD_VERSION:
    registry = read_registry(version.registry)
    debugio.write('registry = %s' % registry,4)
