"""
ajaxWM - the free web based window manager for remote terminals
Copyright (C) 2007 Dennis Felsing, Andreas Waidler

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/>.

$Id: Files.py 76 2007-12-15 11:26:24Z r0q $
"""

#{{{ Imports
import os
import re
import xml.dom.minidom

import ajaxwm
#}}}
class Files:#{{{
    """
Reads in all files the clients will have access to. It does not read in
files beginning with a dot.
    """
    _content = {}
    _themes = []

    FILES_DIR = 'htdocs'
    THEMES_DIR = 'themes'
    BLACKLIST = re.compile(
        """
        \.* # No hidden files and files in hidden directories.
        """
        , re.DOTALL | re.VERBOSE)

    def __init__(self):#{{{
        for dir in (self.FILES_DIR, self.THEMES_DIR):
            self._walk(dir)
        self._themesToXml()
    #}}}
    def _parseTheme(self, path):#{{{
        """
Reads in the xml file of a theme and returns its attributes. 
        """
        sAttrs = xml.dom.minidom.parse(path).firstChild.attributes
        dAttrs = {}
        for attribute in sAttrs.keys():
            dAttrs[attribute] = sAttrs[attribute].value
        return dAttrs
    #}}}
    def _themesToXml(self):#{{{
        # <?xml version="1.0" ?>
        doc = xml.dom.minidom.Document()
        # <ajaxwm>
        eAjaxwm = doc.createElement('ajaxwm')
        doc.appendChild(eAjaxwm)
        for theme in self._themes:
            values = self._parseTheme(theme['realPath'])
            # <theme name="NAME" author="AUTHOR" email="EMAIL">
            eTheme = doc.createElement('theme')
            eTheme.setAttribute('name', values['name'])
            eTheme.setAttribute('author', values['author'])
            eTheme.setAttribute('email', values['email'])
            eAjaxwm.appendChild(eTheme)

            # <path>
            ePath = doc.createElement('path')
            eTheme.appendChild(ePath)
            tPath = doc.createTextNode(theme['userPath'])
            ePath.appendChild(tPath)
            # </path>

            # <description>
            eDesc = doc.createElement('description')
            eTheme.appendChild(eDesc)
            tDesc = doc.createTextNode(values['description'])
            eDesc.appendChild(tDesc)
            # </description>
            # </theme>
        # </ajaxwm>

        self._content['/' + self.THEMES_DIR + '/themes.xml'] = \
        doc.toprettyxml(indent="    ")
    #}}}
    def _walk(self, path):#{{{
        """
Walks through the paths given as parameters and writes the valid ones to the 
content variable of the class.
        """
        if not os.path.isdir(path):
            return
        for root, dirs, files in os.walk(path):
            self._validate(dirs)
            self._validate(files)
            if root == self.THEMES_DIR:
                self._validateThemes(dirs)
            for file in files:
                self._read('/'.join((root, file)))
    #}}}
    def _validate(self, objects):#{{{
        """
Deletes all objects that do not match the BLACKLIST.
        """
        for object in objects:
            if self.BLACKLIST.search(object).group():
                objects.remove(object)
    #}}}
    def _validateThemes(self, dirs):#{{{
        """
Deletes all theme directories that are not valid for this version.
        """
        for dir in dirs:
            if not ajaxwm.VALID_THEMES[0] \
            <= map(int, dir.split('.')) \
            <= ajaxwm.VALID_THEMES[1]:
                dirs.remove(dir)
    #}}}
    def _destination(self, path):#{{{
        pathElements = path.split('/')
        for pos, pathElement in enumerate(pathElements):
            if pathElement == self.THEMES_DIR:
                del pathElements[pos + 1]
                themePath = '/'.join([''] + pathElements)
                if themePath.endswith('.xml'):
                    self._themes.append({'realPath': path, 
                                         'userPath': themePath})
                return themePath
        return path[len(self.FILES_DIR):]
    #}}}
    def _read(self, path):#{{{
        """
Reads in a file to the content.
        """
        self._content[self._destination(path)] = open(path, 'r').read()
    #}}}
#}}}

#------------------------------------------------------------------------------
# vim: fdm=marker ts=4 sw=4 expandtab 

