class ModelCopySelected(object):
    """
    Implemantation MVC de la procedure copySelected
    """
    def __init__(self):
        """
        """
        self.__label = "Un moment..."
        self.startSignal = Signal()
        self.refreshSignal = Signal()
        self.finishSignal = Signal()
        self.NbrJobsSignal = Signal()

    def start(self, lstFiles):
        """ 
        Lance les calculs
        
        @param lstFiles: list of files to process
        """
        self.startSignal.emit(self.__label, max(1, len(lstFiles)))
        if config.Filigrane:
            filigrane = Signature(config.FiligraneSource)
        else:
            filigrane = None

        SelectedDir = os.path.join(config.DefaultRepository, config.SelectedDirectory)
        self.refreshSignal.emit(-1, "copie des fichiers existants")
        if not os.path.isdir(SelectedDir):     fileutils.mkdir(SelectedDir)
#####first of all : copy the subfolders into the day folder to help mixing the files
        for day in os.listdir(SelectedDir):
            for File in os.listdir(os.path.join(SelectedDir, day)):
                if File.find(config.PagePrefix) == 0:
                    if os.path.isdir(os.path.join(SelectedDir, day, File)):
                        for strImageFile in os.listdir(os.path.join(SelectedDir, day, File)):
                            src = os.path.join(SelectedDir, day, File, strImageFile)
                            dst = os.path.join(SelectedDir, day, strImageFile)
                            if os.path.isfile(src) and not os.path.exists(dst):
                                shutil.move(src, dst)
                            if (os.path.isdir(src)) and (os.path.split(src)[1] in [config.ScaledImages["Suffix"], config.Thumbnails["Suffix"]]):
                                shutil.rmtree(src)

#######then copy the selected files to their folders###########################        
        globalCount = 0
        for File in lstFiles:
            dest = os.path.join(SelectedDir, File)
            src = os.path.join(config.DefaultRepository, File)
            destdir = os.path.dirname(dest)
            self.refreshSignal.emit(globalCount, File)
            globalCount += 1
            if not os.path.isdir(destdir):
                fileutils.makedir(destdir)
            if not os.path.exists(dest):
                if filigrane:
                    image = Image.open(src)
                    filigrane.substract(image).save(dest, quality=config.FiligraneQuality, optimize=config.FiligraneOptimize, progressive=config.FiligraneOptimize)
                else:
                    shutil.copy(src, dest)
                try:
                    os.chmod(dest, config.DefaultFileMode)
                except OSError:
                    logger.warning("In ModelCopySelected: unable to chmod %s", dest)
            else :
                logger.info("In ModelCopySelected: %s already exists", dest)
######copy the comments of the directory to the Selected directory 
        AlreadyDone = []
        for File in lstFiles:
            directory = os.path.split(File)[0]
            if directory in AlreadyDone:
                continue
            else:
                AlreadyDone.append(directory)
                dst = os.path.join(SelectedDir, directory, config.CommentFile)
                src = os.path.join(config.DefaultRepository, directory, config.CommentFile)
                if os.path.isfile(src):
                    shutil.copy(src, dst)
        self.finishSignal.emit()
class ModelRangeTout(object):
    """Implemantation MVC de la procedure rangeTout
    moves all the JPEG files to a directory named from 
    their day and with the name according to the time"""

    def __init__(self):
        """
        """
        self.__label = "Initial renaming of new images .... "
        self.startSignal = Signal()
        self.refreshSignal = Signal()
        self.finishSignal = Signal()
        self.NbrJobsSignal = Signal()


    def start(self, rootDir):
        """ Lance les calculs
        
        @param rootDir: top level directory to start processing
        @return: 2tuple containing the list of all images and the start-index
        @rtype: (list,integer)
        """
        config.DefaultRepository = rootDir
        AllJpegs = fileutils.findFiles(rootDir)
        AllFilesToProcess = []
        AllreadyDone = []
        NewFiles = []
        uid = os.getuid()
        gid = os.getgid()
        for i in AllJpegs:
            if i.find(config.TrashDirectory) == 0: continue
            if i.find(config.SelectedDirectory) == 0: continue
            try:
                a = int(i[:4])
                m = int(i[5:7])
                j = int(i[8:10])
                if (a >= 0000) and (m <= 12) and (j <= 31) and (i[4] in ["-", "_", "."]) and (i[7] in ["-", "_"]):
                    AllreadyDone.append(i)
                else:
                    AllFilesToProcess.append(i)
            except ValueError:
                AllFilesToProcess.append(i)
        AllFilesToProcess.sort()
        NumFiles = len(AllFilesToProcess)
        self.startSignal.emit(self.__label, NumFiles)
        for h in range(NumFiles):
            i = AllFilesToProcess[h]
            self.refreshSignal.emit(h, i)
            myPhoto = Photo(i, dontCache=True)
            data = myPhoto.readExif()
            try:
                datei, heurei = data["Heure"].split()
                date = re.sub(":", "-", datei)
                heurej = re.sub(":", "h", heurei, 1)
                model = data["Modele"].split(",")[-1]
                heure = unicode2ascii("%s-%s.jpg" % (re.sub(":", "m", heurej, 1), re.sub("/", "", re.sub(" ", "_", model))))
            except ValueError:
                date = time.strftime("%Y-%m-%d", time.gmtime(os.path.getctime(os.path.join(rootDir, i))))
                heure = unicode2ascii("%s-%s.jpg" % (time.strftime("%Hh%Mm%S", time.gmtime(os.path.getctime(os.path.join(rootDir, i)))), re.sub("/", "-", re.sub(" ", "_", os.path.splitext(i)[0]))))
            if not (os.path.isdir(os.path.join(rootDir, date))) :
                fileutils.mkdir(os.path.join(rootDir, date))
#            strImageFile = os.path.join(rootDir, date, heure)
            ToProcess = os.path.join(date, heure)
            bSkipFile = False
            for strImageFile in fileutils.list_files_in_named_dir(rootDir, date, heure):
                logger.warning("%s -x-> %s", i, strImageFile)
                existing = Photo(strImageFile, dontCache=True)
                try:
                    existing.readExif()
                    originalName = existing.exif["Exif.Photo.UserComment"]
                except:
                    logger.error("in ModelRangeTout: reading Exif for %s", i)
                else:
                    if "human_value" in dir(originalName):
                        originalName = originalName.human_value
                    if os.path.basename(originalName) == os.path.basename(i):
                        logger.info("File already in repository, leaving as it is")
                        bSkipFile = True
                        continue #to next file, i.e. leave the existing one
            if bSkipFile:
                continue
            else:
                strImageFile = os.path.join(rootDir, date, heure)
            if os.path.isfile(strImageFile):
                s = 0
                for j in os.listdir(os.path.join(rootDir, date)):
                    if j.find(heure[:-4]) == 0:s += 1
                ToProcess = os.path.join(date, heure[:-4] + "-%s.jpg" % s)
                strImageFile = os.path.join(rootDir, ToProcess)
            shutil.move(os.path.join(rootDir, i), strImageFile)
            try:
                os.chown(strImageFile, uid, gid)
                os.chmod(strImageFile, config.DefaultFileMode)
            except OSError:
                logger.warning("in ModelRangeTout: unable to chown ot chmod  %s" , strImageFile)
            myPhoto = Photo(strImageFile, dontCache=True)
#            Save the old image name in exif tag
            myPhoto.storeOriginalName(i)

            if config.AutoRotate:
                myPhoto.autorotate()
            AllreadyDone.append(ToProcess)
            NewFiles.append(ToProcess)
        AllreadyDone.sort()
        self.finishSignal.emit()

        if len(NewFiles) > 0:
            FirstImage = min(NewFiles)
            return AllreadyDone, AllreadyDone.index(FirstImage)
        else:
            return AllreadyDone, 0
class ModelProcessSelected(object):
    """
    Implemantation MVC de la procedure processSelected
    """
    def __init__(self):
        """
        """
        self.__label = "Un moment..."
        self.startSignal = Signal()
        self.refreshSignal = Signal()
        self.finishSignal = Signal()
        self.NbrJobsSignal = Signal()


    def start(self, lstFiles):
        """ 
        Lance les calculs pour "processSelected"
        i.e. 
        
        @param lstFiles: list of files to process
        """

        def splitIntoPages(pathday, globalCount):
            """Split a directory (pathday) into pages of 20 images (see config.NbrPerPage)
            
            @param pathday:
            @param globalCount:
            @return: the number of images for current page   
            """
            logger.debug("In splitIntoPages %s %s", pathday, globalCount)
            files = []
            for  i in os.listdir(pathday):
                if os.path.splitext(i)[1] in config.Extensions:files.append(i)
            files.sort()
            if  len(files) > config.NbrPerPage:
                pages = 1 + (len(files) - 1) / config.NbrPerPage
                for i in range(1, pages + 1):
                    folder = os.path.join(pathday, config.PagePrefix + str(i))
                    fileutils.mkdir(folder)
                for j in range(len(files)):
                    i = 1 + (j) / config.NbrPerPage
                    filename = os.path.join(pathday, config.PagePrefix + str(i), files[j])
                    self.refreshSignal.emit(globalCount, files[j])
                    globalCount += 1
                    shutil.move(os.path.join(pathday, files[j]), filename)
                    scaleImage(filename, filigrane)
            else:
                for j in files:
                    self.refreshSignal.emit(globalCount, j)
                    globalCount += 1
                    scaleImage(os.path.join(pathday, j), filigrane)
            return globalCount

        def arrangeOneFile(dirname, filename):
            """
            @param dirname:
            @param filename:
            """
            try:
                timetuple = time.strptime(filename[:19], "%Y-%m-%d_%Hh%Mm%S")
                suffix = filename[19:]
            except ValueError:
                try:
                    timetuple = time.strptime(filename[:11], "%Y-%m-%d_")
                    suffix = filename[11:]
                except ValueError:
                    logger.warning("Unable to handle such file: %s" % filename)
                    return
            daydir = os.path.join(SelectedDir, time.strftime("%Y-%m-%d", timetuple))
            os.mkdir(daydir)
            shutil.move(os.path.join(dirname, filename), os.path.join(daydir, time.strftime("%Hh%Mm%S", timetuple) + suffix))

        logger.debug("In Process Selected" + " ".join(lstFiles))
        self.startSignal.emit(self.__label, max(1, len(lstFiles)))
        if config.Filigrane:
            filigrane = Signature(config.FiligraneSource)
        else:
            filigrane = None

        SelectedDir = os.path.join(config.DefaultRepository, config.SelectedDirectory)
        self.refreshSignal.emit(-1, "copie des fichiers existants")
        if not os.path.isdir(SelectedDir):
            fileutils.mkdir(SelectedDir)
#####first of all : copy the subfolders into the day folder to help mixing the files
        AlsoProcess = 0
        for day in os.listdir(SelectedDir):
#if SingleDir : revert to a foldered structure
            DayOrFile = os.path.join(SelectedDir, day)
            if os.path.isfile(DayOrFile):
                arrangeOneFile(SelectedDir, day)
                AlsoProcess += 1
#end SingleDir normalization
            elif os.path.isdir(DayOrFile):
                if day in [config.ScaledImages["Suffix"], config.Thumbnails["Suffix"]]:
                    fileutils.recursive_delete(DayOrFile)
                elif day.find(config.PagePrefix) == 0: #subpages in SIngleDir mode that need to be flatten
                    for File in os.listdir(DayOrFile):
                        if     os.path.isfile(os.path.join(DayOrFile, File)):
                            arrangeOneFile(DayOrFile, File)
                            AlsoProcess += 1
#                        elif os.path.isdir(os.path.join(DayOrFile,File)) and File in [config.ScaledImages["Suffix"],config.Thumbnails["Suffix"]]:
#                            recursive_delete(os.path.join(DayOrFile,File))
                    fileutils.recursive_delete(DayOrFile)
                else:
                    for File in os.listdir(DayOrFile):
                        if File.find(config.PagePrefix) == 0:
                            if os.path.isdir(os.path.join(SelectedDir, day, File)):
                                for strImageFile in os.listdir(os.path.join(SelectedDir, day, File)):
                                    src = os.path.join(SelectedDir, day, File, strImageFile)
                                    dst = os.path.join(SelectedDir, day, strImageFile)
                                    if os.path.isfile(src) and not os.path.exists(dst):
                                        shutil.move(src, dst)
                                        AlsoProcess += 1
                                    if (os.path.isdir(src)) and (os.path.split(src)[1] in [config.ScaledImages["Suffix"], config.Thumbnails["Suffix"]]):
                                        shutil.rmtree(src)
                        else:
                            if os.path.splitext(File)[1] in config.Extensions:
                                AlsoProcess += 1

#######then copy the selected files to their folders###########################        
        for File in lstFiles:
            dest = os.path.join(SelectedDir, File)
            src = os.path.join(config.DefaultRepository, File)
            destdir = os.path.dirname(dest)
            if not os.path.isdir(destdir):
                fileutils.makedir(destdir)
            if not os.path.exists(dest):
                logger.info("copie de %s " % File)
                shutil.copy(src, dest)
                try:
                    os.chmod(dest, config.DefaultFileMode)
                except OSError:
                    logger.warning("Unable to chmod %s" % dest)
                AlsoProcess += 1
            else :
                logger.warning("%s existe déja" % dest)
        if AlsoProcess > 0:self.NbrJobsSignal.emit(AlsoProcess)
######copy the comments of the directory to the Selected directory 
        AlreadyDone = []
        for File in lstFiles:
            directory = os.path.split(File)[0]
            if directory in AlreadyDone:
                continue
            else:
                AlreadyDone.append(directory)
                dst = os.path.join(SelectedDir, directory, config.CommentFile)
                src = os.path.join(config.DefaultRepository, directory, config.CommentFile)
                if os.path.isfile(src):
                    shutil.copy(src, dst)

########finaly recreate the structure with pages or make a single page ########################
        logger.debug("in ModelProcessSelected, SelectedDir= %s", SelectedDir)
        dirs = [ i for i in os.listdir(SelectedDir) if os.path.isdir(os.path.join(SelectedDir, i))]
        dirs.sort()
        if config.ExportSingleDir: #SingleDir
            #first move all files to the root
            for day in dirs:
                daydir = os.path.join(SelectedDir, day)
                for filename in os.listdir(daydir):
                    try:
                        timetuple = time.strptime(day[:10] + "_" + filename[:8], "%Y-%m-%d_%Hh%Mm%S")
                        suffix = filename[8:]
                    except ValueError:
                        try:
                            timetuple = time.strptime(day[:10], "%Y-%m-%d")
                            suffix = filename
                        except ValueError:
                            logger.info("Unable to handle dir: %s\t file: %s" , day, filename)
                            continue
                    src = os.path.join(daydir, filename)
                    dst = os.path.join(SelectedDir, time.strftime("%Y-%m-%d_%Hh%Mm%S", timetuple) + suffix)
                    shutil.move(src, dst)
                fileutils.recursive_delete(daydir)
            splitIntoPages(SelectedDir, 0)
        else: #Multidir
            logger.debug("in Multidir, dirs= " + " ".join(dirs))
            globalCount = 0
            for day in dirs:
                globalCount = splitIntoPages(os.path.join(SelectedDir, day), globalCount)

        self.finishSignal.emit()