#!/usr/bin/env python

# Based off of the similar structure from requests:
# https://raw.githubusercontent.com/kennethreitz/requests/v1.2.3/requests/structures.py

import collections

class CaseInsensitiveDict(collections.MutableMapping):
	def __init__(self, data=None, **kwargs):
		self._store = dict()
		if data is None:
			data = {}
		self.update(data, **kwargs)

	def __setitem__(self, key, value):
		# Use the lowercased key for lookups, but store the actual
		# key alongside the value.
		self._store[key.lower()] = (key, value)

	def __getitem__(self, key):
		return self._store[key.lower()][1]

	def __delitem__(self, key):
		del self._store[key.lower()]

	def __iter__(self):
		return (casedkey for casedkey, mappedvalue in self._store.values())

	def __len__(self):
		return len(self._store)

	def lower_items(self):
		"""Like iteritems(), but with all lowercase keys."""
		return (
				(lowerkey, keyval[1])
				for (lowerkey, keyval)
				in self._store.items()
				)

	def __eq__(self, other):
		if isinstance(other, collections.Mapping):
			other = CaseInsensitiveDict(other)
		else:
			return NotImplemented

		# Compare insensitively
		return dict(self.lower_items()) == dict(other.lower_items())

	# Copy is required
	def copy(self):
		return CaseInsensitiveDict(self._store.values())

	def __repr__(self):
		def pp(items):
			s = '\n'
			for i in items:
				s += '  {}: {}\n'.format(i, items[i])
			return s

		return '{}({})'.format(self.__class__.__name__, pp(dict(self.items())))

