# synarere -- a trivial Python IRC bot.
# Copyright (C) 2010 Michael Rodriguez.
# Rights to this code are documented in docs/LICENSE.

"""
This handles parsing configuration files.
It is a class because it is much easier to handle
data.
"""

# Import required Python module.
import os

# Import required source module.
import vars

class Exception(Exception):
    pass

class ConfigBlock (object):
    def __init__ (self, label, values={}):
        self.label = label
        self.vars = {}
        # Copy over any values given during initialization
        for key in values:
            self.vars[key] = values[key]
    
    def add (self, name, value):
        self.vars[name] = value
    
    def get (self, name, defval=None):
        return self.vars.get(name, defval)

class ConfigParser:
    def __init__(self, file):
        self.file = file
        self.parse()

    def parse(self):
        """Parse our file, and put the data into a dictionary."""

        # Attempt to open the file
        try:
            fh = open(self.file, "r")
        except IOError, e:
            raise Exception(os.strerror(e.args[0]))
        
        # Parse
        self.blocks = []
        
        for line in fh.xreadlines():
            for cno, c in enumerate(line):
                # Comment until EOL
                if c == '#':
                    break
                # Block label
                if c == ':':
                    label = line[: cno].strip()
                    self.blocks.append(ConfigBlock(label))
                # Variable
                if c == '=':
                    if not self.blocks:  # skip this line as no block label was given yet
                        break
                    varname = line[: cno].strip()
                    varval = line[cno + 1 :].strip()
                    self.blocks[-1].add(varname, varval)
                    break
        
        # Close the file handle
        fh.close()

    def xget(self, block, variable=None):
        """
        Return whatever is in block:variable. If variable is None,
        we will iterate over mutiple blocks, thus allowing us to
        return multiple values from multiple blocks.
        """

        if block not in set(b.label for b in self.blocks):
            raise Exception('Block %s not found.' % block)

        for i in self.blocks:
            if i.label == block:
                # Just get blocks by this name
                if variable is None:
                    yield i
                # Get a member of a blocks by this name
                else:
                    yield i.get(variable)

    def get(self, block, variable=None):
        """
        Call our iterating generator (xget) and just store all its
        results into a list to return all at once.
        """

        return [b for b in self.xget(block, variable)]
