# -*- coding: utf-8 -*-
"""Module for parsing retention.dat file."""

import pynag.Parsers.main

# TODO: Raise more specific errors in this class
from pynag.Parsers.errors import ParserError

class RetentionDat(object):

    """ Easy way to parse the content of retention.dat

    After calling parse() contents of retention.dat are kept in self.data

    Example Usage::

        r = retention()
        r.parse()
        print r
        print r.data['info']
    """

    def __init__(self, filename=None, cfg_file=None):
        """ Initilize a new instance of retention.dat

        Args (you only need to provide one of these):

            filename: path to your retention.dat file

            cfg_file: path to your nagios.cfg file, path to retention.dat will
            be looked up in this file

        """
        # If filename is not provided, lets try to discover it from
        # nagios.cfg
        if filename is None:
            main_config = pynag.Parsers.main.MainConfig(cfg_file)
            filename = main_config.get("state_retention_file")

        self.filename = filename
        self.data = None

    def parse(self):
        """ Parses your status.dat file and stores in a dictionary under self.data

        Returns:

            None

        Raises:

            :py:class:`ParserError`: if problem arises while reading status.dat

            :py:class:`ParserError`: if status.dat is not found

            :py:class:`IOError`: if status.dat cannot be read
        """
        self.data = {}
        status = {}  # Holds all attributes of a single item
        key = None  # if within definition, store everything before =
        value = None  # if within definition, store everything after =
        if not self.filename:
            raise ParserError("status.dat file not found")
        in_block = False
        lines = open(self.filename, 'r', encoding='utf-8').readlines()
        for sequence_no, line in enumerate(lines):
            line_num = sequence_no + 1
            # Cleanup and line skips
            line = line.strip()
            if line == "":
                pass
            elif line[0] == "#" or line[0] == ';':
                pass
            elif in_block and line.find("=") != -1:
                (key, value) = line.split("=", 1)
                status[key] = value
            elif line.find("{") != -1:
                in_block = True
                status = {}
                status['meta'] = {}
                status['meta']['type'] = line.split("{")[0].strip()
            elif line.find("}") != -1:
                in_block = False
                # Status definition has finished, lets add it to
                # self.data
                if status['meta']['type'] not in self.data:
                    self.data[status['meta']['type']] = []
                self.data[status['meta']['type']].append(status)
            elif in_block and key == "long_plugin_output":
                # special hack for long_output support. We get here if:
                # * line does not contain {
                # * line does not contain }
                # * line does not contain =
                # * last line parsed started with long_plugin_output=
                status[key] += "\n" + line
            else:
                raise ParserError("Error on %s:%s: Could not parse line: %s" % (self.filename, line_num, line))

    def __setitem__(self, key, item):
        self.data[key] = item

    def __getitem__(self, key):
        return self.data[key]

    def __str__(self):
        if not self.data:
            self.parse()
        str_buffer = "# Generated by pynag"
        for datatype, datalist in list(self.data.items()):
            for item in datalist:
                str_buffer += "%s {\n" % datatype
                for attr, value in list(item.items()):
                    str_buffer += "%s=%s\n" % (attr, value)
                str_buffer += "}\n"
        return str_buffer
