public SmartHomeWebModule(IFindUserMapper userMapper)
        {
            UserMapper = userMapper;

            // StaticConfiguration.EnableHeadRouting = true;

            Before += ctx =>
            {
                TextResources.Culture = (CultureInfo)this.Request.Session["CurrentCulture"];
                return(null);
            };

            Get["/"] = parameters =>
                       Context.CurrentUser.IsAuthenticated()
                    ? Response.AsRedirect("/newsfeed")
                    : (dynamic)View["home.cshtml"];

            // Pages for individual tables
            Get["/person", true] = GetPerson;

            Post["/person", true] = async(parameters, ct) =>
            {
                this.RequiresAuthentication();
                await FriendRequest(FormHelpers.GetString(Request.Form, "friendname"));

                return(await GetPerson(parameters, ct));
            };

            Get["/person/{username}", true] = GetProfile;

            Post["/person/{username}", true] = async(parameters, ct) =>
            {
                this.RequiresAuthentication();
                await FriendRequest(FormHelpers.GetString(Request.Form, "friendname"));

                return(await GetProfile(parameters, ct));
            };

            Get["/editprofile", true] = GetEditProfile;

            Post["/editprofile", true] = UpdateProfile;

            Get["/person/{username}/wall", true] = GetWall;

            Post["/person/{username}/wall", true] = PostWall;

            Get["/location", true] = async(parameters, ct) =>
            {
                var locations = await DataConnection.Ask(x => x.GetLocationsAndOwnerNamesAsync());

                return(View["location.cshtml", locations]);
            };
            Get["/message", true] = GetMessage;

            Post["/message", true] = PostMessage;

            Get["/friends", true] = GetFriends;

            Post["/friends", true] = PostFriends;

            Get["/friend-request"] = _ => Response.AsRedirect("/friends");

            Post["/friend-request", true] = async(parameters, ct) =>
            {
                this.RequiresAuthentication();
                await FriendRequest(FormHelpers.GetString(Request.Form, "friendname"));

                // TODO: this is a hack. Maybe make which success message to display a parameter of FriendRequest().
                if (!string.IsNullOrEmpty(ViewBag.Success))
                {
                    ViewBag.Success = TextResources.FriendRequestAccepted;
                }

                return(await GetFriends(parameters, ct));
            };

            Get["/sensor", true] = GetSensors;

            Get["/add-sensor/{id?}", true] = GetAddSensor;

            Post["/add-sensor/{id?}", true] = PostAddSensor;

            Get["/edit-sensor/{id}", true] = async(parameters, ct) =>
            {
                this.RequiresAuthentication();
                Sensor calledsensor = await DataConnection.Ask(x => x.GetSensorByIdAsync((int)parameters["id"]));

                return(View["edit-sensor.cshtml", calledsensor]);
            };

            Post["/edit-sensor/{id}", true] = async(parameters, ct) =>
            {
                ViewBag.Success = "";
                ViewBag.Error   = "";

                this.RequiresAuthentication();
                string name        = FormHelpers.GetString(Request.Form, "sensortitle");
                string description = FormHelpers.GetRawString(Request.Form, "descriptiontitle");
                string notes       = FormHelpers.GetRawString(Request.Form, "notestitle");

                Sensor original = await DataConnection.Ask(x => x.GetSensorByIdAsync((int)parameters["id"]));

                SensorData updatebis = new SensorData(name, description, notes, original.Data.LocationId);
                Sensor     update    = new Sensor(original.Id, updatebis);

                await DataConnection.Ask(x => x.UpdateSensorAsync(update));

                ViewBag.Success = TextResources.EditedSensorSuccess;

                return(View["edit-sensor.cshtml", update]);
            };

            Get["/edit-location/{id}", true] = async(parameters, ct) =>
            {
                this.RequiresAuthentication();
                int id  = (int)parameters["id"];
                var loc = await DataConnection.Ask(x => x.GetLocationByIdAsync(id));

                if (loc == null)
                {
                    ViewBag.Error = TextResources.LocationDoesNotExist;
                    loc           = new Location(id, new LocationData("", default(Guid), null));
                }
                return(View["edit-location.cshtml", loc]);
            };

            Post["/edit-location/{id}", true] = async(parameters, ct) =>
            {
                ViewBag.Success = "";
                ViewBag.Error   = "";

                this.RequiresAuthentication();

                int    id           = parameters["id"];
                string name         = FormHelpers.GetString(Request.Form, "locationname");
                string elecPriceStr = FormHelpers.GetString(Request.Form, "electricityprice");
                double?elecPrice    = FormHelpers.ParseDoubleOrNull(elecPriceStr);

                var update = await DataConnection.Ask(async dc =>
                {
                    // Retrieve the location that is being edited.
                    var editLoc = await dc.GetLocationByIdAsync(id);
                    if (editLoc == null)
                    {
                        ViewBag.Error = TextResources.LocationDoesNotExist;
                        return(new Location(id, new LocationData(name, default(Guid), elecPrice)));
                    }

                    var newLoc = new Location(id, new LocationData(name, editLoc.Data.OwnerGuid, elecPrice));

                    if (string.IsNullOrWhiteSpace(name))
                    {
                        // Empty names are silly, and we don't allow them.
                        ViewBag.Error = TextResources.EmptyNameError;
                    }
                    else if (name != editLoc.Data.Name && await dc.GetLocationByNameAsync(name) != null)
                    {
                        // Whoops. Name already exists.
                        ViewBag.Error = string.Format(TextResources.LocationAlreadyExistsError, name);
                    }
                    else if (!string.IsNullOrWhiteSpace(elecPriceStr) && elecPrice == null)
                    {
                        // Couldn't parse electricity price.
                        ViewBag.Error = string.Format(TextResources.ElectricityPriceParseError, elecPriceStr);
                    }
                    else
                    {
                        ViewBag.Success = TextResources.EditLocationSuccess;
                        await dc.UpdateLocationAsync(newLoc);
                    }
                    return(newLoc);
                });

                return(View["edit-location.cshtml", update]);
            };

            Get["/add-tag/{id}", true] = GetAddTag;

            Post["/add-tag/{id}", true] = PostAddTag;

            Get["/measurement", true] = async(parameters, ct) =>
            {
                var measurements = await DataConnection.Ask(x => x.GetRawMeasurementsAsync());

                return(View["measurement.cshtml", measurements]);
            };

            Get["/login"] = _ => View["login.cshtml"];

            Post["/login"] = parameter =>
            {
                string       name = Request.Form.username;
                string       pass = Request.Form.password;
                UserIdentity user;

                if (userMapper.FindUser(name, pass, out user))
                {
                    return(this.LoginAndRedirect(user.Guid, DateTime.Now.AddYears(1)));
                }

                ViewBag.Error = TextResources.InvalidLoginError;
                return(View["login.cshtml"]);
            };
            Get["/logout"] = parameter => this.Logout("/");

            Get["/add-location", true] = GetAddLocation;

            Post["/add-location", true] = PostAddLocation;

            Get["/add-has-location", true] = GetAddHasLocation;

            Post["/add-has-location", true] = async(parameters, ct) =>
            {
                this.RequiresAuthentication();

                var locationId         = int.Parse((string)FormHelpers.GetString(Request.Form, "location"));
                var personLocationPair = new PersonLocationPair(CurrentUserGuid(), locationId);
                await DataConnection.Ask(d => d.InsertHasLocationPairAsync(personLocationPair));

                return(await GetAddHasLocation(parameters, ct));
            };

            Get["/add-person", true] = GetAddPerson;

            Post["/add-person", true] = PostAddPerson;

            Get["/newsfeed", true] = GetNewsfeed;

            Get["/dashboard", true] = GetDashboard;

            Post["/dashboard", true] = PostDashboard;

            Get["/compare-graph", true] = CompareGraph;

            Get["/set-culture"] = parameters =>
            {
                string lcid = Request.Query["lcid"];
                Request.Session["CurrentCulture"] = CultureInfo.GetCultureInfo(lcid);
                var referrer = Request.Headers.Referrer;
                return(Response.AsRedirect(string.IsNullOrWhiteSpace(referrer) ? "/" : referrer));
            };

            Get["/view-graph/{sensorId}/{startTime}/{endTime}/{maxMeasurements}"] = parameters =>
            {
                // sensor ids, start times, end times and max number of measurements are formatted
                // as comma-separated lists.

                var sensorIds       = ((string)parameters["sensorId"]).Split(',').Select(s => int.Parse(s.Trim())).ToArray();
                var startTimes      = ((string)parameters["startTime"]).Split(',').Select(s => DateTime.Parse(s.Trim())).ToArray();
                var endTimes        = ((string)parameters["endTime"]).Split(',').Select(s => DateTime.Parse(s.Trim())).ToArray();
                var maxMeasurements = ((string)parameters["maxMeasurements"]).Split(',').Select(s => int.Parse(s.Trim())).ToArray();

                if (sensorIds.Length != startTimes.Length ||
                    sensorIds.Length != endTimes.Length ||
                    sensorIds.Length != maxMeasurements.Length)
                {
                    return(HttpStatusCode.BadRequest);
                }

                var model = new List <AutofitRange>();
                for (int i = 0; i < sensorIds.Length; i++)
                {
                    model.Add(new AutofitRange(sensorIds[i], startTimes[i], endTimes[i], maxMeasurements[i]));
                }
                return(View["view-graph.cshtml", model]);
            };


            Get["/cluster", true] = getCluster;
        }
        public SmartHomeWebModule(IFindUserMapper userMapper)
        {
            UserMapper = userMapper;

            // StaticConfiguration.EnableHeadRouting = true;

            Before += ctx =>
            {
                TextResources.Culture = (CultureInfo)this.Request.Session["CurrentCulture"];
                return null;
            };

            Get["/"] = parameters =>
                Context.CurrentUser.IsAuthenticated()
                    ? Response.AsRedirect("/newsfeed")
                    : (dynamic)View["home.cshtml"];

            // Pages for individual tables
            Get["/person", true] = GetPerson;

            Post["/person", true] = async (parameters, ct) =>
            {
                this.RequiresAuthentication();
                await FriendRequest(FormHelpers.GetString(Request.Form, "friendname"));
                return await GetPerson(parameters, ct);
            };

            Get["/person/{username}", true] = GetProfile;

            Post["/person/{username}", true] = async (parameters, ct) =>
            {
                this.RequiresAuthentication();
                await FriendRequest(FormHelpers.GetString(Request.Form, "friendname"));
                return await GetProfile(parameters, ct);
            };

            Get["/editprofile", true] = GetEditProfile;

            Post["/editprofile", true] = UpdateProfile;
            
            Get["/person/{username}/wall", true] = GetWall;

            Post["/person/{username}/wall", true] = PostWall;

            Get["/location", true] = async (parameters, ct) =>
            {
				var locations = await DataConnection.Ask(x => x.GetLocationsAndOwnerNamesAsync());
                return View["location.cshtml", locations];
            };
            Get["/message", true] = GetMessage;

            Post["/message", true] = PostMessage;

            Get["/friends", true] = GetFriends;

            Post["/friends", true] = PostFriends;

			Get["/friend-request"] = _ => Response.AsRedirect("/friends");

            Post["/friend-request", true] = async (parameters, ct) =>
            {
                this.RequiresAuthentication();
                await FriendRequest(FormHelpers.GetString(Request.Form, "friendname"));

                // TODO: this is a hack. Maybe make which success message to display a parameter of FriendRequest().
                if (!string.IsNullOrEmpty(ViewBag.Success))
                    ViewBag.Success = TextResources.FriendRequestAccepted;

                return await GetFriends(parameters, ct);
            };

            Get["/sensor", true] = GetSensors;

            Get["/add-sensor/{id?}", true] = GetAddSensor;

            Post["/add-sensor/{id?}", true] = PostAddSensor;

            Get["/edit-sensor/{id}", true] = async (parameters, ct) =>
            {
                this.RequiresAuthentication();
                Sensor calledsensor = await DataConnection.Ask(x => x.GetSensorByIdAsync((int)parameters["id"]));
                return View["edit-sensor.cshtml", calledsensor];
            };

            Post["/edit-sensor/{id}", true] = async (parameters, ct) =>
            {
                ViewBag.Success = "";
                ViewBag.Error = "";

                this.RequiresAuthentication();
                string name = FormHelpers.GetString(Request.Form, "sensortitle");
                string description = FormHelpers.GetRawString(Request.Form, "descriptiontitle");
                string notes = FormHelpers.GetRawString(Request.Form, "notestitle");

                Sensor original = await DataConnection.Ask(x => x.GetSensorByIdAsync((int)parameters["id"]));
                SensorData updatebis = new SensorData(name, description, notes, original.Data.LocationId);
                Sensor update = new Sensor(original.Id, updatebis);

                await DataConnection.Ask(x => x.UpdateSensorAsync(update));

                ViewBag.Success = TextResources.EditedSensorSuccess;

                return View["edit-sensor.cshtml", update];
            };

			Get["/edit-location/{id}", true] = async (parameters, ct) =>
			{
				this.RequiresAuthentication();
				int id = (int)parameters["id"];
				var loc = await DataConnection.Ask(x => x.GetLocationByIdAsync(id));
				if (loc == null)
				{
					ViewBag.Error = TextResources.LocationDoesNotExist;
					loc = new Location(id, new LocationData("", default(Guid), null));
				}
				return View["edit-location.cshtml", loc];
			};

			Post["/edit-location/{id}", true] = async (parameters, ct) =>
			{
				ViewBag.Success = "";
				ViewBag.Error = "";

				this.RequiresAuthentication();

				int id = parameters["id"];
				string name = FormHelpers.GetString(Request.Form, "locationname");
				string elecPriceStr = FormHelpers.GetString(Request.Form, "electricityprice");
				double? elecPrice = FormHelpers.ParseDoubleOrNull(elecPriceStr);

				var update = await DataConnection.Ask(async dc =>
				{
					// Retrieve the location that is being edited.
					var editLoc = await dc.GetLocationByIdAsync(id);
					if (editLoc == null)
					{
						ViewBag.Error = TextResources.LocationDoesNotExist;
						return new Location(id, new LocationData(name, default(Guid), elecPrice));
					}

					var newLoc = new Location(id, new LocationData(name, editLoc.Data.OwnerGuid, elecPrice));

					if (string.IsNullOrWhiteSpace(name))
					{
						// Empty names are silly, and we don't allow them.
						ViewBag.Error = TextResources.EmptyNameError;
					}
					else if (name != editLoc.Data.Name && await dc.GetLocationByNameAsync(name) != null)
					{
						// Whoops. Name already exists.
						ViewBag.Error = string.Format(TextResources.LocationAlreadyExistsError, name);
					}
					else if (!string.IsNullOrWhiteSpace(elecPriceStr) && elecPrice == null)
					{
						// Couldn't parse electricity price.
						ViewBag.Error = string.Format(TextResources.ElectricityPriceParseError, elecPriceStr);
					}
					else
					{
						ViewBag.Success = TextResources.EditLocationSuccess;
						await dc.UpdateLocationAsync(newLoc);
					}
					return newLoc;
				});

				return View["edit-location.cshtml", update];
			};

            Get["/add-tag/{id}", true] = GetAddTag;

            Post["/add-tag/{id}", true] = PostAddTag;

            Get["/measurement", true] = async (parameters, ct) =>
            {
                var measurements = await DataConnection.Ask(x => x.GetRawMeasurementsAsync());
                return View["measurement.cshtml", measurements];
            };

            Get["/login"] = _ => View["login.cshtml"];

            Post["/login"] = parameter =>
            {
                string name = Request.Form.username;
                string pass = Request.Form.password;
                UserIdentity user;

                if (userMapper.FindUser(name, pass, out user))
                    return this.LoginAndRedirect(user.Guid, DateTime.Now.AddYears(1));

                ViewBag.Error = TextResources.InvalidLoginError;
                return View["login.cshtml"];
            };
            Get["/logout"] = parameter => this.Logout("/");
            
            Get["/add-location", true] = GetAddLocation;

			Post["/add-location", true] = PostAddLocation;

            Get["/add-has-location", true] = GetAddHasLocation;

            Post["/add-has-location", true] = async (parameters, ct) =>
            {
                this.RequiresAuthentication();

                var locationId = int.Parse((string) FormHelpers.GetString(Request.Form, "location"));
                var personLocationPair = new PersonLocationPair(CurrentUserGuid(), locationId);
                await DataConnection.Ask(d => d.InsertHasLocationPairAsync(personLocationPair));

                return await GetAddHasLocation(parameters, ct);
            };

            Get["/add-person", true] = GetAddPerson;

            Post["/add-person", true] = PostAddPerson;

            Get["/newsfeed", true] = GetNewsfeed;

            Get["/dashboard", true] = GetDashboard;

            Post["/dashboard", true] = PostDashboard;

            Get["/compare-graph", true] = CompareGraph;

            Get["/set-culture"] = parameters =>
            {
                string lcid = Request.Query["lcid"];
                Request.Session["CurrentCulture"] = CultureInfo.GetCultureInfo(lcid);
                var referrer = Request.Headers.Referrer;
                return Response.AsRedirect(string.IsNullOrWhiteSpace(referrer) ? "/" : referrer);
            };

            Get["/view-graph/{sensorId}/{startTime}/{endTime}/{maxMeasurements}"] = parameters =>
            {
                // sensor ids, start times, end times and max number of measurements are formatted
                // as comma-separated lists.

                var sensorIds = ((string)parameters["sensorId"]).Split(',').Select(s => int.Parse(s.Trim())).ToArray();
                var startTimes = ((string)parameters["startTime"]).Split(',').Select(s => DateTime.Parse(s.Trim())).ToArray();
                var endTimes = ((string)parameters["endTime"]).Split(',').Select(s => DateTime.Parse(s.Trim())).ToArray();
                var maxMeasurements = ((string)parameters["maxMeasurements"]).Split(',').Select(s => int.Parse(s.Trim())).ToArray();
             
                if (sensorIds.Length != startTimes.Length 
                    || sensorIds.Length != endTimes.Length 
                    || sensorIds.Length != maxMeasurements.Length)
                {
                    return HttpStatusCode.BadRequest;
                }

                var model = new List<AutofitRange>();
                for (int i = 0; i < sensorIds.Length; i++)
                {
                    model.Add(new AutofitRange(sensorIds[i], startTimes[i], endTimes[i], maxMeasurements[i]));       
                }
                return View["view-graph.cshtml", model];
            };


            Get["/cluster", true] = getCluster;
        }