function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/*
 * Copyright OpenSearch Contributors
 * SPDX-License-Identifier: Apache-2.0
 */

import { TopologyNodePresenter } from '../presenters/topology_node.presenter';

/**
 * A model class that wraps a raw topology node from the SDK and provides
 * convenience methods to access and interpret node data. This class acts as
 * a domain layer between raw API data and application-specific business logic.
 */
export class TopologyNodeModel {
  /**
   * Creates a new TopologyNodeModel instance
   *
   * @param node - The raw topology node data from the SDK
   */
  constructor(node) {
    /** The raw topology node data from the SDK */
    _defineProperty(this, "node", void 0);
    this.node = node;
  }

  /**
   * Gets the unique identifier of the node
   *
   * @returns The node's ID string
   */
  get id() {
    return this.node.NodeId;
  }

  /**
   * Gets the display name of the node
   *
   * @returns The node's name string
   */
  get name() {
    return this.node.Name;
  }

  /**
   * Determines if this node represents a service group rather than an individual service
   *
   * @returns True if the node is a service group, false otherwise
   */
  get isGroup() {
    var _this$node$KeyAttribu;
    return ((_this$node$KeyAttribu = this.node.KeyAttributes) === null || _this$node$KeyAttribu === void 0 ? void 0 : _this$node$KeyAttribu.Type) === 'ServiceGroup';
  }

  /**
   * Gets the aggregated node identifier for this node
   *
   * This identifier is used to group related nodes together in aggregated views.
   * It may be null or undefined if the node is not part of an aggregated group.
   *
   * @returns The aggregated node ID string, null, or undefined
   */
  get aggregatedNodeId() {
    return this.node.AggregatedNodeId;
  }

  /**
   * Determines if this node has instrumentation
   *
   * The definition of "instrumented" differs based on whether the node is a group:
   * - For groups: Checks if at least one service in the group is instrumented
   * - For services: Checks if the service itself is instrumented
   *
   * @returns True if the node is instrumented, false otherwise
   */
  get isInstrumented() {
    const attributes = this.node.AttributeMaps;
    if (this.isGroup) {
      // For groups, check if any service in the group is instrumented
      return !!(attributes !== null && attributes !== void 0 && attributes.some(attr => !!(attr !== null && attr !== void 0 && attr.InstrumentedServiceCount) && Number(attr === null || attr === void 0 ? void 0 : attr.InstrumentedServiceCount) > 0));
    }

    // For services, check the instrumentation type directly
    return !!(attributes !== null && attributes !== void 0 && attributes.some(attr => attr.InstrumentationType && attr.InstrumentationType === 'INSTRUMENTED'));
  }

  /**
   * Checks if this node has platform type information
   *
   * @returns True if platform type is available, false otherwise
   */
  get hasPlatformType() {
    var _this$node$AttributeM;
    return !!((_this$node$AttributeM = this.node.AttributeMaps) !== null && _this$node$AttributeM !== void 0 && _this$node$AttributeM.some(attr => !!attr.PlatformType));
  }

  /**
   * Checks if this node has resource type information
   *
   * @returns True if resource type is available, false otherwise
   */
  get hasResourceType() {
    var _this$node$KeyAttribu2;
    return !!((_this$node$KeyAttribu2 = this.node.KeyAttributes) !== null && _this$node$KeyAttribu2 !== void 0 && _this$node$KeyAttribu2.ResourceType);
  }

  /**
   * Gets the platform type of the node
   *
   * @returns The platform type string if available, undefined otherwise
   */
  get platform() {
    var _this$node$AttributeM2;
    return (_this$node$AttributeM2 = this.node.AttributeMaps) === null || _this$node$AttributeM2 === void 0 || (_this$node$AttributeM2 = _this$node$AttributeM2.find(attr => !!attr.PlatformType)) === null || _this$node$AttributeM2 === void 0 ? void 0 : _this$node$AttributeM2.PlatformType;
  }

  /**
   * Determines the type of the node, prioritizing:
   * 1. PlatformType (if available)
   * 2. ResourceType (if available)
   * 3. Falling back to the node's Type property
   *
   * @returns The determined type string for this node
   */
  get type() {
    if (this.hasPlatformType) {
      var _this$node$AttributeM3;
      return (_this$node$AttributeM3 = this.node.AttributeMaps) === null || _this$node$AttributeM3 === void 0 || (_this$node$AttributeM3 = _this$node$AttributeM3.find(attr => !!attr.PlatformType)) === null || _this$node$AttributeM3 === void 0 ? void 0 : _this$node$AttributeM3.PlatformType;
    }
    if (this.hasResourceType) {
      var _this$node$KeyAttribu3;
      return (_this$node$KeyAttribu3 = this.node.KeyAttributes) === null || _this$node$KeyAttribu3 === void 0 ? void 0 : _this$node$KeyAttribu3.ResourceType;
    }
    return this.node.Type;
  }

  /**
   * Calculates the total number of services within this group
   * Combines both instrumented and uninstrumented services
   *
   * @returns The total number of services, or 0 if not applicable (not a group)
   */
  get numberOfServices() {
    var _this$node$AttributeM4, _Object$values$map$re;
    if (!this.isGroup) return 0;

    // Find attribute with service count information
    const attribute = (_this$node$AttributeM4 = this.node.AttributeMaps) === null || _this$node$AttributeM4 === void 0 ? void 0 : _this$node$AttributeM4.find(attr => !!(attr !== null && attr !== void 0 && attr.InstrumentedServiceCount) || !!(attr !== null && attr !== void 0 && attr.UninstrumentedServiceCount));
    if (!attribute) return 0;

    // Sum up all number values in the attribute
    return (_Object$values$map$re = Object.values(attribute).map(Number).reduce((acc, cur) => acc + cur, 0)) !== null && _Object$values$map$re !== void 0 ? _Object$values$map$re : 0;
  }

  /**
   * Gets the number of uninstrumented services within this group
   *
   * @returns The count of uninstrumented services, or 0 if not applicable (not a group)
   */
  get numberOfUninstrumentedServices() {
    var _this$node$AttributeM5, _this$node$AttributeM6;
    if (!this.isGroup) return 0;
    const count = (_this$node$AttributeM5 = (_this$node$AttributeM6 = this.node.AttributeMaps) === null || _this$node$AttributeM6 === void 0 || (_this$node$AttributeM6 = _this$node$AttributeM6.find(attr => !!(attr !== null && attr !== void 0 && attr.UninstrumentedServiceCount))) === null || _this$node$AttributeM6 === void 0 ? void 0 : _this$node$AttributeM6.UninstrumentedServiceCount) !== null && _this$node$AttributeM5 !== void 0 ? _this$node$AttributeM5 : 0;
    return Number(count);
  }

  /**
   * Gets the group type designation for this node
   *
   * @returns The group type string if available, undefined otherwise
   */
  get groupType() {
    return this.node.KeyAttributes.GroupType;
  }

  /**
   * Determines if this is a user-defined custom group
   * Uses the node ID format to identify the source of the group
   *
   * @returns True if this is a custom group defined by a customer, false otherwise
   */
  get isCustomerDefinedGroup() {
    var _this$node$NodeId$spl, _source$split;
    if (!this.isGroup) return false;

    // Parse the nodeId to extract source information
    // eg. group/source:declared/groupType:Team/name:Payment
    const source = (_this$node$NodeId$spl = this.node.NodeId.split('/')) === null || _this$node$NodeId$spl === void 0 ? void 0 : _this$node$NodeId$spl[1];

    // Check if the source indicates this is a declared (customer-defined) group
    return (source === null || source === void 0 || (_source$split = source.split(':')) === null || _source$split === void 0 ? void 0 : _source$split[1]) === 'declared';
  }
  get isDirectService() {
    var _this$node$AttributeM7;
    if (this.isGroup) return true;
    return !((_this$node$AttributeM7 = this.node.AttributeMaps) !== null && _this$node$AttributeM7 !== void 0 && _this$node$AttributeM7.find(attr => (attr === null || attr === void 0 ? void 0 : attr.isDirectService) === 'false'));
  }

  /**
   * Creates a presenter instance for this node model
   * Useful for formatting and transforming model data for display purposes
   *
   * @returns A TopologyNodePresenter instance for this node
   */
  get presenter() {
    return new TopologyNodePresenter(this);
  }
}