"""
DeepLabCut2.0 Toolbox (deeplabcut.org)
© A. & M. Mathis Labs
https://github.com/AlexEMG/DeepLabCut
Please see AUTHORS for contributors.

https://github.com/AlexEMG/DeepLabCut/blob/master/AUTHORS
Licensed under GNU Lesser General Public License v3.0

"""

import os
import platform
import pydoc
import subprocess
import sys
import webbrowser

import wx

import deeplabcut
from deeplabcut.gui.analyze_videos import Analyze_videos
from deeplabcut.gui.create_training_dataset import Create_training_dataset
from deeplabcut.gui.create_videos import Create_Labeled_Videos
from deeplabcut.gui.evaluate_network import Evaluate_network
from deeplabcut.gui.extract_frames import Extract_frames
from deeplabcut.gui.extract_outlier_frames import Extract_outlier_frames
from deeplabcut.gui.label_frames import Label_frames
from deeplabcut.gui.refine_labels import Refine_labels
from deeplabcut.gui.refine_tracklets import Refine_tracklets
from deeplabcut.gui.train_network import Train_network
from deeplabcut.gui.video_editing import Video_Editing
from deeplabcut.utils import auxiliaryfunctions

media_path = os.path.join(deeplabcut.__path__[0], "gui", "media")
logo = os.path.join(media_path, "logo.png")


class Create_new_project(wx.Panel):
    def __init__(self, parent, gui_size):
        self.gui_size = gui_size
        self.parent = parent
        h = gui_size[0]
        w = gui_size[1]
        wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER, size=(h, w))
        # variable initilization
        self.filelist = []
        self.filelistnew = []
        self.dir = None
        self.copy = False
        self.cfg = None
        self.loaded = False

        # design the panel
        self.sizer = wx.GridBagSizer(10, 15)

        text1 = wx.StaticText(
            self, label="DeepLabCut - Step 1. Create New Project or Load a Project"
        )
        self.sizer.Add(text1, pos=(0, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=15)

        # Add logo of DLC
        # icon = wx.StaticBitmap(self, bitmap=wx.Bitmap(logo))
        # self.sizer.Add(icon, pos=(0,10), flag=wx.TOP|wx.RIGHT|wx.ALIGN_RIGHT,border=10)

        line = wx.StaticLine(self)
        self.sizer.Add(
            line, pos=(1, 0), span=(1, 15), flag=wx.EXPAND | wx.BOTTOM, border=5
        )

        # Add all the options
        self.proj = wx.RadioBox(
            self,
            label="Please choose an option:",
            choices=["Create new project", "Load existing project"],
            majorDimension=0,
            style=wx.RA_SPECIFY_COLS,
        )
        self.sizer.Add(self.proj, pos=(2, 0), span=(1, 15), flag=wx.LEFT, border=5)
        self.proj.Bind(wx.EVT_RADIOBOX, self.chooseOption)

        #        line = wx.StaticLine(self)
        #        self.sizer.Add(line, pos=(3, 0), span=(1, 8),flag=wx.EXPAND|wx.BOTTOM, border=10)

        self.proj_name = wx.StaticText(self, label="Name of the Project:")
        self.sizer.Add(self.proj_name, pos=(4, 0), flag=wx.LEFT, border=15)

        self.proj_name_txt_box = wx.TextCtrl(self)
        self.sizer.Add(
            self.proj_name_txt_box, pos=(4, 1), span=(1, 5), flag=wx.TOP | wx.EXPAND
        )

        self.exp = wx.StaticText(self, label="Name of the experimenter:")
        self.sizer.Add(self.exp, pos=(5, 0), flag=wx.LEFT | wx.TOP, border=15)

        self.exp_txt_box = wx.TextCtrl(self)
        self.sizer.Add(
            self.exp_txt_box, pos=(5, 1), span=(1, 5), flag=wx.TOP | wx.EXPAND, border=5
        )

        self.vids = wx.StaticText(self, label="Choose Videos:")
        self.sizer.Add(self.vids, pos=(6, 0), flag=wx.TOP | wx.LEFT, border=10)

        self.sel_vids = wx.Button(self, label="Load Videos")
        self.sizer.Add(
            self.sel_vids, pos=(6, 1), span=(1, 5), flag=wx.TOP | wx.EXPAND, border=10
        )
        self.sel_vids.Bind(wx.EVT_BUTTON, self.select_videos)
        #
        sb = wx.StaticBox(self, label="Optional Attributes")
        self.boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)

        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        hbox4 = wx.BoxSizer(wx.HORIZONTAL)

        self.change_workingdir = wx.CheckBox(
            self, label="Select the directory where project will be created"
        )
        hbox2.Add(self.change_workingdir)
        hbox2.AddSpacer(20)
        self.change_workingdir.Bind(wx.EVT_CHECKBOX, self.activate_change_wd)
        self.sel_wd = wx.Button(self, label="Browse")
        self.sel_wd.Enable(False)
        self.sel_wd.Bind(wx.EVT_BUTTON, self.select_working_dir)
        hbox2.Add(self.sel_wd, 0, wx.ALL, -1)
        self.boxsizer.Add(hbox2)

        self.copy_choice = wx.CheckBox(self, label="Copy the videos")
        self.copy_choice.Bind(wx.EVT_CHECKBOX, self.activate_copy_videos)
        hbox3.Add(self.copy_choice)
        hbox3.AddSpacer(155)
        self.boxsizer.Add(hbox3)

        self.multi_choice = wx.CheckBox(self, label="Is it a multi-animal project?")
        # self.multi_choice.Bind(wx.EVT_CHECKBOX,self.activate_copy_videos)
        hbox4.Add(self.multi_choice)
        self.boxsizer.Add(hbox4)
        self.sizer.Add(
            self.boxsizer,
            pos=(7, 0),
            span=(1, 10),
            flag=wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT,
            border=10,
        )

        self.cfg_text = wx.StaticText(self, label="Select the config file")
        self.sizer.Add(self.cfg_text, pos=(8, 0), flag=wx.LEFT | wx.EXPAND, border=15)

        if sys.platform == "darwin":
            self.sel_config = wx.FilePickerCtrl(
                self,
                path="",
                style=wx.FLP_USE_TEXTCTRL,
                message="Choose the config.yaml file",
                wildcard="*.yaml",
            )
        else:
            self.sel_config = wx.FilePickerCtrl(
                self,
                path="",
                style=wx.FLP_USE_TEXTCTRL,
                message="Choose the config.yaml file",
                wildcard="config.yaml",
            )

        self.sizer.Add(
            self.sel_config, pos=(8, 1), span=(1, 3), flag=wx.TOP | wx.EXPAND, border=5
        )
        self.sel_config.Bind(wx.EVT_BUTTON, self.create_new_project)
        self.sel_config.SetPath("")
        # Hide the button as this is not the default option
        self.sel_config.Hide()
        self.cfg_text.Hide()

        self.sel_vids_new = wx.Button(self, label="Load New Videos")
        self.sizer.Add(self.sel_vids_new, pos=(9, 2), flag=wx.TOP | wx.EXPAND, border=5)
        self.sel_vids_new.Bind(wx.EVT_BUTTON, self.select_new_videos)
        self.sel_vids_new.Enable(False)

        self.help_button = wx.Button(self, label="Help")
        self.sizer.Add(self.help_button, pos=(10, 0), flag=wx.LEFT, border=10)
        self.help_button.Bind(wx.EVT_BUTTON, self.help_function)

        self.ok = wx.Button(self, label="Ok")
        self.sizer.Add(self.ok, pos=(9, 5))
        self.ok.Bind(wx.EVT_BUTTON, self.create_new_project)

        self.edit_config_file = wx.Button(self, label="Edit config file")
        self.sizer.Add(self.edit_config_file, pos=(10, 4))
        self.edit_config_file.Bind(wx.EVT_BUTTON, self.edit_config)
        self.edit_config_file.Enable(False)

        self.reset = wx.Button(self, label="Reset")
        self.sizer.Add(self.reset, pos=(10, 1), flag=wx.BOTTOM | wx.RIGHT, border=10)
        self.reset.Bind(wx.EVT_BUTTON, self.reset_project)
        self.sizer.AddGrowableCol(2)

        self.addvid = wx.Button(self, label="Add New Videos")
        self.sizer.Add(self.addvid, pos=(10, 2))
        self.addvid.Bind(wx.EVT_BUTTON, self.add_videos)
        self.addvid.Enable(False)

        self.SetSizer(self.sizer)
        self.sizer.Fit(self)

    def select_new_videos(self, event):
        """
        Selects the videos from the directory
        """
        cwd = os.getcwd()
        dlg = wx.FileDialog(
            self, "Select new videos to load", cwd, "", "*.*", wx.FD_MULTIPLE
        )
        if dlg.ShowModal() == wx.ID_OK:
            self.addvids = dlg.GetPaths()
            self.filelistnew = self.filelistnew + self.addvids
            self.sel_vids_new.SetLabel(
                "Total %s Videos selected" % len(self.filelistnew)
            )

    def help_function(self, event):

        filepath = "help.txt"
        f = open(filepath, "w")
        sys.stdout = f
        fnc_name = "deeplabcut.create_new_project"
        pydoc.help(fnc_name)
        f.close()
        sys.stdout = sys.__stdout__
        help_file = open("help.txt", "r+")
        help_text = help_file.read()
        wx.MessageBox(help_text, "Help", wx.OK | wx.ICON_INFORMATION)
        help_file.close()
        os.remove("help.txt")

    def chooseOption(self, event):
        if self.proj.GetStringSelection() == "Load existing project":

            if self.loaded:
                self.sel_config.SetPath(self.cfg)
            self.proj_name.Enable(False)
            self.proj_name_txt_box.Enable(False)
            self.exp.Enable(False)
            # self.vids.Enable(False)
            self.exp_txt_box.Enable(False)
            self.sel_vids.Enable(False)
            self.sel_vids_new.Enable(False)
            self.change_workingdir.Enable(False)
            self.copy_choice.Enable(False)
            self.multi_choice.Enable(False)
            self.sel_config.Show()
            self.cfg_text.Show()
            self.addvid.Enable(False)
            # self.SetSizer(self.sizer)
            # self.sizer.Add(self.sizer, pos=(3, 0), span=(1, 8),flag=wx.EXPAND|wx.BOTTOM, border=15)
            self.sizer.Fit(self)
        else:
            self.proj_name.Enable(True)
            self.proj_name_txt_box.Enable(True)
            self.exp.Enable(True)
            self.exp_txt_box.Enable(True)
            self.sel_vids.Enable(True)
            self.sel_vids_new.Enable(False)
            self.change_workingdir.Enable(True)
            self.copy_choice.Enable(True)
            self.multi_choice.Enable(True)
            if self.sel_config.IsShown():
                self.sel_config.Hide()
                self.cfg_text.Hide()
            #                self.ok.Enable(False)
            #            else:
            #                self.ok.Enable(True)
            self.addvid.Enable(False)
            self.SetSizer(self.sizer)
            self.sizer.Fit(self)

    def edit_config(self, event):
        """
        """
        if self.cfg != "":
            # For mac compatibility
            if platform.system() == "Darwin":
                self.file_open_bool = subprocess.call(["open", self.cfg])
                self.file_open_bool = True
            else:
                self.file_open_bool = webbrowser.open(self.cfg)

            if self.file_open_bool:
                pass
            else:
                raise FileNotFoundError("File not found!")

    def select_videos(self, event):
        """
        Selects the videos from the directory
        """
        cwd = os.getcwd()
        dlg = wx.FileDialog(
            self, "Select videos to add to the project", cwd, "", "*.*", wx.FD_MULTIPLE
        )
        if dlg.ShowModal() == wx.ID_OK:
            self.vids = dlg.GetPaths()
            self.filelist = self.filelist + self.vids
            self.sel_vids.SetLabel("Total %s Videos selected" % len(self.filelist))

    def activate_copy_videos(self, event):
        """
        Activates the option to copy videos
        """
        self.change_copy = event.GetEventObject()
        if self.change_copy.GetValue() == True:
            self.copy = True
        else:
            self.copy = False

    def activate_change_wd(self, event):
        """
        Activates the option to change the working directory
        """
        self.change_wd = event.GetEventObject()
        if self.change_wd.GetValue() == True:
            self.sel_wd.Enable(True)
        else:
            self.sel_wd.Enable(False)

    def select_working_dir(self, event):
        cwd = os.getcwd()
        dlg = wx.DirDialog(
            self,
            "Choose the directory where your project will be saved:",
            cwd,
            style=wx.DD_DEFAULT_STYLE,
        )
        if dlg.ShowModal() == wx.ID_OK:
            self.dir = dlg.GetPath()

    def create_new_project(self, event):
        """
        Finally create the new project
        """
        if self.sel_config.IsShown():
            self.cfg = self.sel_config.GetPath()
            if self.cfg == "":
                wx.MessageBox(
                    "Please choose the config.yaml file to load the project",
                    "Error",
                    wx.OK | wx.ICON_ERROR,
                )
                self.loaded = False
            else:
                wx.MessageBox("Project Loaded!", "Info", wx.OK | wx.ICON_INFORMATION)
                self.loaded = True
                self.sel_vids_new.Enable(True)
                self.addvid.Enable(True)
                self.edit_config_file.Enable(True)
        else:
            self.task = self.proj_name_txt_box.GetValue()
            self.scorer = self.exp_txt_box.GetValue()

            if self.task != "" and self.scorer != "" and self.filelist != []:
                self.cfg = deeplabcut.create_new_project(
                    self.task,
                    self.scorer,
                    self.filelist,
                    self.dir,
                    copy_videos=self.copy,
                    multianimal=self.multi_choice.IsChecked(),
                )
            else:
                wx.MessageBox(
                    "Some of the enteries are missing.\n\nMake sure that the task and experimenter name are specified and videos are selected!",
                    "Error",
                    wx.OK | wx.ICON_ERROR,
                )
                self.cfg = False
            if self.cfg:
                wx.MessageBox(
                    "New Project Created", "Info", wx.OK | wx.ICON_INFORMATION
                )
                self.loaded = True
                self.edit_config_file.Enable(True)

        # Remove the pages in case the user goes back to the create new project and creates/load a new project
        if self.parent.GetPageCount() > 3:
            for i in range(2, self.parent.GetPageCount()):
                self.parent.RemovePage(2)
                self.parent.Layout()

        # Add all the other pages
        if self.loaded:
            self.edit_config_file.Enable(True)
            cfg = auxiliaryfunctions.read_config(self.cfg)
            if self.parent.GetPageCount() < 3:
                page3 = Extract_frames(self.parent, self.gui_size, self.cfg)
                self.parent.AddPage(page3, "Extract frames")

                page4 = Label_frames(self.parent, self.gui_size, self.cfg)
                self.parent.AddPage(page4, "Label frames")

                page5 = Create_training_dataset(self.parent, self.gui_size, self.cfg)
                self.parent.AddPage(page5, "Create training dataset")

                page6 = Train_network(self.parent, self.gui_size, self.cfg)
                self.parent.AddPage(page6, "Train network")

                page7 = Evaluate_network(self.parent, self.gui_size, self.cfg)
                self.parent.AddPage(page7, "Evaluate network")

                page12 = Video_Editing(self.parent, self.gui_size, self.cfg)
                self.parent.AddPage(page12, "Video editor")

                page8 = Analyze_videos(self.parent, self.gui_size, self.cfg)
                self.parent.AddPage(page8, "Analyze videos")

                if cfg.get("multianimalproject", False):
                    page = Refine_tracklets(self.parent, self.gui_size, self.cfg)
                    self.parent.AddPage(page, "Refine tracklets")
                page11 = Create_Labeled_Videos(self.parent, self.gui_size, self.cfg)
                self.parent.AddPage(page11, "Create videos")
                page9 = Extract_outlier_frames(self.parent, self.gui_size, self.cfg)
                self.parent.AddPage(page9, "Extract outlier frames")
                page10 = Refine_labels(self.parent, self.gui_size, self.cfg, page5)
                self.parent.AddPage(page10, "Refine labels")
                self.edit_config_file.Enable(True)

    def add_videos(self, event):
        print("adding new videos to be able to label ...")
        self.cfg = self.sel_config.GetPath()
        if len(self.filelistnew) > 0:
            self.filelistnew = self.filelistnew + self.addvids
            deeplabcut.add_new_videos(self.cfg, self.filelistnew)
        else:
            print("Please select videos to add first. Click 'Load New Videos'...")

    def reset_project(self, event):
        self.loaded = False
        if self.sel_config.IsShown():
            self.sel_config.SetPath("")
            self.proj.SetSelection(0)
            self.sel_config.Hide()
            self.cfg_text.Hide()

        self.sel_config.SetPath("")
        self.proj_name_txt_box.SetValue("")
        self.exp_txt_box.SetValue("")
        self.filelist = []
        self.sel_vids.SetLabel("Load Videos")
        self.dir = os.getcwd()
        self.edit_config_file.Enable(False)
        self.proj_name.Enable(True)
        self.proj_name_txt_box.Enable(True)
        self.multi_choice.Enable(True)
        self.exp.Enable(True)
        self.exp_txt_box.Enable(True)
        self.sel_vids.Enable(True)
        self.addvid.Enable(False)
        self.sel_vids_new.Enable(False)
        self.change_workingdir.Enable(True)
        self.copy_choice.Enable(True)

        try:
            self.change_wd.SetValue(False)
        except:
            pass
        try:
            self.change_copy.SetValue(False)
        except:
            pass
        # self.yes.Enable(False)
        # self.no.Enable(False)
        self.sel_wd.Enable(False)