# -*- coding: UTF-8 -*-
'''
================================================================================
Project: SiriL-ic ( SiriL Image Companion )

This script structures the SiriL work folder into a subfolder, copies the
astronomical images into the subfolders, and builds the associated SiriL
script. It can also group scripts.
================================================================================
   Author:  M27trognondepomme <pebe92 (at) gmail.com>

This program is provided without any guarantee.

The license is  LGPL-v3
For details, see GNU General Public License, version 3 or later.
                       "https://www.gnu.org/licenses/gpl.html"
================================================================================
'''
import os
import sys
import shutil
import subprocess
import threading
import wx

from sirilic.lib.constantes import MASTERDIR, TEMPDIR, SRCDIR, TYPENAME, IMAGE
from sirilic.lib.tools import mkdirs, nettoyage_dossier, GestionThread


# ==============================================================================
class CopyThread(threading.Thread):
    def __init__(self, log, db, workdir, flagCopy=True, flagClean=True,
                 extDest=".fit"):
        threading.Thread.__init__(self)
        log.clear()
        self.param = (log, db, workdir, flagCopy, flagClean, extDest)
        self.overwriteFiles = False

    # --------------------------------------------------------------------------
    def run(self):
        (log, db, workdir, flagCopy, flagClean, extDest) = self.param
        task = GestionThread()
        task.SetRunning(self)

        # Calcul le nombre d'etape pour la barre de progression:
        StepCnt = 0
        for keystr, dbImage in db.GetDb().items():
            if db.Item_IsInitialised(keystr) == "uninitialized":
                continue
            for iodf in dbImage.db['Images']:
                if iodf.IsInitialised() == "":
                    continue
                StepCnt += 1
        log.SetStepNumber(StepCnt)

        # Construction de l'arborescence des dossiers
        StepCnt = 0
        log.print_ligne("-")
        log.print_titre('-', _('Building directories'))
        for keystr, dbImage in db.GetDb().items():
            objectname = dbImage.db['Object']
            layername = dbImage.db['LayerName']
            sessionname = dbImage.db['Session']
            if db.Item_IsInitialised(keystr) == "uninitialized":
                log.insert(_("Warning") + " " + keystr + " " +
                           _("uninitialized") + " => " + _("skipping") + '\n')
                continue
            full_dir = os.path.join(
                workdir, objectname, layername, sessionname)
            for iodf in dbImage.db['Images']:
                if task.IsAborted():
                    return
                if iodf.IsInitialised() == "":
                    continue
                if iodf.IsLib():
                    continue
                data = iodf.GetData()
                subdir = os.path.join(full_dir, data['typename'])
                if not os.path.exists(subdir):
                    log.insert(_("Make directory:") + " " + subdir + '\n')
                    mkdirs(subdir)
                else:  # le dossier existe, nettoyage si option active
                    if flagClean:
                        data = iodf.GetData()
                        srcExt = os.path.splitext(data['files'][0])[1]
                        nettoyage_dossier(log, subdir, srcExt)
                        srcdir = os.path.join(subdir, SRCDIR)
                        if os.path.exists(srcdir):
                            nettoyage_dossier(log, srcdir, "*.*")

            subdir = os.path.join(full_dir, MASTERDIR)
            if not os.path.exists(subdir):
                log.insert(_("Make directory:") + " " + subdir + '\n')
                mkdirs(subdir)
                log.insert("\n")
            subdir = os.path.join(workdir, objectname, TEMPDIR)
            if not os.path.exists(subdir):
                log.insert(_("Make directory:") + " " + subdir + '\n')
                mkdirs(subdir)
                log.insert("\n")

        # Copie des fichiers
        self.overwriteFiles = flagClean
        log.print_ligne("-")
        log.print_titre('-', _('COPYING TO SIRIL DIRECTORY'))
        log.print_ligne("-")
        for keystr, dbImage in db.GetDb().items():
            objectname = dbImage.db['Object']
            layername = dbImage.db['LayerName']
            sessionname = dbImage.db['Session']
            if db.Item_IsInitialised(keystr) == "uninitialized":
                continue
            log.print_ligne("-")
            full_dir = os.path.join(
                workdir, objectname, layername, sessionname)
            for iodf in dbImage.db['Images']:
                if iodf.IsInitialised() == "":
                    continue
                StepCnt += 1
                log.SetProgressBar(StepCnt)
                data = iodf.GetData()
                if iodf.IsLib():
                    copylib = False
                    if 'copylib' in data.keys():
                        copylib = data['copylib']

                    if not copylib and not iodf.IsSynthetic():
                        destfile = os.path.join(
                            full_dir, MASTERDIR,
                            "master-" + data['typename'][:-1].lower() + extDest)
                        srcfile = data['files'][0]
                        if self.Check_and_Copy(log, flagCopy,
                                               srcfile, destfile):
                            return
                else:
                    if iodf.IsMultiImage():
                        destdir = os.path.join(full_dir, data['typename'])
                        srcfile = iodf.GetFilesExpanded()[0]
                        ext = os.path.splitext(srcfile)[1]
                        destfile = os.path.join(
                            destdir, data['typename'].lower() + ext)
                        if self.Check_and_Copy(log, flagCopy,
                                               srcfile, destfile):
                            return
                    else:
                        destdir = os.path.join(
                            full_dir, data['typename'], SRCDIR)
                        mkdirs(destdir)
                        srcfiles = iodf.GetFilesExpanded()
                        for srcfile in srcfiles:
                            srcname = os.path.basename(srcfile)
                            destfile = os.path.join(destdir, srcname)
                            if self.Check_and_Copy(log, flagCopy,
                                                   srcfile, destfile):
                                return
                        if data['typename'] == TYPENAME[IMAGE] \
                                and len(srcfiles) < 2:
                            log.insert("\n" + _("... aborted") + ": " +
                                       _("Siril requires a minimum "
                                         "of 2 light images") + "\n")
                            return
        log.insert('\n')
        log.print_ligne('.')
        log.print_titre('.', _("COPY : FINISHED"))
        log.print_ligne('.')
        log.insert('\n')
        log.SetFinishBar()

    def Check_and_Copy(self, log, flagCopy, srcfile, destfile):
        if self.overwriteFiles is False:
            cr = CheckOverwrite(log, destfile)
            if cr is None:
                pass
            elif cr is False:
                self.overwriteFiles = True
            else:
                return True
        if copy_link(log, flagCopy, srcfile, destfile):
            return True
        return False


# ==============================================================================
def copy_link(log, flagCopy, src, dst):
    task = GestionThread()
    if task.IsAborted():
        log.AbortMsg()
        return True

    if src == dst:
        log.insert(_('Skip') + ' ' + src + " == " + dst + '\n')
        return False

    if flagCopy is True:
        TypeAction = _('Copy')
    else:
        TypeAction = _('Link')

    log.insert(TypeAction + ' ' + src + " -> " + dst + '\n')
    try:
        if os.path.exists(dst):
            os.remove(dst)
        if flagCopy is True:
            shutil.copy2(src, dst)
        else:
            if sys.platform.startswith('win'):
                subprocess.check_call('mklink "%s" "%s"' %
                                      (dst, src), shell=True)
            else:
                os.symlink(src, dst)
    except Exception as e:   # pylint: disable=broad-except
        log.insert(_("... aborted") + "\n")
        log.insert("*** copy_link() :" + str(e) + '\n')
        if sys.platform.startswith('win') and flagCopy is False:
            log.insert("***" + _("Symbolic Link Error on Windows: "))
            log.insert(_('Check if the "Developer Mode" option is enabled') +
                       "\n")
            log.insert(
                _("Warning, Symbolic Link on Windows works"
                  " only with NTFS partition") + "\n")
        return True
    return False


# ==============================================================================
def CheckOverwrite(log, file):
    ''' Vérifie si le fichier existe et ouvre une boite de dialogue si on veut
        écraser ou non le fichier
    '''
    cr = None
    if os.path.exists(file):
        dlg = wx.MessageDialog(None,
                               _("Are you sure you want"
                                 " to overwrite image files?"),
                               'Error', wx.NO | wx.YES | wx.ICON_ERROR)
        value = dlg.ShowModal()
        dlg.Destroy()
        if value == wx.ID_NO:
            log.insert(_("... aborted") + "\n")
            cr = True
        else:
            cr = False
    return cr
