#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  picker.py
#
#  Copyright 2019 Dominic Davis-Foster <dominic@davis-foster.co.uk>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#
#
# generated by wxGlade 0.9.3 on Thu Jun  6 12:07:28 2019
#

# stdlib
import pathlib

# 3rd party
import wx

# this package
from . import icons
from domdf_wxpython_tools.dialogs import file_dialog


# begin wxGlade: dependencies
# end wxGlade

# begin wxGlade: extracode
# end wxGlade

# TODO: Forward events

class dir_picker(wx.Panel):
	"""
	
	"""
	def __init__(
			self, parent, id=wx.ID_ANY, value="", pos=wx.DefaultPosition,
			size=wx.DefaultSize, style=wx.TAB_TRAVERSAL, name=b"dir_picker",
	):
		"""
		
		:param parent:
		:type parent:
		:param id:
		:type id:
		:param value:
		:type value:
		:param pos:
		:type pos:
		:param size:
		:type size:
		:param style:
		:type style:
		:param name:
		:type name:
		"""
		
		self._parent = parent
		self.initial_value = value
		
		wx.Panel.__init__(self, self._parent, id=id, pos=pos, size=size, style=style, name=name)
		self.dir_value = wx.TextCtrl(self, wx.ID_ANY, "")
		self.clear_btn = wx.BitmapButton(self, wx.ID_ANY, icons.get_button_icon("ART_GO_BACK", 16))
		self.browse_btn = wx.BitmapButton(self, wx.ID_ANY, icons.get_button_icon("ART_FOLDER_OPEN", 16))
		
		self.textctrl_width = 150
		self.height = 29
		
		self.__set_properties()
		self.__do_layout()
		
		self.Bind(wx.EVT_BUTTON, self.Clear, self.clear_btn)
		self.Bind(wx.EVT_BUTTON, self.Browse, self.browse_btn)
		
		return
	
	def __set_properties(self):
		# begin wxGlade: dir_picker.__set_properties
		self.dir_value.SetMinSize((-1, 29))
		self.dir_value.SetMaxSize((-1, 29))
		self.clear_btn.SetMinSize((29, 29))
		self.browse_btn.SetMinSize((29, 29))
		# end wxGlade
		# self.dir_value.SetMinSize((self.textctrl_width, self.height))
		# self.clear_btn.SetMinSize((self.height, self.height))
		# self.browse_btn.SetMinSize((self.height, self.height))
		# self.SetMinSize((self.textctrl_width + 5 + (2*self.height), self.height+5))
	
	def __do_layout(self):
		# begin wxGlade: dir_picker.__do_layout
		sizer = wx.BoxSizer(wx.HORIZONTAL)
		sizer_5 = wx.BoxSizer(wx.VERTICAL)
		sizer_5.Add(self.dir_value, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 0)
		sizer.Add(sizer_5, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 0)
		sizer.Add(self.clear_btn, 0, wx.ALIGN_CENTER_VERTICAL, 0)
		sizer.Add(self.browse_btn, 0, wx.ALIGN_CENTER_VERTICAL, 0)
		self.SetSizer(sizer)
		sizer.Fit(self)
		self.Layout()
		# end wxGlade
	
	def set_textctrl_width(self, width):
		self.SetTextWidth(width)
	
	def set_height(self, height):
		self.SetHeight(height)
		
	def get_value(self):
		return self.GetValue()
	
	def reset_value(self):
		return self.ResetValue()
	
	def AppendText(self, text):
		"""
		Appends the text to the end of the text control.

		:param text: Text to write to the text control
		:type text: string
		"""
		return self.dir_value.AppendText(text)
	
	def Browse(self, *_):  # wxGlade: dir_picker.<event_handler>
		if self.get_value() == '':
			default_path = self.initial_value
		else:
			default_path = self.get_value()
		
		dlg = wx.DirDialog(
			None, "Choose a directory:",
			style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON,
			defaultPath=default_path
		)
		
		if dlg.ShowModal() == wx.ID_OK:
			self.dir_value.SetValue((dlg.GetPath()))
		dlg.Destroy()
		self.dir_value.SetFocus()
	
	def CanCopy(self):
		"""
		Returns True if the selection can be copied to the clipboard.

		:rtype: bool
		"""
		return self.dir_value.CanCopy()
	
	def CanCut(self):
		"""
		Returns True if the selection can be cut to the clipboard.

		:rtype: bool
		"""
		return self.dir_value.CanCut()
	
	def CanPaste(self):
		"""
		Returns True if the contents of the clipboard can be pasted into the text control.
		
		On some platforms (Motif, GTK) this is an approximation and returns True if the control is editable, False otherwise.

		:rtype: bool
		"""
		return self.dir_value.CanPaste()
	
	def CanRedo(self):
		"""
		Returns True if there is a redo facility available and the last operation can be redone.
		
		:rtype: bool
		"""
		return self.dir_value.CanRedo()

	def CanUndo(self):
		"""
		Returns True if there is an undo facility available and the last operation can be undone.
		
		:rtype:	bool
		"""
		return self.dir_value.CanUndo()

	def Clear(self, *_):  # wxGlade: dir_picker.<event_handler>
		"""
		Clears the text in the control.

		Note that this function will generate a wxEVT_TEXT event, i.e. its effect is identical to calling SetValue (“”).
		"""
		self.dir_value.Clear()
		self.dir_value.SetFocus()

	def Copy(self):
		"""
		Copies the selected text to the clipboard.
		"""
		return self.dir_value.Copy()

	def Cut(self):
		"""
		Copies the selected text to the clipboard and removes it from the control.
		"""
		return self.dir_value.Cut()
		
	def GetInsertionPoint(self):
		"""
		Returns the insertion point, or cursor, position.
	
		This is defined as the zero based index of the character position to the right of the insertion point. For example, if the insertion point is at the end of the single-line text control, it is equal to GetLastPosition .
	
		:rtype:	long
		"""
		return self.dir_value.GetInsertionPoint()

	def GetLastPosition(self):
		"""
		Returns the zero based index of the last position in the text control, which is equal to the number of characters in the control.
	
		:rtype:	wx.TextPos
		"""
		return self.dir_value.GetLastPosition()

	def GetSelection(self):
		"""
		Gets the current selection span.
	
		If the returned values are equal, there was no selection. Please note that the indices returned may be used with the other wx.TextCtrl methods but don’t necessarily represent the correct indices into the string returned by GetValue for multiline controls under Windows (at least,) you should use GetStringSelection to get the selected text.
	
		:rtype:	tuple
		"""
		return self.dir_value.GetSelection()

	def GetStringSelection(self):
		"""
		Gets the text currently selected in the control.
	
		If there is no selection, the returned string is empty.
	
		:rtype:	string
		"""
		return self.dir_value.GetStringSelection()

	def GetValue(self):
		"""
		Gets the contents of the control.
		
		Notice that for a multiline text control, the lines will be separated by (Unix-style) \n characters, even under Windows where they are separated by a \r\n sequence in the native control.
		
		:rtype:	string
		"""
		return self.dir_value.GetValue()
	
	def IsEditable(self):
		"""
		Returns True if the controls contents may be edited by user (note that it always can be changed by the program).
		
		In other words, this functions returns True if the control hasn’t been put in read-only mode by a previous call to SetEditable .
		
		:rtype:	bool
		"""
		return self.dir_value.IsEditable()

	def IsEmpty(self):
		"""
		Returns True if the control is currently empty.
		
		This is the same as GetValue .empty() but can be much more efficient for the multiline controls containing big amounts of text.
		
		:rtype:	bool
		"""
		return self.dir_value.IsEmpty()
	
	def Paste(self):
		"""
		Pastes text from the clipboard to the text item.
		"""
		return self.dir_value.Paste()

	def Redo(self):
		"""
		If there is a redo facility and the last operation can be redone, redoes the last operation.
		
		Does nothing if there is no redo facility.
		"""
		return self.dir_value.Redo()
		
	def Remove(self, from_, to_):
		"""
		Removes the text starting at the first given position up to (but not including) the character at the last position.
		
		This function puts the current insertion point position at to as a side effect.
		
		:param from_: The first position
		:type from_: long
		:param to_: The last position
		:type to_: long
		"""
		return self.dir_value.Remove(from_, to_)
	
	def Replace(self, from_, to_, value):
		"""
		Replaces the text starting at the first position up to (but not including) the character at the last position with the given text.
		
		This function puts the current insertion point position at to as a side effect.
		
		:param from_: The first position
		:type from_: long
		:param to_: The last position
		:type to_: long
		:param value: The value to replace the existing text with
		:type value: string
		"""
		return self.dir_value.Replace(from_, to_, value)

	def ResetValue(self):
		"""
		Resets the text ctrl to the initial value, either specified in __init__ or set with SetInitialValue
		"""
		return self.dir_value.SetValue(self.initial_value)

	def SelectAll(self):
		"""
		Selects all text in the control.
		
		See also SetSelection
		"""
		return self.dir_value.SelectAll()

	def SelectNone(self):
		"""
		Deselects selected text in the control.
		"""
		return self.dir_value.SelectNone()

	def SetHeight(self, height):
		"""
		Set the height of the widgets
		
		:param height: Height of the widgets
		:type height: float or int
		"""
		self.height = height
		self.__set_properties()
		self.Layout()

	def SetInitialValue(self, value):
		"""
		Sets the initial value for the text ctrl
		
		:param value: Initial value for the text ctrl
		:type value: string
		"""
		self.initial_value = value
		
	def SetInsertionPoint(self, pos):
		"""
		Sets the insertion point at the given position.
		
		:param pos: Position to set, in the range from 0 to GetLastPosition inclusive.
		:type pos: long
		:return:
		"""
		return self.dir_value.SetInsertionPoint(pos)

	def SetInsertionPointEnd(self):
		"""
		Sets the insertion point at the end of the text control.
		
		This is equivalent to calling wx.TextCtrl.SetInsertionPoint with wx.TextCtrl.GetLastPosition argument.
		"""
		return self.dir_value.SetInsertionPointEnd()

	def SetSelection(self, from_, to_):
		"""
		Selects the text starting at the first position up to (but not including) the character at the last position.
		
		If both parameters are equal to -1 all text in the control is selected.
		
		Notice that the insertion point will be moved to from by this function.
		
		:param from_: The first position
		:type from_: long
		:param to_: The last position
		:type to_: long
		
		See also SelectAll
		"""
		
		return self.dir_value.SetSelection(from_, to_)

	def SetTextWidth(self, width):
		"""
		Sets the width of the TextCtrl
		
		:param width: The width of the TextCtrl
		:type width: float or int
		"""
		
		self.textctrl_width = width
		self.__set_properties()
		self.Layout()

	def SetValue(self, value):
		"""
		Sets the new text control value.
		
		It also marks the control as not-modified which means that IsModified() would return False immediately after the call to SetValue .
		
		The insertion point is set to the start of the control (i.e. position 0) by this function unless the control value doesn’t change at all, in which case the insertion point is left at its original position.
		
		Note that, unlike most other functions changing the controls values, this function generates a wxEVT_TEXT event. To avoid this you can use ChangeValue instead.
		
		Parameters:	value (string) – The new value to set. It may contain newline characters if the text control is multi-line.
		"""
		
		return self.dir_value.SetValue(value)
		
	def Undo(self):
		"""
		If there is an undo facility and the last operation can be undone, undoes the last operation.
		
		Does nothing if there is no undo facility.
		"""
		
		return self.dir_value.Undo()

	def WriteText(self, text):
		"""
		Writes the text into the text control at the current insertion position.

		:param text: Text to write to the text control
		:type text: string
		"""
		
		return self.dir_value.WriteText(text)
	
# end of class dir_picker


class file_picker(dir_picker):
	"""

	"""
	
	def __init__(
			self, parent, id=wx.ID_ANY, value="", pos=wx.DefaultPosition, size=wx.DefaultSize,
			style=wx.TAB_TRAVERSAL | wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, name=b"file_picker",
			extension="*", title="File Picker", filetypestring="All Files", **kwargs
	):
		"""

		:param parent:
		:type parent:
		:param id:
		:type id:
		:param value:
		:type value:
		:param pos:
		:type pos:
		:param size:
		:type size:
		:param style:
		:type style:
		:param name:
		:type name:
		:param extension:
		:type extension:
		:param title:
		:type title:
		:param filetypestring:
		:type filetypestring:
		:param kwargs:
		:type kwargs:
		"""
		
		self._parent = parent
		self.initial_value = value
		self.file_extension = extension
		self.dialog_title = title
		self.filetypestring = filetypestring
		self.file_dialog_kwargs = kwargs
		self.style = style
		
		dir_picker.__init__(self, parent, id, value, pos, size, style, name)
	
	def Browse(self, *_):  # wxGlade: dir_picker.<event_handler>
		if self.get_value() == '':
			default_path = str(pathlib.Path(self.initial_value).parent)
		else:
			default_path = pathlib.Path(self.get_value())
			if default_path.is_file():
				default_path = default_path.parent
			default_path = str(default_path)
		
		pathname = file_dialog(
			self, extension=self.file_extension,
			style=self.style,
			defaultDir=default_path,
			filetypestring=self.filetypestring,
			title=self.dialog_title,
		)
		
		if pathname:
			self.dir_value.SetValue(pathname)
			self.dir_value.SetFocus()

# end of class file_picker


class file_folder_picker(dir_picker):
	"""
	
	"""
	
	def __init__(
			self, parent, id=wx.ID_ANY, value="", pos=wx.DefaultPosition, size=wx.DefaultSize,
			style=wx.TAB_TRAVERSAL | wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, name=b"file_picker",
			extension="*", title="File Picker", filetypestring="All Files", start_as_files=True, **kwargs
	):
		"""

		:param parent:
		:type parent:
		:param id:
		:type id:
		:param value:
		:type value:
		:param pos:
		:type pos:
		:param size:
		:type size:
		:param style:
		:type style:
		:param name:
		:type name:
		:param extension:
		:type extension:
		:param title:
		:type title:
		:param filetypestring:
		:type filetypestring:
		:param kwargs:
		:type kwargs:
		"""
		
		self._parent = parent
		self.initial_value = value
		self.file_extension = extension
		self.dialog_title = title
		self.filetypestring = filetypestring
		self.file_dialog_kwargs = kwargs
		self.style = style
		self.files_mode = start_as_files
		
		dir_picker.__init__(self, parent, id, value, pos, size, style, name)
	
	def set_folders_mode(self):
		self.files_mode = False
	
	def set_files_mode(self):
		self.files_mode = True
	
	def toggle_mode(self):
		self.files_mode = not self.files_mode
		
	def Browse(self, *_):  # wxGlade: dir_picker.<event_handler>
		
		if self.files_mode:
		
			if self.get_value() == '':
				default_path = str(pathlib.Path(self.initial_value).parent)
			else:
				default_path = pathlib.Path(self.get_value())
				if default_path.is_file():
					default_path = default_path.parent
				default_path = str(default_path)
			
			pathname = file_dialog(
				self, extension=self.file_extension,
				style=self.style,
				defaultDir=default_path,
				filetypestring=self.filetypestring,
				title=self.dialog_title,
			)
			
			if pathname:
				self.dir_value.SetValue(pathname)
				self.dir_value.SetFocus()
	
		else:
			if self.get_value() == '':
				default_path = self.initial_value
			else:
				default_path = self.get_value()
			
			dlg = wx.DirDialog(
				None, "Choose a directory:",
				style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON,
				defaultPath=default_path
			)
			
			if dlg.ShowModal() == wx.ID_OK:
				self.dir_value.SetValue((dlg.GetPath()))
			dlg.Destroy()
			self.dir_value.SetFocus()
