// Licensed to 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. Apache Software Foundation (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 core

import (
	"math"
	"sync"
	"time"

	"github.com/apache/skywalking-go/plugins/core/reporter"

	commonv3 "skywalking.apache.org/repo/goapi/collect/common/v3"
	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
)

type DefaultSpan struct {
	Refs          []reporter.SpanContext
	tracer        *Tracer
	StartTime     time.Time
	EndTime       time.Time
	OperationName string
	Peer          string
	Layer         agentv3.SpanLayer
	ComponentID   int32
	Tags          []*commonv3.KeyStringValuePair
	Logs          []*agentv3.Log
	IsError       bool
	SpanType      SpanType
	Parent        TracingSpan

	InAsyncMode       bool
	AsyncModeFinished bool
	AsyncOpLocker     *sync.Mutex
}

func NewDefaultSpan(tracer *Tracer, parent TracingSpan) *DefaultSpan {
	return &DefaultSpan{
		tracer:    tracer,
		StartTime: time.Now(),
		SpanType:  SpanTypeLocal,
		Parent:    parent,
	}
}

// For TracingSpan
func (ds *DefaultSpan) SetOperationName(name string) {
	if ds.InAsyncMode {
		ds.AsyncOpLocker.Lock()
		defer ds.AsyncOpLocker.Unlock()
	}
	ds.OperationName = name
}

func (ds *DefaultSpan) GetOperationName() string {
	return ds.OperationName
}

func (ds *DefaultSpan) SetPeer(peer string) {
	if ds.InAsyncMode {
		ds.AsyncOpLocker.Lock()
		defer ds.AsyncOpLocker.Unlock()
	}
	ds.Peer = peer
}

func (ds *DefaultSpan) GetPeer() string {
	return ds.Peer
}

func (ds *DefaultSpan) SetSpanLayer(layer int32) {
	if ds.InAsyncMode {
		ds.AsyncOpLocker.Lock()
		defer ds.AsyncOpLocker.Unlock()
	}
	ds.Layer = agentv3.SpanLayer(layer)
}

func (ds *DefaultSpan) GetSpanLayer() agentv3.SpanLayer {
	return ds.Layer
}

func (ds *DefaultSpan) SetComponent(componentID int32) {
	if ds.InAsyncMode {
		ds.AsyncOpLocker.Lock()
		defer ds.AsyncOpLocker.Unlock()
	}
	ds.ComponentID = componentID
}

func (ds *DefaultSpan) GetComponent() int32 {
	return ds.ComponentID
}

func (ds *DefaultSpan) Tag(key, value string) {
	if ds.InAsyncMode {
		ds.AsyncOpLocker.Lock()
		defer ds.AsyncOpLocker.Unlock()
	}
	for _, tag := range ds.Tags {
		if tag.Key == key {
			tag.Value = value
			return
		}
	}
	ds.Tags = append(ds.Tags, &commonv3.KeyStringValuePair{Key: key, Value: value})
}

func (ds *DefaultSpan) Log(ll ...string) {
	if ds.InAsyncMode {
		ds.AsyncOpLocker.Lock()
		defer ds.AsyncOpLocker.Unlock()
	}
	data := make([]*commonv3.KeyStringValuePair, 0, int32(math.Ceil(float64(len(ll))/2.0)))
	var kvp *commonv3.KeyStringValuePair
	for i, l := range ll {
		if i%2 == 0 {
			kvp = &commonv3.KeyStringValuePair{}
			data = append(data, kvp)
			kvp.Key = l
		} else if kvp != nil {
			kvp.Value = l
		}
	}
	ds.Logs = append(ds.Logs, &agentv3.Log{Time: Millisecond(time.Now()), Data: data})
}

func (ds *DefaultSpan) Error(ll ...string) {
	if ds.InAsyncMode {
		ds.AsyncOpLocker.Lock()
		defer ds.AsyncOpLocker.Unlock()
	}
	ds.IsError = true
	ds.Log(ll...)
}

func (ds *DefaultSpan) End(changeParent bool) {
	ds.EndTime = time.Now()
	if changeParent {
		if ctx := getTracingContext(); ctx != nil {
			ctx.SaveActiveSpan(ds.Parent)
		}
	}
}

func (ds *DefaultSpan) IsEntry() bool {
	return ds.SpanType == SpanTypeEntry
}

func (ds *DefaultSpan) IsExit() bool {
	return ds.SpanType == SpanTypeExit
}

func (ds *DefaultSpan) IsValid() bool {
	return ds.EndTime.IsZero()
}

func (ds *DefaultSpan) ParentSpan() TracingSpan {
	return ds.Parent
}

func (ds *DefaultSpan) PrepareAsync() {
	if ds.InAsyncMode {
		panic("already in async mode")
	}
	ds.InAsyncMode = true
	ds.AsyncModeFinished = false
	ds.AsyncOpLocker = &sync.Mutex{}
}

func (ds *DefaultSpan) AsyncFinish() {
	if !ds.InAsyncMode {
		panic("not in async mode")
	}
	if ds.AsyncModeFinished {
		panic("already finished async")
	}
	ds.AsyncModeFinished = true
	ds.AsyncOpLocker = nil
}
