func main() {
	// Check for a linked MongoDB container if we are running in Docker
	mongoHost := os.Getenv("MONGO_PORT_27017_TCP_ADDR")
	if mongoHost == "" {
		mongoHost = "localhost"
	}
	registerURL := flag.String("registerURL", "", "Register a FHIR Subscription to the specified URL")
	registerENV := flag.String("registerENV", "", "Register a FHIR Subscription to the the Docker environment variable IE_PORT_3001_TCP*")
	flag.Parse()
	parsedURL := *registerURL
	if parsedURL != "" {
		registerServer(parsedURL)
	}
	if registerENV != nil {
		registerServer(fmt.Sprintf("http://%s:%s", os.Getenv("IE_PORT_3001_TCP_ADDR"), os.Getenv("IE_PORT_3001_TCP_PORT")))
	}

	e := echo.New()
	session, err := mgo.Dial(mongoHost)
	if err != nil {
		panic("Can't connect to the database")
	}
	defer session.Close()

	basePieURL := discoverSelf() + "pies"
	db := session.DB("riskservice")
	svc := service.NewReferenceRiskService(db)
	svc.RegisterPlugin(assessments.NewCHA2DS2VAScPlugin())
	svc.RegisterPlugin(assessments.NewSimplePlugin())
	fnDelayer := server.NewFunctionDelayer(3 * time.Second)
	server.RegisterRoutes(e, db, basePieURL, svc, fnDelayer)
	e.Use(middleware.Logger())
	e.Run(":9000")
}
func (s *ServiceSuite) TestGetRequiredDataQueryURLForCHADS(c *C) {
	s.Service.RegisterPlugin(assessments.NewCHA2DS2VAScPlugin())
	qURL, err := s.Service.getRequiredDataQueryURL("12345", "http://example.org/fhir")
	util.CheckErr(err)
	c.Assert(strings.HasPrefix(qURL, "http://example.org/fhir/Patient?"), Equals, true)
	qURL2, _ := url.Parse(qURL)
	c.Assert(qURL2.Query(), HasLen, 2)
	c.Assert(qURL2.Query().Get("_id"), Equals, "12345")
	c.Assert(qURL2.Query()["_revinclude"], HasLen, 1)
	c.Assert(qURL2.Query().Get("_revinclude"), Equals, "Condition:patient")
}
func (s *ServiceSuite) TestGetRequiredDataQueryURLForCHADSandSimple(c *C) {
	s.Service.RegisterPlugin(assessments.NewCHA2DS2VAScPlugin())
	s.Service.RegisterPlugin(assessments.NewSimplePlugin())
	qURL, err := s.Service.getRequiredDataQueryURL("12345", "http://example.org/fhir")
	util.CheckErr(err)
	c.Assert(strings.HasPrefix(qURL, "http://example.org/fhir/Patient?"), Equals, true)
	qURL2, _ := url.Parse(qURL)
	c.Assert(qURL2.Query()["_revinclude"], HasLen, 2)
	var cFound, mFound bool
	for _, v := range qURL2.Query()["_revinclude"] {
		if v == "Condition:patient" {
			cFound = true
		} else if v == "MedicationStatement:patient" {
			mFound = true
		}
	}
	c.Assert(cFound, Equals, true)
	c.Assert(mFound, Equals, true)
}
func (s *ServiceSuite) TestEndToEndCalculations(c *C) {
	// Get the test data for Chad Chadworth (for the CHADS test -- get it?)
	data, err := os.Open("fixtures/chad_chadworth_bundle.json")
	util.CheckErr(err)
	defer data.Close()

	// Store Chad Chadworth's information to Mongo
	res, err := http.Post(s.Server.URL+"/", "application/json", data)
	util.CheckErr(err)
	defer res.Body.Close()

	// Get the response so we can pull out the patient ID
	decoder := json.NewDecoder(res.Body)
	responseBundle := new(models.Bundle)
	err = decoder.Decode(responseBundle)
	util.CheckErr(err)
	patientID := responseBundle.Entry[0].Resource.(*models.Patient).Id

	// Confirm there are no risk assessments or pies
	raCollection := s.Database.C("riskassessments")
	count, err := raCollection.Count()
	util.CheckErr(err)
	c.Assert(count, Equals, 0)
	piesCollection := s.Database.C("pies")
	count, err = piesCollection.Count()
	util.CheckErr(err)
	c.Assert(count, Equals, 0)

	// Now register the plugins and request the calculation!
	s.Service.RegisterPlugin(assessments.NewCHA2DS2VAScPlugin())
	s.Service.RegisterPlugin(assessments.NewSimplePlugin())

	err = s.Service.Calculate(patientID, s.Server.URL, s.Server.URL+"/pies")
	util.CheckErr(err)

	count, err = raCollection.Find(bson.M{"method.coding.code": "CHADS"}).Count()
	util.CheckErr(err)
	c.Assert(count, Equals, 4)
	count, err = raCollection.Find(bson.M{"method.coding.code": "Simple"}).Count()
	util.CheckErr(err)
	c.Assert(count, Equals, 4)
	count, err = piesCollection.Count()
	util.CheckErr(err)
	c.Assert(count, Equals, 8)

	var ras []models.RiskAssessment
	err = raCollection.Find(bson.M{"method.coding.code": "CHADS"}).Sort("date.time").All(&ras)
	util.CheckErr(err)

	loc := time.FixedZone("-0500", -5*60*60)
	s.checkCHADSRiskAssessment(c, &ras[0], patientID, time.Date(2012, time.September, 20, 8, 0, 0, 0, loc), 1.3, false)
	s.checkCHADSPie(c, &ras[0], patientID, 0, 0, 0, 0, 0, 1, 0)
	s.checkCHADSRiskAssessment(c, &ras[1], patientID, time.Date(2013, time.September, 2, 10, 0, 0, 0, loc), 2.2, false)
	s.checkCHADSPie(c, &ras[1], patientID, 0, 1, 0, 0, 0, 1, 0)
	s.checkCHADSRiskAssessment(c, &ras[2], patientID, time.Date(2014, time.January, 17, 20, 35, 0, 0, loc), 4.0, false)
	s.checkCHADSPie(c, &ras[2], patientID, 0, 1, 0, 2, 0, 1, 0)
	s.checkCHADSRiskAssessment(c, &ras[3], patientID, time.Date(2015, time.September, 2, 0, 0, 0, 0, loc), 6.7, true)
	s.checkCHADSPie(c, &ras[3], patientID, 0, 1, 0, 2, 0, 2, 0)

	ras = nil
	err = raCollection.Find(bson.M{"method.coding.code": "Simple"}).Sort("date.time").All(&ras)
	util.CheckErr(err)

	s.checkSimpleRiskAssessment(c, &ras[0], patientID, time.Date(2012, time.September, 20, 8, 0, 0, 0, loc), 1, false)
	s.checkSimplePie(c, &ras[0], patientID, 1, 0)
	s.checkSimpleRiskAssessment(c, &ras[1], patientID, time.Date(2013, time.September, 2, 10, 0, 0, 0, loc), 3, false)
	s.checkSimplePie(c, &ras[1], patientID, 2, 1)
	s.checkSimpleRiskAssessment(c, &ras[2], patientID, time.Date(2014, time.January, 17, 20, 35, 0, 0, loc), 4, false)
	s.checkSimplePie(c, &ras[2], patientID, 3, 1)
	s.checkSimpleRiskAssessment(c, &ras[3], patientID, time.Date(2014, time.January, 17, 20, 40, 0, 0, loc), 3, true)
	s.checkSimplePie(c, &ras[3], patientID, 2, 1)
}
func (s *ServiceSuite) TestEndToEndCalculationsWithNACHADS(c *C) {
	// Get the test data for Chad Chadworth (for the CHADS test -- get it?)
	data, err := os.Open("fixtures/chad_chadworth_bundle.json")
	util.CheckErr(err)
	defer data.Close()

	// Remove the AFib entry (index 5) so he is Not Applicable
	bundle := new(models.Bundle)
	decoder := json.NewDecoder(data)
	err = decoder.Decode(bundle)
	util.CheckErr(err)
	bundle.Entry = append(bundle.Entry[:5], bundle.Entry[6:]...)
	b, err := json.Marshal(bundle)
	util.CheckErr(err)

	// Store Chad Chadworth's modified information to Mongo
	res, err := http.Post(s.Server.URL+"/", "application/json", bytes.NewBuffer(b))
	util.CheckErr(err)
	defer res.Body.Close()

	// Get the response so we can pull out the patient ID
	decoder = json.NewDecoder(res.Body)
	responseBundle := new(models.Bundle)
	err = decoder.Decode(responseBundle)
	util.CheckErr(err)
	patientID := responseBundle.Entry[0].Resource.(*models.Patient).Id

	// Confirm there are no risk assessments or pies
	raCollection := s.Database.C("riskassessments")
	count, err := raCollection.Count()
	util.CheckErr(err)
	c.Assert(count, Equals, 0)
	piesCollection := s.Database.C("pies")
	count, err = piesCollection.Count()
	util.CheckErr(err)
	c.Assert(count, Equals, 0)

	// Now register the plugins and request the calculation!
	s.Service.RegisterPlugin(assessments.NewCHA2DS2VAScPlugin())
	s.Service.RegisterPlugin(assessments.NewSimplePlugin())

	err = s.Service.Calculate(patientID, s.Server.URL, s.Server.URL+"/pies")
	util.CheckErr(err)

	count, err = raCollection.Find(bson.M{"method.coding.code": "CHADS"}).Count()
	util.CheckErr(err)
	c.Assert(count, Equals, 1)
	count, err = raCollection.Find(bson.M{"method.coding.code": "Simple"}).Count()
	util.CheckErr(err)
	c.Assert(count, Equals, 4)
	count, err = piesCollection.Count()
	util.CheckErr(err)
	c.Assert(count, Equals, 4)

	var ras []models.RiskAssessment
	err = raCollection.Find(bson.M{"method.coding.code": "CHADS"}).All(&ras)
	util.CheckErr(err)

	// Check that the CHADS is not applicable
	c.Assert(ras, HasLen, 1)
	ra := ras[0]
	c.Assert(ra.Subject.Reference, Equals, "Patient/"+patientID)
	c.Assert(ra.Method.MatchesCode("http://interventionengine.org/risk-assessments", "CHADS"), Equals, true)
	c.Assert(time.Now().Sub(ra.Date.Time) < time.Minute, Equals, true)
	c.Assert(ra.Prediction, HasLen, 1)
	c.Assert(ra.Prediction[0].Outcome.Text, Equals, "Stroke")
	c.Assert(ra.Prediction[0].ProbabilityCodeableConcept.Coding, HasLen, 1)
	c.Assert(ra.Prediction[0].ProbabilityCodeableConcept.Coding[0].System, Equals, "http://snomed.info/sct")
	c.Assert(ra.Prediction[0].ProbabilityCodeableConcept.Coding[0].Code, Equals, "385432009")
	c.Assert(ra.Prediction[0].ProbabilityCodeableConcept.Text, Equals, "Not applicable")
	c.Assert(ra.Basis, HasLen, 0)
	c.Assert(ra.Meta.Tag, HasLen, 1)
	c.Assert(ra.Meta.Tag[0], DeepEquals, models.Coding{System: "http://interventionengine.org/tags/", Code: "MOST_RECENT"})

	// Simple should still be good
	ras = nil
	err = raCollection.Find(bson.M{"method.coding.code": "Simple"}).Sort("date.time").All(&ras)
	util.CheckErr(err)

	loc := time.FixedZone("-0500", -5*60*60)
	s.checkSimpleRiskAssessment(c, &ras[0], patientID, time.Date(2012, time.September, 20, 8, 0, 0, 0, loc), 1, false)
	s.checkSimplePie(c, &ras[0], patientID, 1, 0)
	s.checkSimpleRiskAssessment(c, &ras[1], patientID, time.Date(2013, time.September, 2, 10, 0, 0, 0, loc), 3, false)
	s.checkSimplePie(c, &ras[1], patientID, 2, 1)
	s.checkSimpleRiskAssessment(c, &ras[2], patientID, time.Date(2014, time.January, 17, 20, 35, 0, 0, loc), 4, false)
	s.checkSimplePie(c, &ras[2], patientID, 3, 1)
	s.checkSimpleRiskAssessment(c, &ras[3], patientID, time.Date(2014, time.January, 17, 20, 40, 0, 0, loc), 3, true)
	s.checkSimplePie(c, &ras[3], patientID, 2, 1)
}