# Copyright (C) 2009 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

"""Format unique/missing revisions as HTML."""

from cgi import escape
import codecs
from cStringIO import StringIO

from bzrlib import errors
from bzrlib.branch import Branch
from bzrlib.missing import find_unmerged, iter_log_revisions

from bzrlib.plugins.explorer.lib.html_log import HtmlLogFormatter
from bzrlib.plugins.explorer.lib.i18n import gettext, N_
from bzrlib.plugins.explorer.lib.kinds import (
    ERROR_STATUS,
    WARNING_STATUS,
    GOOD_STATUS,
    html_status_message,
    )


def extra_revisions_as_html(branch, in_parent=False):
    """Format extra revisions (branch vs parent) as html.

    :param in_parent: if True, find the extra revisions in the parent
      branch instead of in the given branch
    """
    parent = branch.get_parent()
    if parent is None:
        return html_status_message(ERROR_STATUS,
            gettext("No parent location defined yet."))
    try:
        parent_branch = Branch.open(parent)
    except errors.NotBranchError, ex:
        return html_status_message(ERROR_STATUS,
                gettext("Not a branch: %s") % (ex.path,))
    except errors.ConnectionError:
        return html_status_message(ERROR_STATUS,
                gettext("Could not connect to branch: %s") % (parent,))
        
    if in_parent:
        restrict = "remote"
    else:
        restrict = "local"
    my_extra, parent_extra = _unmerged(branch, parent_branch, restrict)
    if in_parent:
        return _format_revisions(parent_extra, parent_branch,
            gettext("Revisions in parent branch but not here: %d"),
            gettext("All parent branch revisions are present here."))
    else:
        return _format_revisions(my_extra, branch,
            gettext("Revisions here but not in parent branch: %d"),
            gettext("All revisions present in parent branch."))


def _unmerged(local_branch, remote_branch, restrict):
    if remote_branch.base == local_branch.base:
        remote_branch = local_branch
    local_branch.lock_read()
    try:
        remote_branch.lock_read()
        try:
            return find_unmerged(local_branch, remote_branch, restrict,
                    backward=True)
        finally:
            remote_branch.unlock()
    finally:
        local_branch.unlock()


def _format_revisions(revisions, branch, total_msg, up_to_date_msg):
    if revisions:
        log_revs = list(iter_log_revisions(revisions, branch.repository,
            verbose=False))
        sio = codecs.getwriter('utf-8')(StringIO())
        #sio.encoding = 'utf-8'
        try:
            summary = total_msg % len(log_revs)
            sio.write(html_status_message(WARNING_STATUS, summary))
            sio.write('<br>')
            lf = HtmlLogFormatter(sio)
            lf.begin_log()
            for log_rev in log_revs:
                lf.log_revision(log_rev)
            lf.end_log()
            return sio.getvalue().decode('utf-8')
        finally:
            sio.close()
    else:
        return html_status_message(GOOD_STATUS, up_to_date_msg)
