
# 
#   Copyright 2016 RIFT.IO Inc
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#

import hashlib
import re

def checksum_string(s):
    return hashlib.md5(s.encode('utf-8')).hexdigest()


def checksum(fd):
    """ Calculate a md5 checksum of fd file handle

    Arguments:
      fd: A file descriptor return from open() call

    Returns:
      A md5 checksum of the file

    """
    pos = fd.tell()
    try:
        current = hashlib.md5()
        while True:
            data = fd.read(2 ** 16)
            if len(data) == 0:
                return current.hexdigest()
            current.update(data)
    finally:
        fd.seek(pos)


class ArchiveChecksums(dict):
    @classmethod
    def from_file_desc(cls, fd):
        checksum_pattern = re.compile(r"(\S+)\s+(\S+)")
        checksums = dict()

        pos = fd.tell()
        try:
            for line in (line.decode('utf-8').strip() for line in fd if line):

                # Skip comments
                if line.startswith('#'):
                    continue

                # Skip lines that do not contain the pattern we are looking for
                result = checksum_pattern.search(line)
                if result is None:
                    continue

                chksum, filepath = result.groups()
                checksums[filepath] = chksum

        finally:
            fd.seek(pos)

        return cls(checksums)

    def to_string(self):
        string = ""
        for file_name, file_checksum in self.items():
            string += "{}  {}\n".format(file_name, file_checksum)

        return string
