# coding=utf8
import sublime
import os
import re
import shutil

from SideBarProject import SideBarProject

try:
	import desktop
except:
	pass

class Object():
	pass

def expand_vars(path):
	for k, v in os.environ.iteritems():
		try:
			# dirty hack, this should be autofixed in python3
			k = unicode(k.encode('utf8'))
			v = unicode(v.encode('utf8'))
			path = path.replace(u'%'+k+'%', v).replace(u'%'+k.lower()+'%', v)
		except:
			pass
	return path

class SideBarItem:

	def __init__(self, path, is_directory):
		self._path = path
		self._is_directory = is_directory

	def path(self, path = ''):
		if path == '':
			return self._path
		else:
			self._path = path
			self._is_directory = os.path.isdir(path)
			return path

	def pathSystem(self):
		import sys
		return self.path().encode(sys.getfilesystemencoding())

	def pathWithoutProject(self):
		path = self.path()
		for directory in SideBarProject().getDirectories():
			path = path.replace(directory, '', 1)
		return path.replace('\\', '/')

	def pathProject(self):
		path = self.path()
		for directory in SideBarProject().getDirectories():
			path2 = path.replace(directory, '', 1)
			if path2 != path:
				return directory
		return False

	def projectURL(self, type):
		filename = os.path.normpath(os.path.join(sublime.packages_path(), '..', 'Settings', 'SideBarEnhancements.json'))
		if os.path.lexists(filename):
			#try:
				import json
				data = file(filename, 'r').read()
				data = data.replace('\t', ' ').replace('\\', '/').replace('\\', '/').replace('//', '/').replace('//', '/').replace('http:/', 'http://').replace('https:/', 'https://')
				data = json.loads(data, strict=False)

				for path in data.keys():
					path2 = expand_vars(path)
					print '-------------------------------------------------------'
					print 'searching:'
					path2 = path2.replace('\\', '/').replace('\\', '/').replace('//', '/').replace('//', '/')
					print path2
					print 'in:'
					path3 = self.path().replace('\\', '/').replace('\\', '/').replace('//', '/').replace('//', '/')
					print path3
					print '-------------------------------------------------------'
					path4 = re.sub(re.compile("^"+re.escape(path2), re.IGNORECASE), '', path3);
					print path4
					if path4 != path3:
						url = data[path][type]
						if url:
							if url[-1:] != '/':
								url = url+'/'
						import urllib
						return url+(re.sub("^/", '', urllib.quote(path4.encode('utf-8'))));

			#except:
			#	return False
		else:
			return False

	def isUnderCurrentProject(self):
		path = self.path()
		path2 = self.path()
		for directory in SideBarProject().getDirectories():
			path2 = path2.replace(directory, '', 1)
		return path != path2

	def pathRelativeFromProject(self):
		return re.sub('^/+', '', self.pathWithoutProject())

	def pathRelativeFromProjectEncoded(self):
		import urllib
		return urllib.quote(self.pathRelativeFromProject().encode('utf-8'))

	def pathRelativeFromView(self):
		return os.path.relpath(self.path(), os.path.dirname(sublime.active_window().active_view().file_name())).replace('\\', '/')

	def pathRelativeFromViewEncoded(self):
		import urllib
		return urllib.quote(os.path.relpath(self.path(), os.path.dirname(sublime.active_window().active_view().file_name())).replace('\\', '/').encode('utf-8'))

	def pathAbsoluteFromProject(self):
		return self.pathWithoutProject()

	def pathAbsoluteFromProjectEncoded(self):
		import urllib
		return urllib.quote(self.pathAbsoluteFromProject().encode('utf-8'))

	def uri(self):
		import urllib
		return 'file:'+urllib.pathname2url(self.path().encode('utf-8'));

	def join(self, name):
		return os.path.join(self.path(), name)

	def dirname(self):
		branch, leaf = os.path.split(self.path())
		return branch;

	def forCwdSystemPath(self):
		if self.isDirectory():
			return self.pathSystem()
		else:
			return self.dirnameSystem()

	def forCwdSystemName(self):
		if self.isDirectory():
			return '.'
		else:
			path = self.pathSystem()
			branch = self.dirnameSystem()
			leaf = path.replace(branch, '', 1).replace('\\', '').replace('/', '')
			return leaf

	def forCwdSystemPathRelativeFrom(self, relativeFrom):
		relative = SideBarItem(relativeFrom, os.path.isdir(relativeFrom))
		path = self.pathSystem().replace(relative.pathSystem(), '', 1).replace('\\', '/')
		if path == '':
			return '.'
		else:
			return re.sub('^/+', '', path)

	def forCwdSystemPathRelativeFromRecursive(self, relativeFrom):
		relative = SideBarItem(relativeFrom, os.path.isdir(relativeFrom))
		path = self.pathSystem().replace(relative.pathSystem(), '', 1).replace('\\', '/')
		if path == '':
			return '.'
		else:
			if self.isDirectory():
				return re.sub('^/+', '', path)+'/'
			else:
				return re.sub('^/+', '', path)

	def dirnameSystem(self):
		import sys
		return self.dirname().encode(sys.getfilesystemencoding())

	def dirnameCreate(self):
		try:
			os.makedirs(self.dirname())
		except:
			pass

	def name(self):
		branch, leaf = os.path.split(self.path())
		return leaf;

	def nameSystem(self):
		import sys
		return self.name().encode(sys.getfilesystemencoding())

	def nameEncoded(self):
		import urllib
		return urllib.quote(self.name().encode('utf-8'));

	def namePretty(self):
		return self.name().replace(self.extension(), '').replace('-', ' ').replace('_', ' ').strip();

	def open(self):
		if sublime.platform() == 'osx':
			import subprocess
			subprocess.Popen(['open', '-a', self.nameSystem()], cwd=self.dirnameSystem())
		elif sublime.platform() == 'windows':
			import subprocess
			subprocess.Popen([self.nameSystem()], cwd=self.dirnameSystem(), shell=True)
		else:
			desktop.open(self.path())

	def edit(self):
		return sublime.active_window().open_file(self.path())

	def isDirectory(self):
		return self._is_directory

	def isFile(self):
		return self.isDirectory() == False

	def contentUTF8(self):
		import codecs
		return codecs.open(self.path(), 'r', 'utf-8').read()

	def contentBinary(self):
		return file(self.path(), "rb").read()

	def contentBase64(self):
		return 'data:'+self.mime()+';base64,'+(file(self.path(), "rb").read().encode("base64").replace('\n', ''))

	def reveal(self):
		sublime.active_window().run_command("open_dir", {"dir": self.dirname(), "file": self.name()} )

	def write(self, content):
		file(self.path(), 'w+').write(content)

	def mime(self):
		import mimetypes
		return mimetypes.guess_type(self.path())[0] or 'application/octet-stream'

	def extension(self):
		return os.path.splitext('name'+self.name())[1].lower()

	def exists(self):
		return os.path.isdir(self.path()) or os.path.isfile(self.path())

	def create(self):
		if self.isDirectory():
			self.dirnameCreate()
			os.makedirs(self.path())
		else:
			self.dirnameCreate()
			self.write('')

	def copy(self, location, replace = False):
		location = SideBarItem(location, os.path.isdir(location));
		if location.exists() and replace == False:
			return False
		elif location.exists() and location.isFile():
			os.remove(location.path())

		location.dirnameCreate();
		if self.isDirectory():
			if location.exists():
				self.copy_recursive(self.path(), location.path())
			else:
				shutil.copytree(self.path(), location.path())
		else:
			shutil.copy2(self.path(), location.path())
		return True

	def copy_recursive(self, _from, _to):

		if os.path.isfile(_from) or os.path.islink(_from):
			try:
				os.makedirs(os.path.dirname(_to));
			except:
				pass
			if os.path.exists(_to):
				os.remove(_to)
			shutil.copy2(_from, _to)
		else:
			try:
				os.makedirs(_to);
			except:
				pass
			for content in os.listdir(_from):
				__from = os.path.join(_from, content)
				__to = os.path.join(_to, content)
				self.copy_recursive(__from, __to)

	def move(self, location, replace = False):
		location = SideBarItem(location, os.path.isdir(location));
		if location.exists() and replace == False:
			if self.path().lower() == location.path().lower():
				pass
			else:
				return False
		elif location.exists() and location.isFile():
			os.remove(location.path())

		if self.path().lower() == location.path().lower():
			location.dirnameCreate();
			os.rename(self.path(), location.path()+'.sublime-temp')
			os.rename(location.path()+'.sublime-temp', location.path())
			self._move_moveViews(self.path(), location.path())
		else:
			location.dirnameCreate();
			if location.exists():
				self.move_recursive(self.path(), location.path())
			else:
				os.rename(self.path(), location.path())
			self._move_moveViews(self.path(), location.path())
		return True

	def move_recursive(self, _from, _to):
		if os.path.isfile(_from) or os.path.islink(_from):
			try:
				os.makedirs(os.path.dirname(_to));
			except:
				pass
			if os.path.exists(_to):
				os.remove(_to)
			os.rename(_from, _to)
		else:
			try:
				os.makedirs(_to);
			except:
				pass
			for content in os.listdir(_from):
				__from = os.path.join(_from, content)
				__to = os.path.join(_to, content)
				self.move_recursive(__from, __to)
			os.rmdir(_from)

	def _move_moveViews(self, old, location):
		for window in sublime.windows():
			active_view = window.active_view()
			views = []
			for view in window.views():
				if view.file_name():
					views.append(view)
			views.reverse();
			for view in views:
				if old == view.file_name():
					active_view = self._move_moveView(window, view, location, active_view)
				elif view.file_name().find(old+'\\') == 0:
					active_view = self._move_moveView(window, view, view.file_name().replace(old+'\\', location+'\\', 1), active_view)
				elif view.file_name().find(old+'/') == 0:
					active_view = self._move_moveView(window, view, view.file_name().replace(old+'/', location+'/', 1), active_view)

	def _move_moveView(self, window, view, location, active_view):
		if active_view == view:
			is_active_view = True
		else:
			is_active_view = False

		options = Object()

		options.scroll = view.viewport_position()

		options.selections = [[item.a, item.b] for item in view.sel()]

		options.marks = [[item.a, item.b] for item in view.get_regions("mark")]

		options.bookmarks = [[item.a, item.b] for item in view.get_regions("bookmarks")]

		if int(sublime.version()) >= 2167:
			options.folds = [[item.a, item.b] for item in view.folded_regions()]
		else:
			options.folds = [[item.a, item.b] for item in view.unfold(sublime.Region(0, view.size()))]

		options.syntax = view.settings().get('syntax')

		try:
			_window = window or view.window() or sublime.active_window()
			options.position = _window.get_view_index(view)
		except:
			options.position = False

		window.focus_view(view)
		if view.is_dirty():
			options.content = view.substr(sublime.Region(0, view.size()))
			view.window().run_command('revert')
		else:
			options.content = False

		_view = view
		view = window.open_file(location)
		window.focus_view(_view)
		window.run_command('close')

		sublime.set_timeout(lambda: self._move_restoreView(view, options, window), 200)

		if is_active_view:
			window.focus_view(view)
			return view
		else:
			window.focus_view(active_view)
			return active_view

	def _move_restoreView(self, view, options, window):
		if view.is_loading():
			sublime.set_timeout(lambda: self._move_restoreView(view, options, window), 100)
		else:
			if options.content != False:
				edit = view.begin_edit()
				view.replace(edit, sublime.Region(0, view.size()), options.content);
				view.sel().clear()
				view.sel().add(sublime.Region(0))
				view.end_edit(edit)

			if options.position != False:
				try:
					_window = window or view.window() or sublime.active_window()
					group, index = options.position
					_window.set_view_index(view, group, index)
				except:
					pass

			if options.syntax:
				view.settings().set('syntax', options.syntax);

			for r in options.folds:
				view.fold(sublime.Region(r[0], r[1]))

			view.sel().clear()
			for r in options.selections:
				view.sel().add(sublime.Region(r[0], r[1]))

			rs = []
			for r in options.marks:
				rs.append(sublime.Region(r[0], r[1]))
			if len(rs):
				view.add_regions("mark", rs, "mark", "dot", sublime.HIDDEN | sublime.PERSISTENT)

			rs = []
			for r in options.bookmarks:
				rs.append(sublime.Region(r[0], r[1]))
			if len(rs):
				view.add_regions("bookmarks", rs, "bookmarks", "bookmark", sublime.HIDDEN | sublime.PERSISTENT)

			view.set_viewport_position(options.scroll, False)

	def close_associated_buffers(self):
		path = self.path()
		closed_items = []
		for window in sublime.windows():
			active_view = window.active_view()
			views = []
			for view in window.views():
				if view.file_name():
					views.append(view)
			views.reverse();
			for view in views:
				if path == view.file_name():
					if view.window():
						closed_items.append([view.file_name(), view.window(), view.window().get_view_index(view)])
					if len(window.views()) == 1:
						window.new_file()
					window.focus_view(view)
					window.run_command('revert')
					window.run_command('close')
				elif view.file_name().find(path+'\\') == 0:
					if view.window():
						closed_items.append([view.file_name(), view.window(), view.window().get_view_index(view)])
					if len(window.views()) == 1:
						window.new_file()
					window.focus_view(view)
					window.run_command('revert')
					window.run_command('close')
				elif view.file_name().find(path+'/') == 0:
					if view.window():
						closed_items.append([view.file_name(), view.window(), view.window().get_view_index(view)])
					if len(window.views()) == 1:
						window.new_file()
					window.focus_view(view)
					window.run_command('revert')
					window.run_command('close')

			# try to repaint
			try:
				window.focus_view(active_view)
				window.focus_view(window.active_view())
			except:
				try:
					window.focus_view(window.active_view())
				except:
					pass
		return closed_items