/// <summary>
        /// Get a zip file containing all shape files
        /// </summary>
        /// <remarks>
        /// HTTP GET call format:http://{server}/api/EPADelineate?watershedOutletLat=latValue&watershedOutletLon=lonValue
        /// </remarks>
        /// <param name="watershedOutletLat">Latidue of the watershed outlet location based on WGS84 datum</param>
        /// <param name="watershedOutletLon">Longitude of the watershed outlet location based on WGS84 datum</param>
        /// <returns>A zip file of all shape files, shape files data based on WGS84 datum</returns>
        public HttpResponseMessage GetShapeFiles(double watershedOutletLat, double watershedOutletLon)
        {
            HttpResponseMessage response = new HttpResponseMessage();
            ServiceContext db = new ServiceContext();
            ServiceLog serviceLog = null;
            try
            {
                var service = db.Services.First(s => s.APIName == "EPADelineateController.GetShapeFiles");
                serviceLog = new ServiceLog
                                    {
                                        JobID = Guid.NewGuid().ToString(),
                                        ServiceID = service.ServiceID,
                                        CallTime = DateTime.Now,
                                        StartTime = DateTime.Now,
                                        RunStatus = RunStatus.Processing
                                    };

                db.ServiceLogs.Add(serviceLog);
                db.SaveChanges();

                serviceLog = db.ServiceLogs.First(s => s.JobID == serviceLog.JobID);

                Delineate(watershedOutletLat, watershedOutletLon);

                // Ref:http://stackoverflow.com/questions/12145390/how-to-set-downloading-file-name-in-asp-net-mvc-web-api
                // create a zip file of all shapes files
                string zipFilePath = Path.Combine(_targetShapeFileZipDirPath, "shapefiles.zip");

                if (File.Exists(zipFilePath))
                {
                    File.Delete(zipFilePath);
                }

                ZipFile.CreateFromDirectory(_targetShapeFilesDirPath, zipFilePath);

                // load the zip file to memory
                MemoryStream ms = new MemoryStream();

                using (FileStream file = new FileStream(zipFilePath, FileMode.Open, FileAccess.Read))
                {
                    file.CopyTo(ms);
                    file.Close();
                    if (ms.Length == 0)
                    {
                        string errMsg = "No watershed exists for the selected outlet location.";
                        logger.Error(errMsg);
                        return Request.CreateErrorResponse(HttpStatusCode.NotFound, errMsg);
                    }
                    response.StatusCode = HttpStatusCode.OK;
                    ms.Position = 0;
                    response.Content = new StreamContent(ms);
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

                    // Ref: http://weblogs.asp.net/cibrax/archive/2011/04/25/implementing-caching-in-your-wcf-web-apis.aspx
                    // set the browser to cache this response for 10 secs only
                    response.Content.Headers.Expires = DateTime.Now.AddSeconds(10);
                    response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                    {
                        FileName = UEB.UEBSettings.WATERSHED_SHAPE_ZIP_FILE_NAME
                    };

                    logger.Info("All shape files were zipped and sent to the client as a zip file.");
                }

                // clean up the temporary folders for shape files
                DirectoryInfo dir = new DirectoryInfo(_targetShapeFileGuidDirPath);
                dir.Delete(true);
                serviceLog.RunStatus = RunStatus.Success;
                serviceLog.FinishTime = DateTime.Now;
                db.SaveChanges();

            }
            catch (Exception ex)
            {
                logger.Fatal(ex.Message);
                serviceLog.RunStatus = RunStatus.Error;
                serviceLog.FinishTime = DateTime.Now;
                serviceLog.Error = ex.Message;
                db.SaveChanges();
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
            }

            return response;
        }
        public HttpResponseMessage PostRunUEB()
        {
            HttpResponseMessage response = new HttpResponseMessage();
            ServiceContext db = new ServiceContext();

            string modelRunRootPath = string.Empty;
            string uebInputPackageZipFileName = "ueb_input_package.zip";
            string uebInputPackageZipFile = string.Empty;
            string uebExecutableFilesPath = string.Empty;
            string uebExecutionControlFileName = UEB.UEBSettings.UEB_EXECUTION_CONTROL_FILE_NAME;
            string msg = string.Empty;
            ServiceLog serviceLog = null;

            // get the ueb model package zip file from the request
            Stream uebPackageZipFileFromClient = null;

            try
            {
                var t_stream = this.Request.Content.ReadAsStreamAsync().ContinueWith(s =>
                {
                    uebPackageZipFileFromClient = s.Result;
                });
                t_stream.Wait();

                msg = string.Format("Input model package zip file was read from the http request.");
                logger.Info(msg);
            }
            catch (Exception ex)
            {
                logger.Fatal(ex.Message);
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
            }

            if (uebPackageZipFileFromClient == null)
            {
                string errMsg = "No model package file was received from the client.";
                logger.Error(errMsg);
                response.StatusCode = HttpStatusCode.BadRequest;
                response.Content = new StringContent(errMsg);
                return response;
            }

            // generate a guid to pass on to the client as a job ID and use this as part of creating a unique folder
            // for model run output
            Guid jobGuid = Guid.NewGuid();
            modelRunRootPath = Path.Combine(UEB.UEBSettings.WORKING_DIR_PATH, jobGuid.ToString(), UEB.UEBSettings.UEB_RUN_FOLDER_NAME);
            uebInputPackageZipFile = Path.Combine(modelRunRootPath, uebInputPackageZipFileName);
            Directory.CreateDirectory(modelRunRootPath);
            msg = string.Format("Directory ({0}) was created for running ueb model.", modelRunRootPath);
            logger.Info(msg);

            try
            {
                var service = db.Services.First(s => s.APIName == "RunUEBController.PostRunUEB");

                serviceLog = new ServiceLog
                {
                    JobID = jobGuid.ToString(),
                    ServiceID = service.ServiceID,
                    CallTime = DateTime.Now,
                    StartTime = DateTime.Now,
                    RunStatus = RunStatus.Processing
                };

                db.ServiceLogs.Add(serviceLog);
                db.SaveChanges();

                serviceLog = db.ServiceLogs.First(s => s.JobID == serviceLog.JobID);

                // save the recieved package file locally for ueb to use
                using (var fileStream = File.Create(uebInputPackageZipFile))
                {
                    uebPackageZipFileFromClient.CopyTo(fileStream);
                }

                msg = string.Format("Input model package zip file was saved: {0}.", uebInputPackageZipFile);
                logger.Info(msg);
            }
            catch (Exception ex)
            {
                serviceLog.RunStatus = RunStatus.Error;
                serviceLog.FinishTime = DateTime.Now;
                serviceLog.Error = ex.Message;
                db.SaveChanges();

                logger.Fatal(ex.Message);
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
            }

            // unzip the request zip file
            ZipFile.ExtractToDirectory(uebInputPackageZipFile, modelRunRootPath);

            // copy the UEB executables and dlls to model run folder
            uebExecutableFilesPath = UEB.UEBSettings.UEB_EXECUTABLE_DIR_PATH;
            string[] files = Directory.GetFiles(uebExecutableFilesPath);
            string fileName = string.Empty;
            string destFile = string.Empty;

            foreach (string file in files)
            {
                // Use static Path methods to extract only the file name from the path.
                fileName = Path.GetFileName(file);
                destFile = Path.Combine(modelRunRootPath, fileName);

                // Copy the file and overwrite destination file if they already exist.
                File.Copy(file, destFile, true);
            }

            //Run ueb in async mode
            RunUEB(modelRunRootPath, uebInputPackageZipFile, jobGuid.ToString());

            UebRunStatusResponse uebRunStatus = new UebRunStatusResponse();
            uebRunStatus.Message = "UEB execution has started.";
            uebRunStatus.RunJobID = jobGuid.ToString();
            string jsonResponse = JsonConvert.SerializeObject(uebRunStatus, Formatting.Indented);
            response.StatusCode = HttpStatusCode.OK;
            response.Content = new StringContent(jsonResponse);
            return response;
        }
        /// <summary>
        /// Creates UEB model package
        /// <remarks>
        /// POST is used since the input data needs to come in as a zip file in the body of the request
        /// and can't be sent as query parameter
        /// </remarks>
        /// </summary>
        /// <returns></returns>
        public HttpResponseMessage PostUEBPackageCreate()
        {
            string uebPackageBuildRequestJson = string.Empty;
            HttpResponseMessage response = new HttpResponseMessage();
            Stream uebPackageBuildRequestZipFile = null;
            ServiceContext db = new ServiceContext();
            ServiceLog serviceLog = null;

            var t_stream = this.Request.Content.ReadAsStreamAsync().ContinueWith(s =>
            {
                uebPackageBuildRequestZipFile = s.Result;
            });
            t_stream.Wait();

            // generate a guid to pass on to the client as a job ID
            Guid jobGuid = Guid.NewGuid();

            // set the package request processing root dir path
            _packageRequestProcessRootDirPath = Path.Combine(UEB.UEBSettings.WORKING_DIR_PATH, jobGuid.ToString());

            // set other directory paths necessary for processing the request to build ueb package
            _sourceFilePath = _packageRequestProcessRootDirPath;
            _targetTempPackageFilePath = Path.Combine(_packageRequestProcessRootDirPath, UEB.UEBSettings.PACKAGE_FILES_OUTPUT_SUB_DIR_PATH);
            _targetPackageDirPath = Path.Combine(_packageRequestProcessRootDirPath, UEB.UEBSettings.PACKAGE_OUTPUT_SUB_DIR_PATH);

            // set the path for saving the client request zip file
            _clientPackageRequestDirPath = Path.Combine(_packageRequestProcessRootDirPath, UEB.UEBSettings.PACKAGE_BUILD_REQUEST_SUB_DIR_PATH);
            string packageRequestZipFile = Path.Combine(_clientPackageRequestDirPath, UEB.UEBSettings.PACKAGE_BUILD_REQUEST_ZIP_FILE_NAME);
            try
            {
                var service = db.Services.First(s => s.APIName == "GenerateUEBPackageController.PostUEBPackageCreate");

                serviceLog = new ServiceLog
                {
                    JobID = jobGuid.ToString(),
                    ServiceID = service.ServiceID,
                    CallTime = DateTime.Now,
                    RunStatus = RunStatus.InQueue
                };

                db.ServiceLogs.Add(serviceLog);
                db.SaveChanges();

                serviceLog = db.ServiceLogs.First(s => s.JobID == serviceLog.JobID);

                if (Directory.Exists(_packageRequestProcessRootDirPath))
                {
                    Directory.Delete(_packageRequestProcessRootDirPath);
                }

                Directory.CreateDirectory(_packageRequestProcessRootDirPath);

                if (Directory.Exists(_targetTempPackageFilePath))
                {
                    Directory.Delete(_targetTempPackageFilePath);
                }

                Directory.CreateDirectory(_targetTempPackageFilePath);

                if (Directory.Exists(_clientPackageRequestDirPath))
                {
                    Directory.Delete(_clientPackageRequestDirPath);
                }

                Directory.CreateDirectory(_clientPackageRequestDirPath);

                using (var fileStream = File.Create(packageRequestZipFile))
                {
                    uebPackageBuildRequestZipFile.CopyTo(fileStream);
                }

                // unzip the request zip file
                ZipFile.ExtractToDirectory(packageRequestZipFile, _clientPackageRequestDirPath);
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);
                response.StatusCode = HttpStatusCode.BadRequest;
                response.Content = new StringContent(ex.Message);

                serviceLog.RunStatus = RunStatus.Error;
                serviceLog.Error = ex.Message;
                db.SaveChanges();

                return response;
            }

            // read the file with json extension to a string - uebPackageBuildRequestJson
            string[] jsonFiles = Directory.GetFiles(_clientPackageRequestDirPath, "*.json");
            if (jsonFiles.Length != 1)
            {
                string errMsg = "Either no json file was found in the package request or there are multiple json files";
                logger.Error(errMsg);
                response.StatusCode = HttpStatusCode.BadRequest;
                response.Content = new StringContent(errMsg);

                serviceLog.RunStatus = RunStatus.Error;
                serviceLog.Error = errMsg;
                db.SaveChanges();

                return response;
            }

            using (var fileReader = new StreamReader(jsonFiles[0]))
            {
                uebPackageBuildRequestJson = fileReader.ReadToEnd();
            }

            UEB.UEBPackageRequest pkgRequest;
            try
            {
                pkgRequest = JsonConvert.DeserializeObject<UEB.UEBPackageRequest>(uebPackageBuildRequestJson);
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);
                response.StatusCode = HttpStatusCode.BadRequest;
                response.Content = new StringContent(ex.Message);

                serviceLog.RunStatus = RunStatus.Error;
                serviceLog.Error = ex.Message;
                db.SaveChanges();

                return response;
            }

            // check if the client request is valid
            string validationResult = ValidateUEBPackageRequest(pkgRequest);
            if (string.IsNullOrEmpty(validationResult) == false)
            {
                logger.Error(validationResult);
                response.StatusCode = HttpStatusCode.BadRequest;
                response.Content = new StringContent(validationResult);

                serviceLog.RunStatus = RunStatus.Error;
                serviceLog.Error = validationResult;
                db.SaveChanges();

                return response;
            }

            // if the domain file is a shape file, extract the domain zip file to the root processing dir path
            string domainFile = Path.Combine(_clientPackageRequestDirPath, pkgRequest.DomainFileName);

            if (Path.GetExtension(domainFile) == ".zip")
            {
                // unzip the domain shape zip file
                ZipFile.ExtractToDirectory(domainFile, _packageRequestProcessRootDirPath);
            }

            // copy all the files with extensions (.dat, .nc) that came with the client uebpackagerequest zip file
            // to the package root processing folder
            string[] files = Directory.GetFiles(_clientPackageRequestDirPath);
            string fileName = string.Empty;
            string destFile = string.Empty;

            foreach (string file in files)
            {
                if (Path.GetExtension(file) == ".nc" || Path.GetExtension(file) == ".dat")
                {
                    // Use static Path methods to extract only the file name from the path.
                    fileName = Path.GetFileName(file);
                    destFile = Path.Combine(_packageRequestProcessRootDirPath, fileName);

                    // Copy the file and overwrite destination file if they already exist.
                    File.Copy(file, destFile, true);
                }
            }

            PackageCreationStatus pkgStatus = new PackageCreationStatus();
            pkgStatus.Message = "UEB package build request is now in a job queue.";
            pkgStatus.PackageID = jobGuid.ToString();
            string jsonResponse = JsonConvert.SerializeObject(pkgStatus, Formatting.Indented);
            response.StatusCode = HttpStatusCode.OK;
            response.Content = new StringContent(jsonResponse);

            //PK:2/11/2014 (Added): start the package build process  - this would start the package build process for this request
            // if no other requests are in queue. Othewise it will start the build process for the build request that
            // has been in queue for the longest time (first-in and first-out principle)
            PackageBuilder uebPkgBuilder = new PackageBuilder();
            int numberOfJobsStarted = uebPkgBuilder.Run();
            logger.Info("Number of queued jobs started:" + numberOfJobsStarted);

            return response;
        }