# -*- coding: utf-8 -*-

"""
    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/>.

    @author: hgg
"""
from os.path import basename

from module.utils import fs_encode
from module.plugins.Hook import Hook
from module.PyFile import PyFile


class UnSkipOnFail(Hook):
    __name__ = 'UnSkipOnFail'
    __version__ = '0.01'
    __description__ = """When a download fails, restart skipped duplicates"""
    __config__ = [("activated", "bool", "Activated", True)]
    __author_name__ = "hagg"
    __author_mail__ = ""

    def downloadFailed(self, pyfile):
        pyfile_name = basename(pyfile.name)
        pid = pyfile.package().id
        msg = 'look for skipped duplicates for %s (pid:%s)...'
        self.logInfo(msg % (pyfile_name, pid))
        dups = self.findDuplicates(pyfile)
        for link in dups:
            # check if link is "skipped"(=4)
            if link.status == 4:
                lpid = link.packageID
                self.logInfo('restart "%s" (pid:%s)...' % (pyfile_name, lpid))
                self.setLinkStatus(link, "queued")

    def findDuplicates(self, pyfile):
        """ Search all packages for duplicate links to "pyfile".
            Duplicates are links that would overwrite "pyfile".
            To test on duplicity the package-folder and link-name
            of twolinks are compared (basename(link.name)).
            So this method returns a list of all links with equal
            package-folders and filenames as "pyfile", but except
            the data for "pyfile" iotselöf.
            It does MOT check the link's status.
        """
        dups = []
        pyfile_name = fs_encode(basename(pyfile.name))
        # get packages (w/o files, as most file data is useless here)
        queue = self.core.api.getQueue()
        for package in queue:
            # check if package-folder equals pyfile's package folder
            if fs_encode(package.folder) == fs_encode(pyfile.package().folder):
                # now get packaged data w/ files/links
                pdata = self.core.api.getPackageData(package.pid)
                if pdata.links:
                    for link in pdata.links:
                        link_name = fs_encode(basename(link.name))
                        # check if link name collides with pdata's name
                        if link_name == pyfile_name:
                            # at last check if it is not pyfile itself
                            if link.fid != pyfile.id:
                                dups.append(link)
        return dups

    def setLinkStatus(self, link, new_status):
        """ Change status of "link" to "new_status".
            "link" has to be a valid FileData object,
            "new_status" has to be a valid status name
              (i.e. "queued" for this Plugin)
            It creates a temporary PyFile object using
            "link" data, changes its status, and tells
            the core.files-manager to save its data.
        """
        pyfile = PyFile(self.core.files,
                        link.fid,
                        link.url,
                        link.name,
                        link.size,
                        link.status,
                        link.error,
                        link.plugin,
                        link.packageID,
                        link.order)
        pyfile.setStatus(new_status)
        self.core.files.save()
        pyfile.release()
