# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of logilab-common.
#
# logilab-common is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option) any
# later version.
#
# logilab-common 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 Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
"""Manipulation of upstream change log files.

The upstream change log files format handled is simpler than the one
often used such as those generated by the default Emacs changelog mode.

Sample ChangeLog format::

  Change log for project Yoo
  ==========================

   --
      * add a new functionality

  2002-02-01 -- 0.1.1
      * fix bug #435454
      * fix bug #434356

  2002-01-01 -- 0.1
      * initial release


There is 3 entries in this change log, one for each released version and one
for the next version (i.e. the current entry).
Each entry contains a set of messages corresponding to changes done in this
release.
All the non empty lines before the first entry are considered as the change
log title.
"""

__docformat__ = "restructuredtext en"

import sys
from stat import S_IWRITE

from six import string_types

BULLET = '*'
SUBBULLET = '-'
INDENT = ' ' * 4

class NoEntry(Exception):
    """raised when we are unable to find an entry"""

class EntryNotFound(Exception):
    """raised when we are unable to find a given entry"""

class Version(tuple):
    """simple class to handle soft version number has a tuple while
    correctly printing it as X.Y.Z
    """
    def __new__(cls, versionstr):
        if isinstance(versionstr, string_types):
            versionstr = versionstr.strip(' :') # XXX (syt) duh?
            parsed = cls.parse(versionstr)
        else:
            parsed = versionstr
        return tuple.__new__(cls, parsed)

    @classmethod
    def parse(cls, versionstr):
        versionstr = versionstr.strip(' :')
        try:
            return [int(i) for i in versionstr.split('.')]
        except ValueError as ex:
            raise ValueError("invalid literal for version '%s' (%s)"%(versionstr, ex))

    def __str__(self):
        return '.'.join([str(i) for i in self])

# upstream change log #########################################################

class ChangeLogEntry(object):
    """a change log entry, i.e. a set of messages associated to a version and
    its release date
    """
    version_class = Version

    def __init__(self, date=None, version=None, **kwargs):
        self.__dict__.update(kwargs)
        if version:
            self.version = self.version_class(version)
        else:
            self.version = None
        self.date = date
        self.messages = []

    def add_message(self, msg):
        """add a new message"""
        self.messages.append(([msg], []))

    def complete_latest_message(self, msg_suite):
        """complete the latest added message
        """
        if not self.messages:
            raise ValueError('unable to complete last message as there is no previous message)')
        if self.messages[-1][1]: # sub messages
            self.messages[-1][1][-1].append(msg_suite)
        else: # message
            self.messages[-1][0].append(msg_suite)

    def add_sub_message(self, sub_msg, key=None):
        if not self.messages:
            raise ValueError('unable to complete last message as there is no previous message)')
        if key is None:
            self.messages[-1][1].append([sub_msg])
        else:
            raise NotImplementedError("sub message to specific key are not implemented yet")

    def write(self, stream=sys.stdout):
        """write the entry to file """
        stream.write('%s  --  %s\n' % (self.date or '', self.version or ''))
        for msg, sub_msgs in self.messages:
            stream.write('%s%s %s\n' % (INDENT, BULLET, msg[0]))
            stream.write(''.join(msg[1:]))
            if sub_msgs:
                stream.write('\n')
            for sub_msg in sub_msgs:
                stream.write('%s%s %s\n' % (INDENT * 2, SUBBULLET, sub_msg[0]))
                stream.write(''.join(sub_msg[1:]))
            stream.write('\n')

        stream.write('\n\n')

class ChangeLog(object):
    """object representation of a whole ChangeLog file"""

    entry_class = ChangeLogEntry

    def __init__(self, changelog_file, title=''):
        self.file = changelog_file
        self.title = title
        self.additional_content = ''
        self.entries = []
        self.load()

    def __repr__(self):
        return '<ChangeLog %s at %s (%s entries)>' % (self.file, id(self),
                                                      len(self.entries))

    def add_entry(self, entry):
        """add a new entry to the change log"""
        self.entries.append(entry)

    def get_entry(self, version='', create=None):
        """ return a given changelog entry
        if version is omitted, return the current entry
        """
        if not self.entries:
            if version or not create:
                raise NoEntry()
            self.entries.append(self.entry_class())
        if not version:
            if self.entries[0].version and create is not None:
                self.entries.insert(0, self.entry_class())
            return self.entries[0]
        version = self.version_class(version)
        for entry in self.entries:
            if entry.version == version:
                return entry
        raise EntryNotFound()

    def add(self, msg, create=None):
        """add a new message to the latest opened entry"""
        entry = self.get_entry(create=create)
        entry.add_message(msg)

    def load(self):
        """ read a logilab's ChangeLog from file """
        try:
            stream = open(self.file)
        except IOError:
            return
        last = None
        expect_sub = False
        for line in stream.readlines():
            sline = line.strip()
            words = sline.split()
            # if new entry
            if len(words) == 1 and words[0] == '--':
                expect_sub = False
                last = self.entry_class()
                self.add_entry(last)
            # if old entry
            elif len(words) == 3 and words[1] == '--':
                expect_sub = False
                last = self.entry_class(words[0], words[2])
                self.add_entry(last)
            # if title
            elif sline and last is None:
                self.title = '%s%s' % (self.title, line)
            # if new entry
            elif sline and sline[0] == BULLET:
                expect_sub = False
                last.add_message(sline[1:].strip())
            # if new sub_entry
            elif expect_sub and sline and sline[0] == SUBBULLET:
                last.add_sub_message(sline[1:].strip())
            # if new line for current entry
            elif sline and last.messages:
                last.complete_latest_message(line)
            else:
                expect_sub = True
                self.additional_content += line
        stream.close()

    def format_title(self):
        return '%s\n\n' % self.title.strip()

    def save(self):
        """write back change log"""
        # filetutils isn't importable in appengine, so import locally
        from logilab.common.fileutils import ensure_fs_mode
        ensure_fs_mode(self.file, S_IWRITE)
        self.write(open(self.file, 'w'))

    def write(self, stream=sys.stdout):
        """write changelog to stream"""
        stream.write(self.format_title())
        for entry in self.entries:
            entry.write(stream)

