# -*- 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 wx
import os
import sys
import glob
from sirilic.lib.constantes import TAB_FILES
from sirilic.lib.constantes import IMAGE, OFFSET, DARK, FLAT, DFLAT, NB_IODF
from sirilic.ui import gui


# ==============================================================================
class FileDropTarget(wx.FileDropTarget):
    def __init__(self, target_obj):
        wx.FileDropTarget.__init__(self)
        self.target_obj = target_obj

    def OnDropFiles(self, _x, _y, filenames):
        for file in filenames:
            self.target_obj.Append(file)
        return True


# ==============================================================================
class TabFiles:
    def __init__(self, i_gui, i_prefs, ChangeTab):

        self.i_gui = i_gui
        self.i_files = i_gui.wfiles
        self.w_list = [None] * NB_IODF
        self.w_list[IMAGE] = self.i_files.wImageFiles
        self.w_list[OFFSET] = self.i_files.wOffsetFiles
        self.w_list[DARK] = self.i_files.wDarkFiles
        self.w_list[FLAT] = self.i_files.wFlatFiles
        self.w_list[DFLAT] = self.i_files.wDFlatFiles
        self.prefs = i_prefs
        self.ChangeTab = ChangeTab

        for wfiles in self.w_list:
            wfiles.lb_file.SetDropTarget(FileDropTarget(wfiles.lb_file))
            wfiles.bAdd_file.Bind(
                wx.EVT_BUTTON, lambda evt, target_obj=wfiles.lb_file: self.CB_GetFiles(evt, target_obj))
            wfiles.bDEL_file.Bind(
                wx.EVT_BUTTON, lambda evt, target_obj=wfiles.lb_file: self.CB_DelLine(evt, target_obj))
            wfiles.bCLR_file.Bind(
                wx.EVT_BUTTON, lambda evt, target_obj=wfiles.lb_file: self.CB_ClearAll(evt, target_obj))
            wfiles.bEdit_file.Bind(
                wx.EVT_BUTTON, lambda evt, target_obj=wfiles.lb_file: self.CB_EditLine(evt, target_obj))
            wfiles.lb_file.Bind(wx.EVT_CONTEXT_MENU, lambda evt,
                                target_obj=wfiles.lb_file: self.CB_popupmenu(evt, target_obj))

        self.MemoFileBox = []
        self.menu_labels_by_id = {}
        self.menu_labels = [_("Copy all"), _(
            "Replace all"), _("Append"), _("Clear all")]
        for title in self.menu_labels:
            self.menu_labels_by_id[wx.NewId()] = title

        self.i_files.bFastFiles.Bind(wx.EVT_BUTTON, self.CB_Fast)
        self.i_files.bFastFiles.SetFont(
            self.i_files.bFastFiles.GetFont().MakeBold())

    # --------------------------------------------------------------------------
    def CB_popupmenu(self, event, target_obj):
        menu = wx.Menu()
        for (no_id, title) in self.menu_labels_by_id.items():
            menu.Append(no_id, title)
            menu.Bind(wx.EVT_MENU, lambda evt, idmenu=no_id, target_obj=target_obj: self.MenuSelectionCb(
                evt, idmenu, target_obj), id=no_id)
        pos = event.GetPosition()
        pos = self.i_gui.ScreenToClient(pos)
        self.i_gui.PopupMenu(menu, pos)
        menu.Destroy()

    def MenuSelectionCb(self, _event, no_id, target_obj):
        if self.menu_labels_by_id[no_id] == self.menu_labels[0]:  # "Copy all"
            self.MemoFileBox = self.getListBoxFiles(target_obj)

        if self.menu_labels_by_id[no_id] == self.menu_labels[1]:  # "Replace all"
            self.setListBoxFiles(target_obj, self.MemoFileBox)

        if self.menu_labels_by_id[no_id] == self.menu_labels[2]:  # "Append"
            FileBox = self.getListBoxFiles(target_obj) + self.MemoFileBox
            FileBox = set(FileBox)
            self.setListBoxFiles(target_obj, list(FileBox))

        if self.menu_labels_by_id[no_id] == self.menu_labels[3]:  # "Clear all"
            target_obj.Clear()

    # --------------------------------------------------------------------------
    # Efface les listbox
    def ClrAllListBoxFiles(self, _event=None):
        for wfiles in self.w_list:
            wfiles.lb_file.Clear()
    # --------------------------------------------------------------------------
    # charge les listes de fichiers dans les listbox

    def Set(self, files):
        self.ClrAllListBoxFiles()
        # files
        for no in range(NB_IODF):
            self.setListBoxFiles(self.w_list[no].lb_file, files[no])

    def setListBoxFiles(self, listbox, listfiles):
        if not listfiles:
            return
        listbox.Set(listfiles)
    # --------------------------------------------------------------------------
    # recupere les listes de fichiers dans les listbox

    def Get(self):
        files = [None] * NB_IODF
        for no in range(NB_IODF):
            files[no] = self.getListBoxFiles(self.w_list[no].lb_file)
        return files

    def getListBoxFiles(self, listbox):
        files = []
        for item in range(listbox.GetCount()):
            file = listbox.GetString(item)
            if len(file) != 0:
                files.append(file)
        return files

    # --------------------------------------------------------------------------
    # Callback generique pour ajouter un fichier a une lisbox
    def CB_GetFiles(self, _event, target_obj):
        if target_obj.GetCount() == 0:
            defaultdir = self.prefs.Get('workdir')
        else:
            item = target_obj.GetSelection()
            if item == - 1:
                item = 0
            defaultdir = os.path.dirname(target_obj.GetString(item))
            if not os.path.exists(defaultdir):
                defaultdir = self.prefs.Get('workdir')
        typefile = "Fit files |*.fit;*.fts;*.fits|All file|*.*"
        flag = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE
        with wx.FileDialog(None, _("Open"), defaultdir, "", typefile, flag) as openFileDialog:
            if openFileDialog.ShowModal() == wx.ID_CANCEL:
                return
            for file in openFileDialog.GetPaths():
                if len(file) != 0:
                    target_obj.Append(file)
            self.ChangeTab(TAB_FILES)

    # --------------------------------------------------------------------------
    # Callback generique pour effacer une lisbox
    def CB_ClearAll(self, _event, target_obj):
        target_obj.Clear()
        self.ChangeTab(TAB_FILES)

    # --------------------------------------------------------------------------
    # Callback generique detruire une lifne d'une lisbox
    def CB_DelLine(self, _event, target_obj):
        try:
            target_obj.Delete(target_obj.GetSelection())
            self.ChangeTab(TAB_FILES)
        except Exception:   # pylint: disable=broad-except
            pass

    def CB_EditLine(self, _event, target_obj):
        item = target_obj.GetSelection()
        if item == -1 and target_obj.GetCount() != 0:
            item = 0
        if item == -1 or target_obj.GetCount() == 0:
            with gui.CModifyFile(None, -1, "") as dlg:
                dlg.text_file.SetValue("")
                if dlg.ShowModal() == wx.ID_CANCEL:
                    return
                file = dlg.text_file.GetValue()
                if len(file) != 0:
                    target_obj.Append(file)
            return

        filename = target_obj.GetString(item)
        with gui.CModifyFile(None, -1, "") as dlg:
            dlg.text_file.SetValue(filename)
            if dlg.ShowModal() == wx.ID_CANCEL:
                return
            file = dlg.text_file.GetValue()
            if len(file) != 0:
                target_obj.SetString(item, file)
            else:
                target_obj.Delete(item)
            self.ChangeTab(TAB_FILES)

    # --------------------------------------------------------------------------
    # Callback pour remplir les listes à partir d'une pattern
    def CB_Fast(self, _event):

        with gui.CPatternFilesDlg(None, -1, "") as dlg:
            if sys.platform.startswith('win32'):
                dlg.bRoot.SetMinSize((32, -1))

            dlg.bRoot.Bind(wx.EVT_BUTTON, lambda evt,
                           target_obj=dlg.eRoot: self.CB_SelectDir(evt, target_obj))

            rootpat = self.prefs.Get('root_pattern')
            filepat = self.prefs.Get('files_pattern')
            dlg.eRoot.SetValue(rootpat)
            dlg.eImage.SetValue(filepat[IMAGE])
            dlg.eOffset.SetValue(filepat[OFFSET])
            dlg.eDark.SetValue(filepat[DARK])
            dlg.eFlat.SetValue(filepat[FLAT])
            dlg.eDFlat.SetValue(filepat[DFLAT])

            if dlg.ShowModal() == wx.ID_CANCEL:
                return

            rootpat = dlg.eRoot.GetValue()
            self.prefs.Set('root_pattern', rootpat)
            filepat[IMAGE] = dlg.eImage.GetValue()
            filepat[OFFSET] = dlg.eOffset.GetValue()
            filepat[DARK] = dlg.eDark.GetValue()
            filepat[FLAT] = dlg.eFlat.GetValue()
            filepat[DFLAT] = dlg.eDFlat.GetValue()

            for no in range(NB_IODF):
                pattern = filepat[no]
                if pattern == '':
                    continue
                if filepat[no][0] != os.path.sep and filepat[no][1] != ':':
                    pattern = os.path.join(rootpat, pattern)
                liste_expanded = []
                yy = glob.glob(pattern)
                for zz in yy:
                    liste_expanded.append(zz)
                liste_expanded = list(set(liste_expanded))
                if len(liste_expanded) == 0:
                    continue
                self.w_list[no].lb_file.Clear()
                self.setListBoxFiles(self.w_list[no].lb_file, liste_expanded)

    def CB_SelectDir(self, _event, target_obj):
        defaultdir = target_obj.GetValue()
        if not os.path.exists(defaultdir):
            defaultdir = self.prefs.Get('workdir')
        dirstyle = wx.DD_DEFAULT_STYLE | wx.FD_FILE_MUST_EXIST
        with wx.DirDialog(None, 'Choose root directory', defaultdir, style=dirstyle) as openDirDialog:
            if openDirDialog.ShowModal() == wx.ID_CANCEL:
                return
            target_obj.SetValue(openDirDialog.GetPath())
