#!/usr/bin/python

import json
import tornado.web

from . import base
from . import ui_modules

class BaseHandler(base.BaseHandler):
	@property
	def when(self):
		return self.get_argument_date("when", None)


class ProfileSendHandler(BaseHandler):
	def check_xsrf_cookie(self):
		# This cookie is not required here.
		pass

	def get_profile_blob(self):
		profile = self.get_argument("profile", None)

		# Send "400 bad request" if no profile was provided
		if not profile:
			raise tornado.web.HTTPError(400, "No profile received")

		# Try to decode the profile
		try:
			return json.loads(profile)
		except json.decoder.JSONDecodeError as e:
			raise tornado.web.HTTPError(400, "Profile could not be decoded: %s" % e)

	def post(self, public_id):
		profile_blob = self.get_profile_blob()

		# Handle the profile.
		with self.db.transaction():
			try:
				self.fireinfo.handle_profile(public_id, profile_blob,
					country_code=self.current_country_code,
					asn=self.current_address.asn if self.current_address else None)

			except ValueError as e:
				raise tornado.web.HTTPError(400, "Could not process profile: %s" % e)

		self.finish("Your profile was successfully saved to the database.")


class IndexHandler(base.AnalyticsMixin, BaseHandler):
	def get(self):
		data = {
			"when"           : self.when,

			# Release
			"latest_release" : self.backend.releases.get_latest(),

			# Hardware
			"arches"         : self.fireinfo.get_arch_map(when=self.when),
			"cpu_vendors"    : self.fireinfo.get_cpu_vendors_map(when=self.when),

			# Memory
			"memory_avg"     : self.backend.fireinfo.get_average_memory_amount(when=self.when),

			# Virtualization
			"hypervisors"    : self.fireinfo.get_hypervisor_map(when=self.when),
			"virtual_ratio"  : self.fireinfo.get_virtual_ratio(when=self.when),

			# Location
			"locations"      : self.fireinfo.get_geo_location_map(when=self.when),
		}

		self.render("fireinfo/index.html", **data)


class DriverDetail(base.AnalyticsMixin, BaseHandler):
	def get(self, driver):
		devices = self.fireinfo.get_devices_by_driver(driver, when=self.when)

		self.render("fireinfo/driver.html", driver=driver, devices=devices)


class ProfileHandler(base.AnalyticsMixin, BaseHandler):
	def get(self, profile_id):
		profile = self.fireinfo.get_profile(profile_id, when=self.when)

		if not profile or not profile.is_showable():
			raise tornado.web.HTTPError(404)

		self.render("fireinfo/profile.html", profile=profile)


class RandomProfileHandler(base.AnalyticsMixin, BaseHandler):
	def get(self):
		profile = self.fireinfo.get_random_profile(when=self.when)
		if not profile:
			raise tornado.web.HTTPError(404, "Could not find a random profile")

		self.redirect("/fireinfo/profile/%s" % profile.profile_id)


class ReleasesHandler(base.AnalyticsMixin, BaseHandler):
	def get(self):
		data = {
			"releases" : self.fireinfo.get_releases_map(when=self.when),
			"kernels"  : self.fireinfo.get_kernels_map(when=self.when),
		}

		return self.render("fireinfo/releases.html", **data)


class ProcessorsHandler(base.AnalyticsMixin, BaseHandler):
	def get(self):
		return self.render("fireinfo/processors.html", when=self.when)


class VendorsHandler(base.AnalyticsMixin, BaseHandler):
	def get(self):
		vendors = self.fireinfo.get_vendor_list(when=self.when)

		self.render("fireinfo/vendors.html", vendors=vendors)


class VendorHandler(base.AnalyticsMixin, BaseHandler):
	def get(self, subsystem, vendor_id):
		devices = self.fireinfo.get_devices_by_vendor(subsystem, vendor_id, when=self.when)
		if not devices:
			raise tornado.web.HTTPError(404)

		vendor_name = self.fireinfo.get_vendor_string(subsystem, vendor_id)

		self.render("fireinfo/vendor.html", vendor_name=vendor_name, devices=devices)


class DeviceTableModule(ui_modules.UIModule):
	def render(self, devices, show_group=True, embedded=False):
		return self.render_string("fireinfo/modules/table-devices.html",
				devices=devices, show_group=show_group, embedded=embedded)


class DeviceAndGroupsTableModule(ui_modules.UIModule):
	def render(self, devices):
		_ = self.locale.translate

		groups = {}

		for device in devices:
			if device.cls not in groups:
				groups[device.cls] = []

			groups[device.cls].append(device)

		# Sort all devices
		for key in list(groups.keys()):
			groups[key].sort()

		# Order the groups by their name
		groups = list(groups.items())
		groups.sort()

		return self.render_string("fireinfo/modules/table-devices-and-groups.html",
				groups=groups)


class AdminIndexHandler(BaseHandler):
	@tornado.web.authenticated
	def prepare(self):
		if not self.current_user.is_staff():
			raise tornado.web.HTTPError(401)

	@tornado.web.authenticated
	def get(self):
		with_data, total = self.backend.fireinfo.get_active_profiles()

		# Fetch the ASN map
		asn_map = self.backend.fireinfo.get_asn_map()

		self.render("fireinfo/admin.html", with_data=with_data, total=total,
			asn_map=asn_map)
