<?php

namespace EesyPHP;

/**
 * Internal Sentry Span object implementation
 * This internal implementation principally permit to keep trace of new span parent
 * and list of started spans.
 */
class SentrySpan {

    /**
     * Keep trace of started Sentry spans
     * @var array<int,mixed>
     */
    private static $_started_spans = array();

    /**
     * The unique ID of the Sentry span
     * Note: internal ID used as key in self::$_started_spans
     * @var int|null
     */
    private $id = null;

    /**
     * The parent of the Sentry span
     * @var mixed
     */
    private $parent = null;

    /**
     * The context of the Sentry span
     * @var null|\Sentry\Tracing\SpanContext
     */
    private $context = null;

    /**
     * The Sentry span object
     * @var mixed
     */
    private $span = null;

    /**
     * Sentry span constructor
     * @param string|null $op The operation name
     * @param string|null $name The span name
     * @return void
     */
    public function __construct($op, $name) {
        // In phpstan context, do not initialize
        // @phpstan-ignore-next-line
        if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__'))
          return;
        $this -> parent = \Sentry\SentrySdk::getCurrentHub()->getSpan();
        // Check if we have a parent span (this is the case if we started a transaction earlier)
        if (is_null($this -> parent)) return;

        while (is_null($this -> id)) {
            $this -> id = rand();
            if (isset(self :: $_started_spans[$this -> id]))
                $this -> id = null;
        }
        $this -> context = new \Sentry\Tracing\SpanContext();
        $this -> context->setOp($op);
        $this -> context->setDescription($name);
        $this -> span = $this->parent->startChild($this -> context);

        // Set the current span to the span we just started
        \Sentry\SentrySdk::getCurrentHub()->setSpan($this -> span);

        self :: $_started_spans[$this -> id] = $this;
    }

    /**
     * Finish the span (if started)
     * @return void
     */
    public function finish() {
        if (!$this -> span) return;
        $this -> span -> finish();
        unset(self::$_started_spans[$this -> id]);
        \Sentry\SentrySdk::getCurrentHub()->setSpan($this -> parent);
    }

    /**
     * Finish all started spans
     * @see SentryTransaction::__destruct()
     * @return void
     */
    public static function finishAll() {
        foreach (array_reverse(self :: $_started_spans) as $id => $span)
            $span -> finish();
    }
}

# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab
