private Response processRequest(DynamicDictionary parameters, RequestDetails requestDetails, 
            Func<DataModel, DataModel> dataStorageDelegate, Func<DataModel, RequestDetails, Response> responseDelegate)
        {
            var reqDataModel = new DataModel() { Path = Request.Url };
            var response = new Response();

            //If request have parameters - construct the Path and jsonQuery for the Model (i.e. "/movies/{id}")
            if (requestDetails.Parameters != null && requestDetails.Parameters.Any())
            {
                string lastParName = requestDetails.Parameters.Last();                                  //we are assuming that the last parameter in request path is an "id" 
                string lastParValue = parameters[lastParName].Value;                                    //and we can use this parameter name and value to compose json filter for our dataStorage        

                reqDataModel.Path = reqDataModel.Path.Remove(reqDataModel.Path.Length - lastParValue.Length);                     //remove last parameter value from the "/movies/101" => "/movies/", where 101 is some "id"
                reqDataModel.jsonQuery = $"{{\"{lastParName}\":\"{lastParValue}\"}}";                                             // {"lastParameterName":"lastParameterValue"}
            }

            
            JObject reqBobyJsonObj = null;
            string reqBodyJsonStr = Request.Body.AsString();

            //if request body contains Json - we need to validate (try to parse) this Json first
            if (!String.IsNullOrEmpty(reqBodyJsonStr))
            {
                try
                {
                    reqBobyJsonObj = JObject.Parse(reqBodyJsonStr);
                }
                catch (Exception ex)
                {
                    logger.Error($"Incorrect JSON in {requestDetails.Verb.ToUpper()} request!");
                    logger.Error(ex);

                    response = "Bad Request";
                    response.StatusCode = HttpStatusCode.BadRequest;
                    return response;                                        
                }            
            }

            //If request have an associated schema - we need to validate received Json (from request body) with this schema
            if (!String.IsNullOrEmpty(requestDetails.Schema)) { 
                JSchema jsonSchema = JSchema.Parse(requestDetails.Schema);
                if (!reqBobyJsonObj?.IsValid(jsonSchema) ?? true)
                {
                    logger.Error($"JSON in {requestDetails.Verb.ToUpper()} request does not match the RAML schema!!!");
                    response.StatusCode = HttpStatusCode.UnprocessableEntity;
                    return response;
                }
            }

            reqDataModel.jsonModel = reqBodyJsonStr;
            var resultingDataModel = dataStorageDelegate(reqDataModel);
            response = responseDelegate(resultingDataModel, requestDetails);
                
            return response;
        }
        public IList<DataModel> GetMany(DataModel model)    //TO DO
        {
            var records = getMongoCollection(model).Find(model.getOrFilter()).ToList();

            List<DataModel> result = new List<DataModel>();
            foreach (var record in records)
            {
                record.Remove("_id");
                result.Add(new DataModel() { jsonModel = record.ToJson(new JsonWriterSettings { OutputMode = JsonOutputMode.Strict }), operationSuccesfull = true });
            }

            return result.AsReadOnly();
        }
        public DataModel Get(DataModel model)
        {
            var resultModel = new DataModel() { operationSuccesfull = false };

            var record = GetBsonDoc(model);
            if (record != null)
            {
                record.Remove("_id");
                resultModel.jsonModel = record.ToJson(new JsonWriterSettings { OutputMode = JsonOutputMode.Strict});
                resultModel.operationSuccesfull = true;
            }

            return resultModel;
        }
        private Response processResp(DataModel resultModel, RequestDetails requestDetails)
        {
            var response = new Response();
            if (resultModel.operationSuccesfull)
            {
                response.StatusCode = (HttpStatusCode)requestDetails.SuccessResponseCode;

                if (!String.IsNullOrEmpty(resultModel.jsonModel))
                {
                    response = resultModel.jsonModel;
                    response.ContentType = "application/json";
                }
            }
            else
            {
                response.StatusCode = HttpStatusCode.NotFound;
            };

            return response;
        }
        public DataModel Update(DataModel model)
        {
            var resultModel = new DataModel() { operationSuccesfull = false };

            var originalDoc = GetBsonDoc(model);
            if (originalDoc != null)
            {
                var replacementDoc = originalDoc.Merge(model.getBsonModel(), true);
                var replacementResult = getMongoCollection(model).ReplaceOne(model.getOrFilter(), replacementDoc);
                
                if (replacementResult.ModifiedCount == 1)
                {
                    resultModel.operationSuccesfull = true;
                    replacementDoc.Remove("_id");
                    resultModel.jsonModel = replacementDoc.ToJson(new JsonWriterSettings { OutputMode = JsonOutputMode.Strict });
                }

            }

            return resultModel;
        }
        public DataModel Drop(DataModel model)   //TO DO
        {
            database.DropCollection(model.getCollectionName());

            return new DataModel() { operationSuccesfull = true };
        }
        public DataModel Delete(DataModel model)
        {
            var result = getMongoCollection(model).DeleteOne(model.getOrFilter());

            return new DataModel() { operationSuccesfull = (result.DeletedCount == 1) }; 
        }
 /// <summary>
 /// MongoDb -> Find with Filter defined in DataModel and return BsonDocument
 /// </summary>
 private BsonDocument GetBsonDoc(DataModel model) => getMongoCollection(model).Find(model.getOrFilter()).ToList().FirstOrDefault();
        public DataModel Insert(DataModel model)
        {
            getMongoCollection(model).InsertOne(model.getBsonModel());

            return new DataModel() { operationSuccesfull = true , jsonModel = model.jsonModel };
        }
 private IMongoCollection<BsonDocument> getMongoCollection(DataModel model) => database.GetCollection<BsonDocument>(model.getCollectionName());