#!/usr/bin/python
# -*- coding: utf-8 -*-

#  Copyright © 2013  B. Clausius <barcc@gmx.de>
#
#  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 3 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, see <http://www.gnu.org/licenses/>.

from __future__ import print_function, division, unicode_literals

import bzrlib.errors
import bzrlib.ignores
import bzrlib.workingtree
import bzrlib.uncommit

from bzrlib import IGNORE_FILENAME
from bzrlib.revision import NULL_REVISION
# Just to make sure… . The plugin should not depend on bzrlib and has to define the constants.
assert IGNORE_FILENAME == '.bzrignore'
assert NULL_REVISION == 'null:'

import bzrlib.plugin
bzrlib.plugin.load_plugins()

import foreign


def find_wt_basedir(path):
    if not path:
        return None, None
    try:
        wt, wt_path = bzrlib.workingtree.WorkingTree.open_containing(path)
        return wt.basedir, wt_path
    except (bzrlib.errors.NotBranchError, bzrlib.errors.NoWorkingTree):
        return None, path
        
def _open_wt(func):
    def return_func(wt_basedir, *args):
        try:
            wt = bzrlib.workingtree.WorkingTree.open_containing(wt_basedir)[0]
        except (bzrlib.errors.NotBranchError, bzrlib.errors.NoWorkingTree):
            return
        return func(wt, *args)
    return return_func
    
@_open_wt
def revert(wt, files=None):
    '''Revert files in 
    
    files: list of relative filenames, or None to revert all
    '''
    wt.revert(files)
    
@_open_wt
def add(wt, files):
    '''Add files
    
    files: list of relative filenames, if None or empty do smart add
    '''
    if files:
        wt.add(files)
    else:
        wt.smart_add([wt.basedir])
        
@_open_wt
def ignore(wt, files):
    bzrlib.ignores.tree_ignores_add_patterns(wt, files)
    
@_open_wt
def uncommit(wt):
    #TODO: add local arg (see commit)
    old_revid = wt.branch.last_revision()
    old_rev = wt.branch.repository.get_revision(old_revid)
    bzrlib.uncommit.uncommit(wt.branch, tree=wt, local=False, keep_tags=False)
    return old_rev.message
    
@_open_wt
def set_parent(wt, location):
    wt.branch.set_parent(location)
    return wt.branch.get_parent() or ''
    
@_open_wt
def set_push_location(wt, location):
    wt.branch.set_push_location(location)
    return wt.branch.get_push_location() or ''
    
@_open_wt
def set_submit_branch(wt, location):
    wt.branch.set_submit_branch(location)
    return wt.branch.get_submit_branch() or ''
    
@_open_wt
def commit(wt, message, specific_files, local, unknowns, pointless):
    # All we care about is if there is a single unknown, so if this loop is
    # entered, then there are unknown files.
    for unused_path in wt.unknowns():
        if not unknowns:
            return 'unknowns'
        break
        
    try:
        rev_id = wt.commit(message,
                   allow_pointless=pointless,
                   strict=False,
                   local=local,
                   specific_files=specific_files)
    except bzrlib.errors.PointlessCommit:
        return 'pointless'
    return 'error' if rev_id is None else 'success'
    
@_open_wt
def save_commitmessage(wt, message):
    # We store in branch's config, which can be a problem if two gcommit
    # are done in two checkouts of one single branch (comments overwrite
    # each other). Ideally should be in working tree. But uncommit does
    # not always have a working tree, though it always has a branch.
    config = wt.branch.get_config()
    # should it be named "gtk_" or some more neutral name ("gui_" ?) to
    # be compatible with qbzr in the future?
    if message is not None:
        config.set_user_option('gtk_global_commit_message', message)
    return config.get_user_option('gtk_global_commit_message')
    
@_open_wt
def get_pending_revisions(wt):
    is_checkout = wt.branch is not None and wt.branch.get_bound_location() is not None
    wt.lock_read()
    try:
        pending_revisions = list(foreign.pending_revisions(wt))
    finally:
        wt.unlock()
    return is_checkout, pending_revisions
    
    
