#
# task_gui.py: Choose tasks for installation
#
# Copyright 2006 Red Hat, Inc.
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
#

import gtk
import gtk.glade
import gobject
import gui
from iw_gui import *
from rhpl.translate import _, N_
from constants import productName

from netconfig_dialog import NetworkConfigurator
import network

from yuminstall import AnacondaYumRepo
import yum.Errors

import logging
log = logging.getLogger("anaconda")

class TaskWindow(InstallWindow):
    def getNext(self):
        if self.xml.get_widget("customRadio").get_active():
            self.dispatch.skipStep("group-selection", skip = 0)
        else:
            self.dispatch.skipStep("group-selection", skip = 1)

        tasks = self.xml.get_widget("taskList").get_model()
        
        # Quick hack to handle overlapping groups in tasks for an installclass
        for (cb, task, grps) in tasks:
            if not cb:
                map(self.backend.deselectGroup, grps)
        for (cb, task, grps) in tasks:
            if cb:
                map(self.backend.selectGroup, grps)

        if self.anaconda.id.instClass.allowExtraRepos:
            repos = self.xml.get_widget("repoList").get_model()
            for (cb, reponame, repo) in repos:
                if cb:
                    repo.enable()

                    # Setup any repositories that were in the installclass's
                    # default list.
                    if not repo.ready():
                        self._setupRepo(repo)
                else:
                    repo.disable()

    def groupsInstalled(self, lst):
        # FIXME: yum specific
        rc = False
        for gid in lst:
            g = self.backend.ayum.comps.return_group(gid)
            if g and not g.selected:
                return False
            elif g:
                rc = True
        return rc

    def groupsExist(self, lst):
        # FIXME: yum specific
        for gid in lst:
            g = self.backend.ayum.comps.return_group(gid)
            if not g:
                return False
        return True

    def _setupRepo(self, repo):
        try:
            self.backend.doRepoSetup(self.anaconda, repo.id, fatalerrors = False)
            log.info("added repository %s with with source URL %s" % (repo.name, repo.baseurl[0]))
        except yum.Errors.RepoError, e:
            self.intf.messageWindow(_("Error"),
                  _("Unable to read package metadata from repository.  "
                    "This may be due to a missing repodata directory.  "
                    "Please ensure that your repository has been "
                    "correctly generated.\n\n%s" %(e,)),
                                    type="ok", custom_icon="error")
            self.backend.ayum.repos.delete(repo.id)
            return False

        if not repo.groups_added:
            self.intf.messageWindow(_("Warning"),
                           _("Unable to find a group file for %s.  "
                             "This will make manual selection of packages "
                             "from the repository not work") %(repo.id,),
                                    type="warning")

        return True

    def _addRepo(self, *args):
        if not network.hasActiveNetDev():
            net = NetworkConfigurator(self.anaconda.id.network)
            ret = net.run()
            net.destroy()
            if ret == gtk.RESPONSE_CANCEL:
                return gtk.RESPONSE_CANCEL
        
        (dxml, dialog) = gui.getGladeWidget("addrepo.glade", "addRepoDialog")
        gui.addFrame(dialog)

        lbl = dxml.get_widget("descLabel")
        txt = lbl.get_text()
        lbl.set_text(txt %(productName,))
        
        dialog.show_all()

        while 1:
            rc = dialog.run()
            if rc == gtk.RESPONSE_CANCEL:
                break
        
            reponame = dxml.get_widget("nameEntry").get_text()
            reponame.strip()
            if len(reponame) == 0:
                self.intf.messageWindow(_("Invalid Repository Name"),
                                        _("You must provide a non-zero length "
                                          "repository name."))
                continue

            repourl = dxml.get_widget("urlEntry").get_text()
            repourl.strip()
            if (len(repourl) == 0 or not
                (repourl.startswith("http://") or
                 repourl.startswith("ftp://"))):
                self.intf.messageWindow(_("Invalid Repository URL"),
                                        _("You must provide an HTTP or FTP "
                                          "URL to a repository."))
                continue

            # FIXME: this is yum specific
            repo = AnacondaYumRepo(uri=repourl, repoid=reponame)
            repo.name = reponame
            repo.basecachedir = self.backend.ayum.conf.cachedir
            repo.enable()

            try:
                self.backend.ayum.repos.add(repo)
            except yum.Errors.DuplicateRepoError, e:
                self.intf.messageWindow(_("Error"),
                      _("The repository %s has already been added.  Please "
                        "choose a different repository name and "
                        "URL.") % reponame, type="ok", custom_icon="error")
                continue

            if not self._setupRepo(repo):
                continue

            s = self.xml.get_widget("repoList").get_model()
            s.append([repo.isEnabled(), repo.name, repo])
            self.repos[repo.name] = (repo.baseurl[0], None)

            break

        dialog.destroy()
        return rc

    def _taskToggled(self, data, row, store):
        i = store.get_iter(int(row))
        val = store.get_value(i, 0)
        store.set_value(i, 0, not val)

    def _repoToggled(self, data, row, store):
        i = store.get_iter(int(row))
        val = store.get_value(i, 0)

        if not val and not network.hasActiveNetDev():
            net = NetworkConfigurator(self.anaconda.id.network)
            ret = net.run()
            net.destroy()
            if ret == gtk.RESPONSE_CANCEL:
                return
        
        store.set_value(i, 0, not val)

    def _createTaskStore(self):
        store = gtk.ListStore(gobject.TYPE_BOOLEAN,
                              gobject.TYPE_STRING,
                              gobject.TYPE_PYOBJECT)
        tl = self.xml.get_widget("taskList")
        tl.set_model(store)

        cbr = gtk.CellRendererToggle()
        col = gtk.TreeViewColumn('', cbr, active = 0)
        cbr.connect("toggled", self._taskToggled, store)
        tl.append_column(col)

        col = gtk.TreeViewColumn('Text', gtk.CellRendererText(), text = 1)
        col.set_clickable(False)
        tl.append_column(col)

        for (txt, grps) in self.tasks:
            if not self.groupsExist(grps):
                continue
            store.append([self.groupsInstalled(grps), _(txt), grps])

        return len(store)

    def _createRepoStore(self):
        store = gtk.ListStore(gobject.TYPE_BOOLEAN,
                              gobject.TYPE_STRING,
                              gobject.TYPE_PYOBJECT)
        tl = self.xml.get_widget("repoList")
        tl.set_model(store)

        cbr = gtk.CellRendererToggle()
        col = gtk.TreeViewColumn('', cbr, active = 0)
        cbr.connect("toggled", self._repoToggled, store)
        tl.append_column(col)

        col = gtk.TreeViewColumn('Text', gtk.CellRendererText(), text = 1)
        col.set_clickable(False)
        tl.append_column(col)

        for (reponame, uri) in self.repos.items():
            repoid = reponame.replace(" ", "")
            if not self.backend.ayum.repos.repos.has_key(repoid):
                continue
            repo = self.backend.ayum.repos.repos[repoid]
            store.append([repo.isEnabled(), repo.name, repo])
        
            
    def getScreen (self, anaconda):
        self.intf = anaconda.intf
        self.dispatch = anaconda.dispatch
        self.backend = anaconda.backend
        self.anaconda = anaconda

        self.tasks = anaconda.id.instClass.tasks
        self.repos = anaconda.id.instClass.repos

        (self.xml, vbox) = gui.getGladeWidget("tasksel.glade", "taskBox")

        lbl = self.xml.get_widget("mainLabel")
        if anaconda.id.instClass.description:
            lbl.set_text(_(anaconda.id.instClass.description))
        else:
            txt = lbl.get_text()
            lbl.set_text(txt %(productName,))

	custom = not self.dispatch.stepInSkipList("group-selection")
        if custom:
            self.xml.get_widget("customRadio").set_active(True)
        else:
            self.xml.get_widget("customRadio").set_active(False)

        if self._createTaskStore() == 0:
            self.xml.get_widget("cbVBox").hide()
            self.xml.get_widget("mainLabel").hide()

        self._createRepoStore()
        if not anaconda.id.instClass.allowExtraRepos:
            vbox.remove(self.xml.get_widget("addRepoBox"))

        self.xml.get_widget("addRepoButton").connect("clicked", self._addRepo)

        return vbox