import hashlib
import os
import os.path
import requests
import requests.exceptions
import shutil
import zipfile

try:
	import urlparse
except ImportError:
	# pylint: disable=import-error, no-name-in-module
	import urllib.parse
	urlparse = urllib.parse
	# pylint: enable=import-error, no-name-in-module

from .exceptions import SolderAPIError

class SolderServer(object):
	SOLDER_CACHE = os.path.join(os.path.expanduser('~'), '.solder-cache')

	def __init__(self, solder_url):
		self.solder_url = solder_url

		self._modpacks = None

	def get_mod_info(self, slug):
		return self._request(
			'/api/mod/{slug}',
			'GET',
			slug = slug,
		)

	def get_modpack_info(self, slug):
		return self._request(
			'/api/modpack/{slug}',
			'GET',
			slug = slug,
		)

	def get_modpack_build_info(self, slug, build):
		return self._request(
			'/api/modpack/{slug}/{build}',
			'GET',
			slug  = slug,
			build = build,
		)

	def download_modpack(self, slug, build, callback):
		build_info = self.get_modpack_build_info(slug, build)

		for mod in build_info['mods']:
			self._download_mod(mod, callback)

	@property
	def server_info(self):
		info = self._request(
			'/api',
			'GET',
		)

		return (info['version'], info['stream'])

	@property
	def modpacks(self):
		if not self._modpacks:
			self._modpacks = self._request('/api/modpack', 'GET')['modpacks']

		return self._modpacks

	def _request(self, url, method, **kwargs):
		url_parts = urlparse.urlparse(self.solder_url)

		url = urlparse.urlunparse(
			(
				url_parts.scheme,
				url_parts.netloc,
				url.format(**kwargs),
				'',
				'',
				'',
			)
		)

		resp = requests.request(method, url)

		if not resp.status_code == 200:
			raise SolderAPIError('API connection error ({})'.format(resp.status_code))

		json_resp = resp.json()
		if 'error' in json_resp:
			raise SolderAPIError(json_resp['error'])

		return json_resp

	@staticmethod
	def _download_mod(mod_info, callback = None):
		if callback:
			callback('mod.download.start', name = mod_info['name'])

		url      = mod_info['url']
		filename = os.path.basename(url)

		if not os.path.exists(SolderServer.SOLDER_CACHE):
			os.mkdir(SolderServer.SOLDER_CACHE)

		if os.path.exists(os.path.join(SolderServer.SOLDER_CACHE, filename)):
			if callback:
				callback('mod.download.cache')

			shutil.copy(os.path.join(SolderServer.SOLDER_CACHE, filename), '.')
		else:
			resp = requests.get(url, stream = True)
			with open(filename, 'wb') as file_handle:
				for chunk in resp.iter_content(chunk_size = 1024):
					if chunk:
						file_handle.write(chunk)
						file_handle.flush()

			if callback:
				callback('mod.download.verify')

			md5 = hashlib.md5(open(filename, 'rb').read()).hexdigest()
			if md5 != mod_info['md5']:
				if callback:
					callback('mod.download.verify.error')

				return

			shutil.copy(filename, os.path.join(SolderServer.SOLDER_CACHE, filename))

		if callback:
			callback('mod.download.unpack')

		with zipfile.ZipFile(filename, 'r') as zip_handle:
			zip_handle.extractall()

		if callback:
			callback('mod.download.clean')

		os.remove(filename)

		if callback:
			callback('mod.download.finish')


@@ -1933,24 +1933,28 @@
 None):%0A%09%09if 
+not 
 callback:%0A%09%09
@@ -1944,32 +1944,172 @@
  not callback:%0A%09
+%09%09# pylint: disable=unused-argument%0A%09%09%09def skip(status, *args, **kwargs):%0A%09%09%09%09pass%0A%0A%09%09%09callback = skip%0A%09%09%09# pylint: enable=unused-argument%0A%0A
 %09%09callback('mod.
@@ -2380,33 +2380,16 @@
 name)):%0A
-%09%09%09if callback:%0A%09
 %09%09%09callb
@@ -2414,16 +2414,16 @@
 cache')%0A
+
 %0A%09%09%09shut
@@ -2710,33 +2710,16 @@
 lush()%0A%0A
-%09%09%09if callback:%0A%09
 %09%09%09callb
@@ -2745,16 +2745,16 @@
 erify')%0A
+
 %0A%09%09%09md5 
@@ -2842,26 +2842,8 @@
 '%5D:%0A
-%09%09%09%09if callback:%0A%09
 %09%09%09%09
@@ -2880,16 +2880,16 @@
 error')%0A
+
 %0A%09%09%09%09ret
@@ -2970,32 +2970,16 @@
 name))%0A%0A
-%09%09if callback:%0A%09
 %09%09callba
@@ -3004,16 +3004,16 @@
 npack')%0A
+
 %0A%09%09with 
@@ -3086,32 +3086,16 @@
 tall()%0A%0A
-%09%09if callback:%0A%09
 %09%09callba
@@ -3119,16 +3119,16 @@
 clean')%0A
+
 %0A%09%09os.re
@@ -3147,24 +3147,8 @@
 e)%0A%0A
-%09%09if callback:%0A%09
 %09%09ca

Remove unnecessary callback branches