public CommonModule(IPdfTemplateHelper pdfTemplateHelper, IEmailer emailer,
            IPdfBarcodesGenerator pdfBarcodesGenerator) : base("/api")
		{
		    _pdfTemplateHelper = pdfTemplateHelper;
            _emailer = emailer;
            _pdfBarcodesGenerator = pdfBarcodesGenerator;
            //	BARCODE FUNCTIONS
			//	Returns a list of airports
			Get["/getAirports"] = _ =>
			{
				var airportList = CustomerSite.ToList().Where(x => x.IsAirport).ToList().OrderBy(x => x.Name);
				return Response.AsJson(airportList.ToList());
			};
			//	Returns a list of airports that have been formatted for a select input
			Get["/getAirportList"] = _ =>
			{
				var airports = CustomerSite.ToList().Where(x => x.IsAirport).ToList();
				List<SelectList> airportList = new List<SelectList>();

				foreach(var airport in airports)
				{
					airportList.Add(new SelectList(){
						id = airport.RecordID,
						text = airport.Name.Trim()
					});
				}

				return Response.AsJson(airportList.OrderBy(x => x.text).ToList());
			};
            
            //	Returns all available pdf templates
		    Get["/getPdfTemplates"] = _ => Response.AsJson(_pdfTemplateHelper.GetTemplates());

            //	Returna a list of Airlines
            Get["/getAirlines"] = _ =>
			{
				var airlineList = AirlineDBO.ToList().OrderBy(x => x.Name);
				return Response.AsJson(airlineList.ToList());
			};
			//	Returns a list of Airlines that have been formatted for a select input
			Get["/getAirlineList"] = _ =>
			{
				var airlines = AirlineDBO.ToList();
				List<SelectList> airlineList = new List<SelectList>();

				foreach(var airline in airlines)
				{
					airlineList.Add(new SelectList()
					{
						id = airline.RecordID,
						text = airline.Name.Trim()
					});
				}

				return Response.AsJson(airlineList.OrderBy(x => x.text).ToList());
			};
            //  Returns a list of barcodes
            Post["/getBarcodes/{type}"] = _ =>
            {
				BarcodeWhere where = this.Bind<BarcodeWhere>();
				DateTime start = new DateTime();
				DateTime end = new DateTime();
				bool validStart = DateTime.TryParse(where.StartDate, out start);
				bool validEnd = DateTime.TryParse(where.EndDate, out end);
				//	If no dates were provided, this gets all.
				if(!validStart && !validEnd)
				{
					var barcodeList = BarcodeCreation.ToListDTO();
					return Response.AsJson(barcodeList.OrderByDescending(x => x.CreatedDateTime).ToList());
				}
				//	If one of the dates isn't valid, this returns.
				else if(!validStart || !validEnd)
				{
					return HttpStatusCode.BadRequest;
				}
				//	Otherwise this returns the filtered results
				else
				{
					var barcodeList = BarcodeCreation.ToListDTO(start, end);
					return Response.AsJson(barcodeList.OrderByDescending(x => x.CreatedDateTime).ToList());
				}
            };
			//	Returns all the details of a barcode - BarcodeCreation, FastTrackBarcode, FastTrackBarcode.Actions
			Get["/getBarcode/{type}/{recordID}"] = _ =>
			{
				Guid recordID;
				bool validGuid = Guid.TryParse(_.recordID, out recordID);
				//	If an invalid Guid was provided, return bad request
				if (!validGuid)
				{
					return HttpStatusCode.BadRequest;
				}
				var barcode = BarcodeCreation.Load(recordID);
				return Response.AsJson(barcode);
			};
			//	Returns a list of barcode actions
			Get["/getBarcodeActions/{type}/{recordID}"] = _ =>
			{
				Guid recordGUID;
				bool validGuid = Guid.TryParse(_.recordID, out recordGUID);
				if (!validGuid)
				{
					return HttpStatusCode.BadRequest;
				}
				var fastTrackActions = FastTrackBarcode.Actions(recordGUID);
				return Response.AsJson(fastTrackActions);
			};
			//	For creating a barcode
			Post["/createBarcode/{type}/{format}"] = _ =>
			{
				string type = _.type;
				string format = _.format;
				//	If departure airport, copy to guid field and then replace with iata
			    IBarcodeGenerator barcodeGenerator = null;
			    FastTrackOptions barcodeOptions = new FastTrackOptions
			    {
			        Quantity = 1
			    };

                Guid temp = new Guid();
                //	Generate barcode
                switch (type)
				{
					case "fasttrack":
				        barcodeGenerator =
				            new AddbarcodeCreationRecordToDb(new SaveFastTrackBarcodeRecordToDb(new BarcodeGenerator()));

                        barcodeOptions = this.Bind<FastTrackOptions>();

                        //	If airline, copy to guid field and then replace with iata, unless it is ---
                        if (!string.IsNullOrWhiteSpace(barcodeOptions.Airline) && barcodeOptions.Airline.Trim() != "---")
						{
							if(Guid.TryParse(barcodeOptions.Airline, out temp))
							{
								Airline airline = Airline.Load(temp);
								//	If no airline was found, empty airline fields
								if(airline == null)
								{
									barcodeOptions.Airline = "---";
									barcodeOptions.AirlineGuid = null;
								}
								//	Otherwise update fields
								else
								{
									barcodeOptions.Airline = airline.AirlineIATA;
									barcodeOptions.AirlineGuid = temp;
								}
							}
						}
						//	If departure airport, copy to guid field and then replace with iata
						if (!string.IsNullOrWhiteSpace(barcodeOptions.DepartureAirport))
						{
							if(Guid.TryParse(barcodeOptions.DepartureAirport, out temp))
							{
								CustomerSite site = CustomerSite.Load(temp);
								//	If no airport was found, that means it doesn't exist, so empties departure fields
								if(site == null)
								{
									barcodeOptions.DepartureAirport = null;
									barcodeOptions.DepartureAirportGuid = null;
								}
								//	Otherwise update fields
								else
								{
									barcodeOptions.DepartureAirportGuid = temp;
									barcodeOptions.DepartureAirport = site.AirportIATADesignation;
								}
							}
						}
						//	If destination airport, copy to guid field and then replace with iata
						if (!string.IsNullOrWhiteSpace(barcodeOptions.DestinationAirport))
						{
							if (Guid.TryParse(barcodeOptions.DestinationAirport, out temp))
							{
								//	If the same as departure, just copy name
								if(barcodeOptions.DepartureAirport == barcodeOptions.DestinationAirport)
								{
									barcodeOptions.DestinationAirport = barcodeOptions.DepartureAirport;
									barcodeOptions.DestinationAirportGuid = barcodeOptions.DepartureAirportGuid;
								}
								//	Otherwise load airport details
								else
								{
									CustomerSite site = CustomerSite.Load(temp);
									//	If no airport was found, that means it doesn't exist, so empties departure fields
									if (site == null)
									{
										barcodeOptions.DestinationAirport = null;
										barcodeOptions.DestinationAirportGuid = null;
									}
									//	Otherwise update fields
									else
									{
										barcodeOptions.DestinationAirportGuid = temp;
										barcodeOptions.DestinationAirport = site.AirportIATADesignation;
									}
								}
							}
						}
						break;
					case "test":
                        barcodeGenerator = new TestBarcodeGenerator();
						break;
					default:
						return HttpStatusCode.BadRequest;
				}
				switch (format)
				{
					case "image":
						List<string> returnText = new List<string>();
                        IBarcodeFileGenerator imageGenerator = new BarcodeImageFileGenerator(barcodeGenerator);

                        for (var i = 0; i < barcodeOptions.Quantity; i++)
				        {
				            returnText.Add(Convert.ToBase64String(imageGenerator.GenerateFile(barcodeOptions).ToArray()));
				        }

						return Response.AsJson(returnText);
					//break;
					case "email":
				        var result = new EmailFastTrackBarcodes(_emailer).EmailBarcodeFile(barcodeOptions,
				            new BarcodePdfFileGenerator(barcodeGenerator, _pdfBarcodesGenerator));

				        return result ? HttpStatusCode.Accepted : HttpStatusCode.BadRequest;
					case "pdf":
				        var stream =
				            new BarcodePdfFileGenerator(barcodeGenerator, _pdfBarcodesGenerator).GenerateFile(barcodeOptions);
                        var streamClone = new MemoryStream(stream.ToArray());
                        Response response = new Response();
				        response.Headers.Add("Content-Disposition",
				            "attachment; filename=GeneratedBarcode" + DateTime.Now.ToString("dd MMM yyyy HH mm") + ".pdf");

						response.Headers.Add("responseType", "arraybuffer");
						response.Contents = responseStream =>
						{
                            streamClone.CopyTo(responseStream);
						};
						return response;
				}
				//	Return BadRequest if not returned already
				return HttpStatusCode.BadRequest;
			};
			//	Exports all the barcodes
			Post["/exportBarcodes/{type}"] = _ =>
			{
				List<string> barcodeGuids = this.BindTo(new List<string>());
				//	If no guids were posted, export all
				if (barcodeGuids.Count() == 0)
				{
					return CSVExporter.ExportBarcodes();
				}
				//	Otherwise export select few
				else
				{
					return CSVExporter.ExportBarcodes(barcodeGuids);
				}
			};
			//	logs the user in using sems data object
			Post["/login/{type}"] = _ =>
			{
				//bind to object model
				var loginParams = this.Bind<Login>();
				//decrypt username
				loginParams.Username = Decrypt.DecryptString(loginParams.Username, _.type + "key");
				//pass sems data obejct user method the username
				var user = User.LoadUser(loginParams.Username);
				//if no user, return 401
				if (user == null)
				{
					Console.WriteLine("No User");
					return HttpStatusCode.Unauthorized;
				}
				//decrypt password
				loginParams.Password = Decrypt.DecryptString(loginParams.Password, _.type + "key");
				//if incorrect password, return 401
				if (user.Password != loginParams.Password)
				{
					Console.WriteLine("Wrong Password");
					return HttpStatusCode.Unauthorized;
				}
				var token = user.RecordID;
				//login but dont redirect, this is handled front end by angular
				return this.LoginWithoutRedirect(token);
			};
			//	logs the user in using sems data object
			Post["/login"] = _ =>
            {
                //bind to object model
                var loginParams = this.Bind<Login>();
				//pass sems data obejct user method the username
				var user = MachSecure.SEMS.DataObjects.User.LoadUser(loginParams.Username);
                //if no user, return 401
                if (user == null)
				{
					Console.WriteLine("Wrong Username");
					return HttpStatusCode.Unauthorized;
				}
                //if incorrect password, return 401
                if (user.Password != loginParams.Password)
				{
					Console.WriteLine("Wrong Password");
					return HttpStatusCode.Unauthorized;
				}
				var token = user.RecordID;
                //login but dont redirect, this is handled front end by angular
                return this.LoginWithoutRedirect(token);
            };
			//	log the user out and redirect to home
            Get["/logout"] = _ => this.LogoutAndRedirect("../#/");
			//	Gets the current logged in user
            Get["/user"] = _ =>
            {
                var user = Context.CurrentUser;
                return Response.AsJson(user);
            };
			//	Tests connection
            Get["/test"] = _ =>
            {
                List<string> s = new List<string>();
				//SMTP.SendEmail("*****@*****.**", "Test Email", "This is a test e-mail");

				for (int i = 0; i < 1000000; i++)
                {
                    s.Add("test");
                }

                return Response.AsJson(s);
            };
		//	/BARCODE ACTIONS
		//	ROSTER IMPORT FUNCTIONS
			//	Returns contents of a csv file
			Post["/readCSV"] = _ =>
			{
				ReadCsvOptions options = this.Bind<ReadCsvOptions>();
				ReturnResult result = new ReturnResult();
				var files = Request.Files;
				//	If no file, return
				if(files.Count() == 0)
				{
					result.Success = false;
					result.Error = "No file found";
					result.ErrorDescription = "No CSV file was uploaded";
					result.Result = null;
					return Response.AsJson(result);
				}
				List<CsvObject> csvs = new List<CsvObject>();
				foreach (var file in files)
				{
					string extension = Path.GetExtension(file.Name);
					//	If not a csv file, return
					if(extension != ".csv")
					{
						result.Success = false;
						result.Error = "Invalid file";
						result.ErrorDescription = file.Name + " is not a csv file";
						result.Result = null;
						return Response.AsJson(result);
					}
					StreamReader csvReader = new StreamReader(file.Value);
					CsvObject csv = new CsvObject();
					List<string[]> rows = new List<string[]>();
					int index = 0;
					bool escape = false;
					while (!csvReader.EndOfStream && escape != true)
					{
						string line = csvReader.ReadLine();
						string[] values = line.Split(',');
						//	If headers, place into headers string[]
						if (index == 0)
						{
							csv.Headers = values;
						}
						else
						{
							rows.Add(values);
						}
						index++;
						//	If there is a limit, and this exceeds it, this sets escape to true
						if (options.Limit != null && options.Limit > 0 && index > options.Limit)
						{
							escape = true;
						}
					}
					csv.Rows = rows;
					csvs.Add(csv);
				}
				//	To get this far, it was successful, so it returns so
				result.Success = true;
				result.Error = null;
				result.ErrorDescription = null;
				result.Result = csvs;
				return Response.AsJson(result);
			};
		//	/ROSTER IMPORT FUNCTIONS
		}
 public BarcodePdfFileGenerator(IBarcodeGenerator barcodeGenerator, IPdfBarcodesGenerator pdfBarcodesGenerator)
 {
     _barcodeGenerator = barcodeGenerator;
     _pdfBarcodesGenerator = pdfBarcodesGenerator;
 }