<?php

namespace Osinet\ClassGrapher;

/**
 * Representation of an "interface" symbol in source code.
 */
class InterfaceInstance {
  const ORIGIN_UNKNOWN = NULL;
  const ORIGIN_PHP = 'php';
  const ORIGIN_EXTENSION = 'extension';
  const ORIGIN_SCRIPT = 'script';

  /**
   * Was instance created just because it was referenced by another symbol ?
   *
   * @var int
   *   0 (No) or 1 (Yes)
   */
  public $implicit;

  /**
   * Origin of symbol. Use the self::ORIGIN_* constants.
   *
   * @var int
   */
  public $origin;

  /**
   * @var Logger
   */
  public $logger = NULL;

  public $name = '(none)';
  public $parent = NULL;

  /**
   * @param \PGPClass $symbol
   *   The interface symbole from grammar_parser.
   * @param int $implicit
   * @param Logger $logger
   *
   * @throws \Exception
   */
  public function __construct(\PGPClass $symbol, $implicit = 0, Logger $logger = NULL) {
    $this->implicit = $implicit;
    $this->logger = $logger;
    $this->name = $symbol->name;
    $this->parent = reset($symbol->extends);
    if (empty($this->logger)) {
      throw new \Exception('No logger in constructor.\n');
    }
    $this->origin = $this->getSymbolOrigin($symbol);
  }

  /**
   * Shortcut for logger->message().
   *
   * @param string $message
   * @param int $level
   */
  public function debug($message, $level = LOG_INFO) {
    $this->logger->legacyLog($message, $level);
  }

  public function getSymbolOrigin() {
    $ret = self::ORIGIN_UNKNOWN;
    try {
      $r = new \ReflectionClass($this->name);
      $this->debug("$this->name is introspectable.\n");
    } catch (\ReflectionException $e) {
      $this->debug("{$this->name} is userland, unshared with parser.\n");
      $ret = self::ORIGIN_SCRIPT;
    }

    if (!isset($ret)) {
      $extension = $r->getExtensionName();
      if ($extension === FALSE) {
        $ret = self::ORIGIN_SCRIPT;
      }
      else {
        $this->implicit = 0;
        $ret = ($extension == 'Core')
          ? self::ORIGIN_PHP
          : self::ORIGIN_EXTENSION . ':' . $extension;
      }
    }
    return $ret;
  }

  public function basicAttributes() {
    $ret = array(
      'shape' => 'box',
      'style' => 'rounded',
    );
    return $ret;
  }

  public function attributes() {
    $ret = $this->basicAttributes();
    if ($this->implicit) {
      $ret['style'] = 'filled';
      $ret['fillcolor'] = '#e0e0e0';
    }
    if ($this->origin != self::ORIGIN_SCRIPT) {
      $ret['label'] = $this->name ."\n". $this->origin;
    }
    return $ret;
  }
}