# -*- coding: utf-8 -*-
import os
from codecs import open

from jinja2 import Environment, FileSystemLoader
from jinja2.exceptions import TemplateNotFound
from feedgenerator import Atom1Feed

from pelican.settings import read_settings
from pelican.utils import clean_output_dir

_TEMPLATES = ('index', 'tag', 'tags', 'article', 'category', 'categories',
              'archives', 'page')


class Generator(object):
    """Base class generator"""
    
    def __init__(self, settings=None, path=None, theme=None, output_path=None, 
        markup=None):
        if settings is None:
            settings = {}
        self.settings = read_settings(settings)
        self.path = path or self.settings['PATH']
        if self.path.endswith('/'):
            self.path = self.path[:-1]

        self.theme = theme or self.settings['THEME']
        output_path = output_path or self.settings['OUTPUT_PATH']
        self.output_path = os.path.realpath(output_path)
        self.markup = markup or self.settings['MARKUP']

        if not os.path.exists(self.theme):
            theme_path = os.sep.join([os.path.dirname(
                os.path.abspath(__file__)), "themes/%s" % self.theme])
            if os.path.exists(theme_path):
                self.theme = theme_path
            else:
                raise Exception("Impossible to find the theme %s" % self.theme)

        if 'SITEURL' not in self.settings:
            self.settings['SITEURL'] = self.output_path

        # get the list of files to parse
        if not path:
            raise Exception('you need to specify a path to search the docs on !')

    def run(self, processors):
        context = self.settings.copy()
        processors = [p() for p in processors]

        for p in processors:
            if hasattr(p, 'preprocess'):
                p.preprocess(context, self)

        if self.output_path not in os.path.realpath(self.path):
            clean_output_dir(self.output_path)

        for p in processors:
            p.process(context, self)

    def generate_feed(self, elements, context, filename=None):
        """Generate a feed with the list of articles provided

        Return the feed. If no output_path or filename is specified, just return
        the feed object.

        :param articles: the articles to put on the feed.
        :param context: the context to get the feed metadatas.
        :param output_path: where to output the file.
        :param filename: the filename to output.
        """
        feed = Atom1Feed(
            title=context['SITENAME'],
            link=context['SITEURL'],
            feed_url='%s/%s' % (context['SITEURL'], filename),
            description=context.get('SITESUBTITLE', ''))
        for element in elements:
            feed.add_item(
                title=element.title,
                link='%s/%s' % (context['SITEURL'], element.url),
                description=element.content,
                author_name=getattr(element, 'author', 'John Doe'),
                pubdate=element.date)

        if filename:
            complete_path = os.path.join(self.output_path, filename)
            try:
                os.makedirs(os.path.dirname(complete_path))
            except Exception:
                pass
            fp = open(complete_path, 'w')
            feed.write(fp, 'utf-8')
            print u' [ok] writing %s' % complete_path
            
            fp.close()
        return feed

    def generate_file(self, name, template, context, **kwargs):
        """Write the file with the given informations

        :param name: name of the file to output
        :param template: template to use to generate the content
        :param context: dict to pass to the templates.
        :param **kwargs: additional variables to pass to the templates
        """
        context = context.copy()
        context.update(kwargs)
        output = template.render(context)
        filename = os.sep.join((self.output_path, name))
        try:
            os.makedirs(os.path.dirname(filename))
        except Exception:
            pass
        with open(filename, 'w', encoding='utf-8') as f:
            f.write(output)
        print u' [ok] writing %s' % filename

    def get_templates(self):
        """Return the templates to use."""
        path = os.path.expanduser(os.path.join(self.theme, 'templates'))
        env = Environment(loader=FileSystemLoader(path))
        templates = {}
        for template in _TEMPLATES:
            try:
                templates[template] = env.get_template('%s.html' % template)
            except TemplateNotFound:
                raise Exception('Unable to load %s.html from %s' % (
                    template, path))
        return templates

    def get_files(self, path, exclude=[]):
        """Return the files to use to use in this generator

        :param path: the path to search the file on
        :param exclude: the list of path to exclude
        """
        files = []
        for root, dirs, temp_files in os.walk(path, followlinks=True):
            for e in exclude:
                if e in dirs:
                    dirs.remove(e)
            files.extend([os.sep.join((root, f)) for f in temp_files
                if True in [f.endswith(markup) for markup in self.markup]])
        return files

@@ -419,36 +419,104 @@
  %22%22%22
-Base class generator%22%22%22%0A    
+Handle all generation process: files writes, feed creation, and this%0A    kind of basic stuff%22%22%22%0A
 %0A   
@@ -590,17 +590,16 @@
 th=None,
- 
 %0A       
@@ -605,32 +605,155 @@
   markup=None):%0A
+        %22%22%22Read the settings, and performs some checks on the environement%0A        before doing anything else.%0A        %22%22%22%0A
         if setti
@@ -1821,24 +1821,97 @@
 rocessors):%0A
+        %22%22%22Get the context from each processor, and then process them%22%22%22%0A
         cont
@@ -3635,28 +3635,16 @@
 te_path%0A
-            
 %0A       
@@ -4519,16 +4519,142 @@
  to use.
+%0A        Use self.theme to get the templates to use, and return a list of%0A        templates ready to use with Jinja2.%0A        
 %22%22%22%0A    
@@ -5002,17 +5002,29 @@
 eption('
-U
+%5Btemplates%5D u
 nable to
@@ -5153,16 +5153,33 @@
 clude=%5B%5D
+, extensions=None
 ):%0A     
@@ -5191,19 +5191,25 @@
 %22Return 
-the
+a list of
  files t
@@ -5217,33 +5217,24 @@
  use
- to use in this generator
+, based on rules
 %0A%0A  
@@ -5339,32 +5339,97 @@
 ude%0A        %22%22%22%0A
+        if not extensions:%0A            extensions = self.markup%0A%0A
         files = 
@@ -5709,41 +5709,34 @@
 ith(
-markup) for markup in self.markup
+ext) for ext in extensions
 %5D%5D)%0A

Add some more comments.