/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package skywalking

import (
	"context"
	"fmt"
	"github.com/apache/servicecomb-mesher/proxy/config"
	gcconfig "github.com/go-chassis/go-chassis/v2/core/config"
	"github.com/go-chassis/go-chassis/v2/core/invocation"
	"github.com/go-chassis/openlog"
	"github.com/tetratelabs/go2sky"
	"github.com/tetratelabs/go2sky/reporter"
)

const (
	CrossProcessProtocolV2 = "Sw6"
	SkyWalkingConsumer     = "skywalking-consumer"
	SkyWalkingProvider     = "skywalking-provider"
	SkyWalkingName         = "skywalking"
	DeafaultSWServerURI    = "127.0.0.1:11800"
)

var r go2sky.Reporter
var tracer *go2sky.Tracer

//CreateEntrySpan use tracer to create and start an entry span for incoming request
func CreateEntrySpan(i *invocation.Invocation) (go2sky.Span, context.Context, error) {
	return tracer.CreateEntrySpan(i.Ctx, i.MicroServiceName+i.URLPathFormat, func() (string, error) {
		return i.Headers()[CrossProcessProtocolV2], nil
	})
}

//CreateExitSpan use tracer to create and start an exit span for client
func CreateExitSpan(ctx context.Context, i *invocation.Invocation) (go2sky.Span, error) {
	return tracer.CreateExitSpan(ctx, i.MicroServiceName+i.URLPathFormat, i.Endpoint+i.URLPathFormat, func(header string) error {
		i.SetHeader(CrossProcessProtocolV2, header)
		return nil
	})
}

//CreateLocalSpan use tracer to create and start a span for local usage
func CreateLocalSpan(ctx context.Context, opts ...go2sky.SpanOption) (go2sky.Span, context.Context, error) {
	return tracer.CreateLocalSpan(ctx, opts...)
}

//Init skywalking manager
func Init() {
	openlog.Debug(fmt.Sprintf("SkyWalking manager Init begin config:%#v", config.GetConfig().ServiceComb.APM))
	var err error
	serverURI := DeafaultSWServerURI
	if config.GetConfig().ServiceComb.APM.Tracing.ServerURI != "" && config.GetConfig().ServiceComb.APM.Tracing.Enable {
		serverURI = config.GetConfig().ServiceComb.APM.Tracing.ServerURI
	}
	r, err = reporter.NewGRPCReporter(serverURI)
	if err != nil {
		openlog.Error(fmt.Sprintf("NewGRPCReporter error:%s ", err.Error()))
	}
	tracer, err = go2sky.NewTracer(gcconfig.MicroserviceDefinition.Name, go2sky.WithReporter(r))
	if err != nil {
		openlog.Error(fmt.Sprintf("NewTracer error " + err.Error()))
	}
	//tracer.WaitUntilRegister()
	openlog.Debug(fmt.Sprintf("SkyWalking manager Init end"))
}
