from __future__ import absolute_import

import mock
import os
import unittest

from mercurial import (
    pycompat,
)

from tortoisehg.hgqt import (
    qtlib,
    repofilter,
    thgrepo,
)

import helpers

def setup_module():
    global _tmpdir
    _tmpdir = helpers.mktmpdir(__name__)

def _listitems(combo):
    return [pycompat.unicode(combo.itemText(i))
                             for i in pycompat.xrange(combo.count())]

class RepoFilterBarBranchTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        hg = helpers.HgClient(
            os.path.join(_tmpdir, pycompat.sysbytes(cls.__name__)))
        hg.init()
        hg.ftouch(b'a')
        hg.addremove()
        hg.commit(b'-m', b'commit to default')
        for name in (b'foo', b'bar', b'baz'):
            hg.update(b'0')
            hg.fappend(b'a', name + b'\n')
            hg.branch(name)
            hg.commit(b'-m', b'create %s branch' % name)
        hg.commit(b'--close-branch', b'-m', b'close baz branch')
        hg.update(b'foo')  # current branch will be listed first
        cls.repo = thgrepo.repository(path=hg.path)

    @classmethod
    def tearDownClass(cls):
        del cls.repo

    def setUp(self):
        qtlib.initfontcache(self.repo.ui)
        repoagent = self.repo._pyqtobj  # TODO
        self.widget = repofilter.RepoFilterBar(repoagent)
        self.branchchanged = mock.Mock()
        self.widget.branchChanged.connect(self.branchchanged)
        # without show(), action.setChecked() sometimes fails with
        # "illegal hardware instruction"
        self.widget.show()

    def tearDown(self):
        del self.widget
        qtlib._fontcache.clear()

    def test_open_branches(self):
        self.assertEqual([self.widget._allBranchesLabel,
                          'foo', 'default', 'bar'],
                         _listitems(self.widget._branchCombo))
        self.assertTrue(self.widget._branchCombo.isEnabled())
        self.assertFalse(self.branchchanged.called)

    def test_only_active_branches(self):
        self.widget._abranchAction.setChecked(False)
        self.widget._abranchAction.trigger()  # checked
        self.assertEqual([self.widget._allBranchesLabel,
                          'foo', 'bar'],
                         _listitems(self.widget._branchCombo))
        self.assertTrue(self.widget._branchCombo.isEnabled())
        self.assertFalse(self.branchchanged.called)

    def test_include_closed_branches(self):
        self.widget._cbranchAction.setChecked(False)
        self.widget._cbranchAction.trigger()  # checked
        self.assertEqual([self.widget._allBranchesLabel,
                         'foo',  'default', 'bar', 'baz'],
                         _listitems(self.widget._branchCombo))
        self.assertTrue(self.widget._branchCombo.isEnabled())
        self.assertFalse(self.branchchanged.called)

    def test_change_branch(self):
        self.widget.setBranch('foo')
        self.assertEqual('foo', self.widget.branch())
        self.branchchanged.assert_called_once_with('foo', False)

    def test_label_for_all_branches(self):
        self.widget.setBranch('')  # all branches
        self.assertEqual('', self.widget.branch())
        self.assertEqual(self.widget._allBranchesLabel,
                         pycompat.unicode(
                             self.widget._branchCombo.currentText()))

    def test_selected_inactive_branch_removed_from_list(self):
        self.widget.setBranch('default')
        self.branchchanged.reset_mock()
        self.widget._abranchAction.setChecked(False)
        self.widget._abranchAction.trigger()  # checked
        self.assertEqual('', self.widget.branch())  # fall back
        self.branchchanged.assert_called_once_with('', False)

    def test_selected_closed_branch_removed_from_list(self):
        self.widget._cbranchAction.setChecked(False)
        self.widget._cbranchAction.trigger()  # checked
        self.widget.setBranch('baz')
        self.branchchanged.reset_mock()
        self.widget._cbranchAction.trigger()  # unchecked
        self.assertEqual('', self.widget.branch())  # fall back
        self.branchchanged.assert_called_once_with('', False)

class RepoFilterBarEmptyBranchTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        hg = helpers.HgClient(
            os.path.join(_tmpdir, pycompat.sysbytes(cls.__name__)))
        hg.init()
        hg.ftouch(b'a')
        hg.addremove()
        hg.commit(b'-m', b'commit to default')
        hg.commit(b'--close-branch', b'-m', b'close default branch')
        cls.repo = thgrepo.repository(path=hg.path)

    @classmethod
    def tearDownClass(cls):
        del cls.repo

    def setUp(self):
        qtlib.initfontcache(self.repo.ui)
        repoagent = self.repo._pyqtobj  # TODO
        self.widget = repofilter.RepoFilterBar(repoagent)
        # without show(), action.setChecked() sometimes fails with
        # "illegal hardware instruction"
        self.widget.show()

    def tearDown(self):
        del self.widget
        qtlib._fontcache.clear()

    def test_empty_branch_combo_is_disabled(self):
        self.assertFalse(self.widget._branchCombo.isEnabled())

    def test_branch_combo_enabled_if_closed_branches_included(self):
        self.widget._cbranchAction.setChecked(False)
        self.widget._cbranchAction.trigger()  # checked
        self.assertTrue(self.widget._branchCombo.isEnabled())
