#! /usr/bin/env python
#
#   Copyright (C) 2006, 2007, One Laptop Per Child Copyright (C) 2007
#   Benjamin Mako Hill <mako@atdot.cc>
#
#   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 3 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, see <http://www.gnu.org/licenses/>.

import os
import sys
import codecs
import shutil
import re
from ConfigParser import ConfigParser

library_config_file = os.environ.get('OLPC_LIBRARY_CONFIG')
if not library_config_file:
    library_config_file = '/usr/share/library-common/config/general.info'

config = ConfigParser()
config.readfp(codecs.open(library_config_file, 'r', 'utf-8'))

main_categories = config.get('library_config', 'main_categories').split(', ')
ignore_dirs = config.get('library_config', 'ignore_dirs').split(', ')

# build a library path
core_library_path = config.get('library_config', 'core_library_path')
home_library_path = config.get('library_config', 'home_library_path')
cache_path = config.get('library_config', 'cache_path')
config_path = config.get('library_config', 'config_path')
i18n_path = config.get('library_config', 'i18n_path')

# create/(re)initialize the .library_pages directory 
output_path = '/home/olpc/.library_pages' # old but kept around for upgrades
try:
    if not os.path.exists(output_path):
        os.mkdir(output_path)
    else: # clear out the directory if it does
        for file in os.listdir(output_path):
            if os.path.isdir(os.path.join(output_path, file)): 
                shutil.rmtree(os.path.join(output_path, file))
            elif os.path.isfile(os.path.join(output_path, file)):
                os.remove(os.path.join(output_path, file))

except:
    print >>sys.stderr, \
        "E: could not initialize library directory '%s'" % output_path
    sys.exit()

# load in the templating system and set up the filesystem loader
try:
    import jinja
except ImportError:
    sys.path.append(os.path.join(os.path.dirname(__file__), 'lib'))
    import jinja

# check /home/olpc/.i18n and if it exists, parse output for LANG value
langs = []
if os.path.exists(i18n_path) and os.path.isfile(i18n_path):
    for line in open(i18n_path, 'r').readlines():
        match = re.match(r'^LANG\s*=\s*[\'\"]?([A-Za-z1-9@\.\-_]{2,})[\'\"]?\s*$', line)
        if match:
            langs.append(match.group(1))

            # if not there, look for categories.(first two letters in
            # LANG).info
            if len(match.group(1)) > 2:
                langs.append(match.group(1)[0:2])

# if still not there settle for categories.info
langs.append("")

# - look for categories.LANG.info
for lang in langs:
    fn = "categories." + lang
    if lang:
        fn = fn + "."
    fn = fn + "info"
    # this should be hit the last time through no matter what
    fn = os.path.join(config_path, fn)
    if os.path.exists(fn) and os.path.isfile(fn):
        category_list_filename = fn
        break

bundle_list = []

# generate category data
def generate_categories():
    category_data = {}
    cp = ConfigParser()
    cp.readfp(codecs.open(category_list_filename, 'r', 'utf-8'))
    for section in cp.sections():
        section_info = {}
        for name, value in cp.items(section):
            section_info[name] = value

        section_info['bundles'] = []
        section_info['name'] = section
        category_data[section] = section_info

    return category_data

category_data = generate_categories()

def add_dir_to_bundle_list(base_path):
    if not os.path.isdir(base_path): 
	return
    else:
    	dir_list = os.listdir(base_path)

    for bundle in dir_list:
        bundle = os.path.join(base_path, bundle).strip()

        # Skip scripts folder
        if os.path.basename(bundle) in ignore_dirs \
            or not os.path.isdir(bundle):
            continue
        elif not os.path.exists(os.path.join(bundle, 'library/library.info')):
            continue

        # this code is now in the wrong place but will be left until we
        # can work out something better with a verification library

        # check the files to make sure that the templates are encoded in
        # UTF-8 and provide a warning if not.  TODO: Warn but don't skip.
        try:
            index = 'index.html'
            if os.path.exists(os.path.join(bundle, index)):
                codecs.open(os.path.join(bundle, index),
                            'r', 'utf-8').read().encode('utf-8')
        except UnicodeDecodeError:
            print >>sys.stderr, \
                "W: index in '%s' is not UTF-8.  Skipping." \
                 % os.path.basename(bundle)
            continue

        # add bundle to bundle_list unless we've seen it already
        if not os.path.basename(bundle) in \
            map(lambda fn: os.path.basename(fn), bundle_list):
            bundle_list.append(bundle)



# build bundle_list
add_dir_to_bundle_list(core_library_path)
add_dir_to_bundle_list(home_library_path)

def add_items_for_section(bundle_hash, cp, section_name):
    for item in cp.items(section_name):
        bundle_hash[item[0]] = item[1]
    return bundle_hash

# iterate through the list of valid bundles and generate the html if its
# templates are present
for bundle in bundle_list:
    info_file_path = os.path.join(bundle + '/library/library.info')

    # Check if there is a info file
    if os.path.isfile(info_file_path):
        new_bundle = {}
        new_bundle['directory'] = bundle
        new_bundle['base_url'] = os.path.dirname(bundle)
        
        cp = ConfigParser()
        cp.readfp(codecs.open(info_file_path, 'r', 'utf-8'))
       
        new_bundle = add_items_for_section(new_bundle, cp, 'Library')

        # override values with any language specific metadata in file
        for lang in langs[:1]:
            if len(lang) < 2:
                break
            if cp.has_section(lang):
                new_bundle = add_items_for_section(new_bundle, cp, lang)
            elif cp.has_section(lang[0:2]):
                new_bundle = add_items_for_section(new_bundle, cp, lang[0:2])

        # if there is no activity start, we set it to index.html
        # (default)
        if not new_bundle.has_key('activity_start') or \
            not new_bundle['activity_start']:
            new_bundle['activity_start'] = 'index.html'

	bundle_category = new_bundle['category']
        if new_bundle['category'] in main_categories:
	    bundle_category = new_bundle['category']
	else:
	    bundle_category = 'other'
        category_data[bundle_category]['bundles'].append(new_bundle) 

def categories():
    categories = []
    cp = ConfigParser()
    cp.readfp(codecs.open(category_list_filename, 'r', 'utf-8'))
    for section in cp.sections():
        if len(category_data[section]['bundles']) > 0:
            categories.append(category_data[section])
    return categories

### INFO BELOW THIS LINE ADDED BACK IN BECAUSE WE'VE CUT THE WEBSERVER
# return a category for a given bundle

template_path = config.get('library_config', 'template_path')
def get_cat_for_bundle(bundle, category_data):
    bundle = bundle.strip()
    if bundle in category_data.keys():
        return bundle
    return None

def render_jinja(file, vars={}):
    jinja_env = jinja.Environment(loader= jinja.FileSystemLoader(template_path))
    tmpl = jinja_env.get_template(file)
    return tmpl.render(vars)

# gather data to output the page
cat = get_cat_for_bundle('search', category_data)
vars = { 'common_url' : template_path,
         'category' : cat,
         'primary_color': category_data[cat]['primarycolor'],
         'secondary_color' : category_data[cat]['secondarycolor'],
         'bundle' : 'search',
         'categories' : categories() }

# render templates and write output
html = render_jinja(os.path.join('library_homepage.tmpl'), vars)
output = open(os.path.join(output_path, 'index.html'), 'w')
print >>output, html.encode('utf-8'),
output.close()


