/*
Wraps the RoundTrip function of the given RoundTripper.
Will provide accounting metrics for the http.Request / http.Response life-cycle
Callers of RoundTrip are responsible for setting the ‘X-CF-RequestID’ field in the request header if they have one.
Callers are also responsible for setting the ‘X-CF-ApplicationID’ and ‘X-CF-InstanceIndex’ fields in the request header if they are known.
*/
func (irt *instrumentedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	requestId, err := GenerateUuid()
	if err != nil {
		log.Printf("failed to generated request ID: %v\n", err)
		requestId = &uuid.UUID{}
	}

	startTime := time.Now()
	parentRequestId := req.Header.Get("X-CF-RequestID")
	req.Header.Set("X-CF-RequestID", requestId.String())

	resp, roundTripErr := irt.roundTripper.RoundTrip(req)

	var statusCode int
	var contentLength int64
	if roundTripErr == nil {
		statusCode = resp.StatusCode
		contentLength = resp.ContentLength
	}

	httpStartStop := factories.NewHttpStartStop(req, statusCode, contentLength, events.PeerType_Client, requestId)
	if parentRequestId != "" {
		if id, err := uuid.ParseHex(parentRequestId); err == nil {
			httpStartStop.ParentRequestId = factories.NewUUID(id)
		}
	}
	httpStartStop.StartTimestamp = proto.Int64(startTime.UnixNano())

	err = irt.emitter.Emit(httpStartStop)
	if err != nil {
		log.Printf("failed to emit startstop event: %v\n", err)
	}

	return resp, roundTripErr
}
/*
Wraps the given http.Handler ServerHTTP function
Will provide accounting metrics for the http.Request / http.Response life-cycle
*/
func (ih *instrumentedHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	requestId, err := uuid.ParseHex(req.Header.Get("X-Vcap-Request-Id"))
	if err != nil {
		requestId, err = GenerateUuid()
		if err != nil {
			log.Printf("failed to generated request ID: %v\n", err)
			requestId = &uuid.UUID{}
		}
		req.Header.Set("X-Vcap-Request-Id", requestId.String())
	}
	rw.Header().Set("X-Vcap-Request-Id", requestId.String())

	startTime := time.Now()

	instrumentedWriter := &instrumentedResponseWriter{writer: rw, statusCode: 200}
	ih.handler.ServeHTTP(instrumentedWriter, req)

	startStopEvent := factories.NewHttpStartStop(req, instrumentedWriter.statusCode, instrumentedWriter.contentLength, events.PeerType_Server, requestId)
	startStopEvent.StartTimestamp = proto.Int64(startTime.UnixNano())

	err = ih.emitter.Emit(startStopEvent)
	if err != nil {
		log.Printf("failed to emit startstop event: %v\n", err)
	}
}
func createEnvelope(eventType events.Envelope_EventType) *events.Envelope {
	envelope := &events.Envelope{Origin: proto.String("origin"), EventType: &eventType, Timestamp: proto.Int64(time.Now().UnixNano())}

	switch eventType {
	case events.Envelope_HttpStartStop:
		req, _ := http.NewRequest("GET", "http://www.example.com", nil)
		req.RemoteAddr = "www.example.com"
		req.Header.Add("User-Agent", "user-agent")
		uuid, _ := uuid.NewV4()
		envelope.HttpStartStop = factories.NewHttpStartStop(req, http.StatusOK, 128, events.PeerType_Client, uuid)
	case events.Envelope_ValueMetric:
		envelope.ValueMetric = factories.NewValueMetric("some-value-metric", 123, "km")
	case events.Envelope_CounterEvent:
		envelope.CounterEvent = factories.NewCounterEvent("some-counter-event", 123)
	case events.Envelope_LogMessage:
		envelope.LogMessage = factories.NewLogMessage(events.LogMessage_OUT, "some message", "appId", "source")
	case events.Envelope_ContainerMetric:
		envelope.ContainerMetric = factories.NewContainerMetric("appID", 123, 1, 5, 5)
	case events.Envelope_Error:
		envelope.Error = factories.NewError("source", 123, "message")
	default:
		panic(fmt.Sprintf("Unknown event %v\n", eventType))
	}

	return envelope
}
/*
RoundTrip wraps the RoundTrip function of the given RoundTripper.
Will provide accounting metrics for the http.Request / http.Response life-cycle
Callers of RoundTrip are responsible for setting the ‘X-Vcap-Request-Id’ field in the request header if they have one.
Callers are also responsible for setting the ‘X-CF-ApplicationID’ and ‘X-CF-InstanceIndex’ fields in the request header if they are known.
*/
func (irt *instrumentedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	startTime := time.Now()
	requestId := req.Header.Get("X-Vcap-Request-Id")
	if requestId == "" {
		requestIdGuid, err := uuid.NewV4()
		if err != nil {
			return nil, err
		}
		requestId = requestIdGuid.String()
	}

	req.Header.Set("X-Vcap-Request-Id", requestId)

	resp, roundTripErr := irt.roundTripper.RoundTrip(req)

	var statusCode int
	var contentLength int64
	if roundTripErr == nil {
		statusCode = resp.StatusCode
		contentLength = resp.ContentLength
	}

	id, err := uuid.ParseHex(requestId)
	if err != nil {
		return nil, err
	}

	httpStartStop := factories.NewHttpStartStop(req, statusCode, contentLength, events.PeerType_Client, id)
	httpStartStop.StartTimestamp = proto.Int64(startTime.UnixNano())

	err = irt.emitter.Emit(httpStartStop)
	if err != nil {
		log.Printf("failed to emit startstop event: %v\n", err)
	}

	return resp, roundTripErr
}