#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created by René Meusel
This file is part of the CernVM File System auxiliary tools.
"""

from datetime import datetime
from dateutil.tz import tzutc

class UnknownManifestField(Exception):
    def __init__(self, key_char):
        self.key_char = key_char

    def __str__(self):
        return self.key_char

class ManifestValidityError(Exception):
    def __init__(self, message):
        Exception.__init__(self, message)


class Manifest:
    """ Wraps information from .cvmfspublished"""

    def __init__(self, manifest_file):
        """ Initializes a Manifest object from a file pointer to .cvmfspublished """
        for line in manifest_file.readlines():
            if len(line) == 0:
                continue
            if line[0:2] == "--":
                break
            self._read_line(line)
        self._check_validity()


    def __str__(self):
        return "<Manifest for " + self.repository_name + ">"


    def __repr__(self):
        return self.__str__()


    def _read_line(self, line):
        """ Parse lines that appear in .cvmfspublished """
        key_char = line[0]
        data     = line[1:-1]
        if   key_char == "C":
            self.root_catalog     = data
        elif key_char == "X":
            self.certificate      = data
        elif key_char == "H":
            self.history_database = data
        elif key_char == "T":
            self.last_modified    = datetime.fromtimestamp(int(data), tz=tzutc())
        elif key_char == "R":
            self.root_hash        = data
        elif key_char == "D":
            self.ttl              = int(data)
        elif key_char == "S":
            self.revision         = int(data)
        elif key_char == "N":
            self.repository_name  = data
        elif key_char == "L":
            self.micro_catalog    = data
        else:
            raise UnknownManifestField(key_char)


    def _check_validity(self):
        """ Checks that all mandatory fields are found in .cvmfspublished """
        if not hasattr(self, 'root_catalog'):
            raise ManifestValidityError("Manifest lacks a root catalog entry")
        if not hasattr(self, 'root_hash'):
            raise ManifestValidityError("Manifest lacks a root hash entry")
        if not hasattr(self, 'ttl'):
            raise ManifestValidityError("Manifest lacks a TTL entry")
        if not hasattr(self, 'revision'):
            raise ManifestValidityError("Manifest lacks a revision entry")
        if not hasattr(self, 'repository_name'):
            raise ManifestValidityError("Manifest lacks a repository name")

@@ -1237,24 +1237,25 @@
 catalog     
+ 
 = data%0A     
@@ -1279,9 +1279,9 @@
 == %22
-X
+R
 %22:%0A 
@@ -1300,19 +1300,20 @@
 elf.
-certificate
+root_hash   
     
@@ -1351,9 +1351,9 @@
 == %22
-H
+B
 %22:%0A 
@@ -1372,31 +1372,37 @@
 elf.
-history_database = 
+root_catalog_size = int(
 data
+)
 %0A   
@@ -1424,17 +1424,17 @@
 har == %22
-T
+X
 %22:%0A     
@@ -1449,72 +1449,104 @@
 elf.
-last_modified
+certificate
     
+   
 = dat
-etime.fromtimestamp(int(data), tz=tzutc())
+a%0A        elif key_char == %22H%22:%0A            self.history_database  = data
 %0A   
@@ -1560,33 +1560,33 @@
 if key_char == %22
-R
+T
 %22:%0A            s
@@ -1593,31 +1593,73 @@
 elf.
-root_hash        = data
+last_modified     = datetime.fromtimestamp(int(data), tz=tzutc())
 %0A   
@@ -1711,32 +1711,33 @@
 tl              
+ 
 = int(data)%0A    
@@ -1788,32 +1788,33 @@
 evision         
+ 
 = int(data)%0A    
@@ -1873,16 +1873,17 @@
 y_name  
+ 
 = data%0A 
@@ -1941,24 +1941,25 @@
 _catalog    
+ 
 = data%0A     

set manifest field 'B' as root_catalog_size